Skip to content

Commit 35dbd8d

Browse files
committed
git-artifacts: port to git-for-windows-automation
This ports the git-artifacts.yml CI pipeline over to the git-for-windows-automation repo, where it can also access arm64 runners in the future. The code is mostly the same as in the original git-for-windows/git repo but has a few optimizations to create the build matrix dynamically. Signed-off-by: Dennis Ameling <[email protected]>
1 parent 1d97887 commit 35dbd8d

File tree

3 files changed

+358
-0
lines changed

3 files changed

+358
-0
lines changed

.github/workflows/git-artifacts.yml

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
name: git-artifacts
2+
run-name: Build git-artifacts (${{ inputs.architecture }})
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
artifacts:
8+
description: 'Optionally restrict what artifacts to build (portable, installer, etc.). Separate artifacts with spaces'
9+
required: false
10+
ref:
11+
description: 'Optionally override which branch to build'
12+
required: false
13+
default: main
14+
repository:
15+
description: 'Optionally override from where to fetch the specified ref'
16+
required: false
17+
default: git-for-windows/git
18+
architecture:
19+
type: choice
20+
description: 'Architecture to build'
21+
required: true
22+
options:
23+
- x86_64
24+
- i686
25+
bundle_artifacts_workflow_run_id:
26+
description: 'Workflow run ID from bundle-artifacts pipeline'
27+
required: false
28+
29+
env:
30+
GPG_OPTIONS: "--batch --yes --no-tty --list-options no-show-photos --verify-options no-show-photos --pinentry-mode loopback"
31+
HOME: "${{github.workspace}}\\home"
32+
USERPROFILE: "${{github.workspace}}\\home"
33+
ARTIFACTS_TO_BUILD: "${{github.event.inputs.artifacts}}"
34+
REPOSITORY: "${{github.event.inputs.repository}}"
35+
REF: "${{github.event.inputs.ref}}"
36+
ARCHITECTURE: "${{github.event.inputs.architecture}}"
37+
BUNDLE_ARTIFACTS_WORKFLOW_RUN_ID: "${{github.event.inputs.bundle_artifacts_workflow_run_id}}"
38+
39+
defaults:
40+
run:
41+
shell: bash
42+
43+
jobs:
44+
pkg:
45+
runs-on: windows-latest
46+
outputs:
47+
artifact_matrix: ${{steps.artifact-build-matrix.outputs.matrix}}
48+
msystem: ${{steps.configure-environment.outputs.MSYSTEM}}
49+
mingw_package_prefix: ${{steps.configure-environment.outputs.MINGW_PACKAGE_PREFIX}}
50+
sdk_repo_arch: ${{steps.configure-environment.outputs.SDK_REPO_ARCH}}
51+
steps:
52+
- name: Configure environment
53+
id: configure-environment
54+
run: |
55+
case "$ARCHITECTURE" in
56+
x86_64)
57+
MSYSTEM=MINGW64
58+
MINGW_PREFIX=/mingw64
59+
MINGW_PACKAGE_PREFIX=mingw-w64-x86_64
60+
SDK_REPO_ARCH=64
61+
;;
62+
i686)
63+
MSYSTEM=MINGW32
64+
MINGW_PREFIX=/mingw32
65+
MINGW_PACKAGE_PREFIX=mingw-w64-i686
66+
SDK_REPO_ARCH=32
67+
;;
68+
*)
69+
echo "Unhandled architecture: $ARCHITECTURE"
70+
exit 1
71+
;;
72+
esac
73+
echo "MSYSTEM=$MSYSTEM" >> $GITHUB_ENV
74+
echo "MSYSTEM=$MSYSTEM" >> $GITHUB_OUTPUT
75+
echo "MINGW_PREFIX=$MINGW_PREFIX" >> $GITHUB_ENV
76+
echo "MINGW_PACKAGE_PREFIX=$MINGW_PACKAGE_PREFIX" >> $GITHUB_ENV
77+
echo "MINGW_PACKAGE_PREFIX=$MINGW_PACKAGE_PREFIX" >> $GITHUB_OUTPUT
78+
echo "SDK_REPO_ARCH=$SDK_REPO_ARCH" >> $GITHUB_OUTPUT
79+
echo "ARTIFACTS_TO_BUILD=$(test -n "$ARTIFACTS_TO_BUILD" && echo $ARTIFACTS_TO_BUILD || \
80+
echo "installer portable archive mingit$(test "$ARCHITECTURE" = aarch64 || echo ' mingit-busybox')")" >> $GITHUB_ENV
81+
- name: Configure user
82+
run:
83+
USER_NAME="${{github.actor}}" &&
84+
USER_EMAIL="${{github.actor}}@users.noreply.github.com" &&
85+
mkdir "$HOME" &&
86+
git config --global user.name "$USER_NAME" &&
87+
git config --global user.email "$USER_EMAIL" &&
88+
echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >> $GITHUB_ENV
89+
- uses: git-for-windows/setup-git-for-windows-sdk@v1
90+
with:
91+
flavor: build-installers
92+
architecture: ${{env.architecture}}
93+
- name: clone git-for-windows-automation
94+
run: git clone --single-branch -b $GITHUB_REF_NAME https://github.com/git-for-windows/git-for-windows-automation
95+
- uses: actions/github-script@v6
96+
id: artifact-build-matrix
97+
name: Create artifact build matrix
98+
with:
99+
script: |
100+
core.info('Preparing artifact build matrix...')
101+
const createArtifactsMatrix = require('./git-for-windows-automation/create-artifacts-matrix')
102+
createArtifactsMatrix(core, process.env.ARTIFACTS_TO_BUILD, process.env.ARCHITECTURE)
103+
- uses: actions/github-script@v6
104+
id: get-bundle-artifacts-url
105+
name: Get bundle-artifacts download URL
106+
with:
107+
script: |
108+
const getArtifact = require('./git-for-windows-automation/get-bundle-artifacts-artifact')
109+
const workflowId = process.env.BUNDLE_ARTIFACTS_WORKFLOW_RUN_ID
110+
core.info('Getting download URL for bundle-artifacts...')
111+
await getArtifact(github, context, core, workflowId)
112+
- name: Download bundle-artifacts zip
113+
run: |
114+
mkdir bundle-artifacts
115+
curl -o bundle-artifacts.zip "${{steps.get-bundle-artifacts-url.outputs.downloadUrl}}"
116+
unzip bundle-artifacts.zip -d bundle-artifacts
117+
echo "GIT_VERSION=$(cat bundle-artifacts/next_version)" >> $GITHUB_ENV
118+
- name: Re-publish bundle-artifacts so the next job can easily use it
119+
uses: actions/upload-artifact@v3
120+
with:
121+
name: bundle-artifacts
122+
path: bundle-artifacts
123+
- name: Clone and update build-extra
124+
run: |
125+
d=/usr/src/build-extra &&
126+
if test ! -d $d/.git
127+
then
128+
git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d
129+
else
130+
git -C $d fetch https://github.com/git-for-windows/build-extra main &&
131+
git -C $d switch -C main FETCH_HEAD
132+
fi &&
133+
git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main
134+
- name: Check out git/git
135+
shell: bash
136+
run: |
137+
git -c init.defaultBranch=main init &&
138+
git remote add -f origin https://github.com/git-for-windows/git &&
139+
git fetch --tags bundle-artifacts/git.bundle $(cat bundle-artifacts/next_version) &&
140+
git reset --hard $(cat bundle-artifacts/next_version)
141+
- name: Prepare home directory for code-signing
142+
env:
143+
CODESIGN_P12: ${{secrets.CODESIGN_P12}}
144+
CODESIGN_PASS: ${{secrets.CODESIGN_PASS}}
145+
if: env.CODESIGN_P12 != '' && env.CODESIGN_PASS != ''
146+
run: |
147+
cd home &&
148+
mkdir -p .sig &&
149+
echo -n "$CODESIGN_P12" | tr % '\n' | base64 -d >.sig/codesign.p12 &&
150+
echo -n "$CODESIGN_PASS" >.sig/codesign.pass
151+
git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"'
152+
- name: Prepare home directory for GPG signing
153+
if: env.GPGKEY != ''
154+
run: |
155+
echo '${{secrets.PRIVGPGKEY}}' | tr % '\n' | gpg $GPG_OPTIONS --import &&
156+
info="$(gpg --list-keys --with-colons "${GPGKEY%% *}" | cut -d : -f 1,10 | sed -n '/^uid/{s|uid:||p;q}')" &&
157+
git config --global user.name "${info% <*}" &&
158+
git config --global user.email "<${info#*<}"
159+
env:
160+
GPGKEY: ${{secrets.GPGKEY}}
161+
- name: Cache ${{env.MINGW_PACKAGE_PREFIX}}-git
162+
id: cache-git-pkg
163+
uses: actions/cache@v3
164+
with:
165+
path: artifacts
166+
key: pkg-${{env.GIT_VERSION}}-${{env.ARCHITECTURE}}
167+
- name: Build ${{env.MINGW_PACKAGE_PREFIX}}-git
168+
if: steps.cache-git-pkg.outputs.cache-hit != 'true'
169+
env:
170+
GPGKEY: "${{secrets.GPGKEY}}"
171+
run: |
172+
set -x
173+
BUILD_SRC=$(test x86_64 != "$ARCHITECTURE" || echo "--build-src-pkg")
174+
# Make sure that there is a `/usr/bin/git` that can be used by `makepkg-mingw`
175+
printf '#!/bin/sh\n\nexec '$MINGW_PREFIX'/bin/git.exe "$@"\n' >/usr/bin/git &&
176+
/usr/src/build-extra/please.sh build-mingw-w64-git --only-$ARCHITECTURE $BUILD_SRC -o artifacts HEAD &&
177+
cp bundle-artifacts/ver artifacts/ &&
178+
if test -n "$GPGKEY"
179+
then
180+
for tar in artifacts/*.tar*
181+
do
182+
/usr/src/build-extra/gnupg-with-gpgkey.sh --detach-sign --no-armor $tar
183+
done
184+
fi &&
185+
b=$PWD/artifacts &&
186+
version=$(cat bundle-artifacts/next_version) &&
187+
(cd /usr/src/MINGW-packages/mingw-w64-git &&
188+
cp PKGBUILD.$version PKGBUILD &&
189+
git commit -s -m "mingw-w64-git: new version ($version)" PKGBUILD &&
190+
git bundle create "$b"/MINGW-packages.bundle origin/main..main)
191+
- name: Publish ${{env.MINGW_PACKAGE_PREFIX}}-git
192+
uses: actions/upload-artifact@v3
193+
with:
194+
name: pkg-${{env.ARCHITECTURE}}
195+
path: artifacts
196+
artifacts:
197+
runs-on: windows-latest
198+
needs: pkg
199+
env:
200+
MSYSTEM: ${{ needs.pkg.outputs.msystem }}
201+
MINGW_PACKAGE_PREFIX: ${{ needs.pkg.outputs.mingw_package_prefix }}
202+
SDK_REPO_ARCH: ${{ needs.pkg.outputs.sdk_repo_arch }}
203+
strategy:
204+
fail-fast: false
205+
matrix: ${{ fromJSON(needs.pkg.outputs.artifact_matrix) }}
206+
steps:
207+
- name: Download pkg-${{env.ARCHITECTURE}}
208+
uses: actions/download-artifact@v3
209+
with:
210+
name: pkg-${{env.ARCHITECTURE}}
211+
path: pkg-${{env.ARCHITECTURE}}
212+
- name: Download bundle-artifacts
213+
uses: actions/download-artifact@v3
214+
with:
215+
name: bundle-artifacts
216+
path: bundle-artifacts
217+
- uses: git-for-windows/setup-git-for-windows-sdk@v1
218+
with:
219+
flavor: build-installers
220+
architecture: ${{env.ARCHITECTURE}}
221+
- name: Clone and update build-extra
222+
run: |
223+
d=/usr/src/build-extra &&
224+
if test ! -d $d/.git
225+
then
226+
git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d
227+
else
228+
git -C $d fetch https://github.com/git-for-windows/build-extra main &&
229+
git -C $d switch -C main FETCH_HEAD
230+
fi &&
231+
git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main
232+
- name: Prepare home directory for code-signing
233+
env:
234+
CODESIGN_P12: ${{secrets.CODESIGN_P12}}
235+
CODESIGN_PASS: ${{secrets.CODESIGN_PASS}}
236+
if: (matrix.artifact.name == 'installer' || matrix.artifact.name == 'portable') && env.CODESIGN_P12 != '' && env.CODESIGN_PASS != ''
237+
run: |
238+
mkdir -p home/.sig &&
239+
echo -n "$CODESIGN_P12" | tr % '\n' | base64 -d >home/.sig/codesign.p12 &&
240+
echo -n "$CODESIGN_PASS" >home/.sig/codesign.pass &&
241+
git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"'
242+
- name: Build ${{env.ARCHITECTURE}} ${{matrix.artifact.name}}
243+
run: |
244+
set -x
245+
eval /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=$(cat pkg-${{env.ARCHITECTURE}}/ver) -o artifacts --${{matrix.artifact.name}} --pkg=pkg-${{env.ARCHITECTURE}}/${{env.MINGW_PACKAGE_PREFIX}}-git-[0-9]*.tar.xz --pkg=pkg-${{env.ARCHITECTURE}}/${{env.MINGW_PACKAGE_PREFIX}}-git-doc-html-[0-9]*.tar.xz &&
246+
if test portable = '${{matrix.artifact.name}}' && test -n "$(git config alias.signtool)"
247+
then
248+
git signtool artifacts/PortableGit-*.exe
249+
fi &&
250+
openssl dgst -sha256 artifacts/${{matrix.artifact.fileprefix}}-*.${{matrix.artifact.fileextension}} | sed "s/.* //" >artifacts/sha-256.txt
251+
- name: Copy package-versions and pdbs
252+
if: matrix.artifact.name == 'installer'
253+
run: |
254+
cp /usr/src/build-extra/installer/package-versions.txt artifacts/ &&
255+
a=$PWD/artifacts &&
256+
p=$PWD/pkg-${{env.ARCHITECTURE}} &&
257+
(cd /usr/src/build-extra &&
258+
mkdir -p cached-source-packages &&
259+
cp "$p"/*-pdb* cached-source-packages/ &&
260+
GIT_CONFIG_PARAMETERS="'windows.sdk${{env.SDK_REPO_ARCH}}.path='" ./please.sh bundle_pdbs --arch=${{env.ARCHITECTURE}} --directory="$a" installer/package-versions.txt)
261+
- name: Publish ${{matrix.artifact.name}}-${{env.ARCHITECTURE}}
262+
uses: actions/upload-artifact@v3
263+
with:
264+
name: ${{matrix.artifact.name}}-${{env.ARCHITECTURE}}
265+
path: artifacts

create-artifacts-matrix.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
module.exports = (core, artifactsString, architecture) => {
2+
const artifacts = artifactsString.split(' ')
3+
4+
if (artifacts.length < 1) {
5+
core.setFailed('No artifacts provided. Provide in a space-separated string, e.g. "installer portable"')
6+
return
7+
}
8+
9+
const validArtifacts = [
10+
{
11+
name: 'installer',
12+
filePrefix: 'Git',
13+
fileExtension: 'exe'
14+
},
15+
{
16+
name: 'portable',
17+
filePrefix: 'PortableGit',
18+
fileExtension: 'exe'
19+
},
20+
{
21+
name: 'archive',
22+
filePrefix: 'Git',
23+
fileExtension: 'tar.bz2'
24+
},
25+
{
26+
name: 'mingit',
27+
filePrefix: 'MinGit',
28+
fileExtension: 'zip'
29+
},
30+
architecture !== 'aarch64' && {
31+
name: 'mingit-busybox',
32+
filePrefix: 'MinGit',
33+
fileExtension: 'zip'
34+
}
35+
]
36+
37+
const artifactsToBuild = []
38+
39+
for (const artifact of artifacts) {
40+
const artifactObject = validArtifacts.find(a => a.name === artifact)
41+
if (!artifactObject) {
42+
core.setFailed(`${artifact} is not a valid artifact for ${architecture}`)
43+
return
44+
}
45+
46+
artifactsToBuild.push(artifactObject)
47+
}
48+
49+
const output = {artifact: artifactsToBuild}
50+
51+
core.info(`Will be using the following matrix: ${JSON.stringify(output)}`)
52+
core.setOutput('matrix', output)
53+
}

get-bundle-artifacts-artifact.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
module.exports = async (github, context, core, workflowId) => {
2+
const { data } = workflowId
3+
? await github.rest.actions.listWorkflowRunArtifacts({
4+
owner: context.repo.owner,
5+
repo: context.repo.repo,
6+
run_id: Number(workflowId)
7+
}) : await github.rest.actions.listArtifactsForRepo({
8+
owner: context.repo.owner,
9+
repo: context.repo.repo
10+
})
11+
12+
const artifacts = data.artifacts.filter(a => a.name === 'bundle-artifacts')
13+
14+
if (artifacts.length === 0) {
15+
core.setFailed('No artifacts with name bundle-artifacts found')
16+
return
17+
}
18+
19+
const artifact = artifacts[0]
20+
21+
core.info(`Getting downloadUrl for artifact ID ${artifact.id}...`)
22+
23+
// This returns a download URL. The URL expires after 1 minute.
24+
const generateDownloadUrl = await github.rest.actions.downloadArtifact({
25+
owner: context.repo.owner,
26+
repo: context.repo.repo,
27+
artifact_id: artifact.id,
28+
archive_format: 'zip'
29+
})
30+
31+
const downloadUrl = generateDownloadUrl.url
32+
33+
if (!downloadUrl) {
34+
core.setFailed(`Could not get download URL for artifact ${artifact.id}. Output: ${JSON.stringify(generateDownloadUrl)}`)
35+
return
36+
}
37+
38+
core.info(`Successfully got downloadUrl. It expires after 1 minute: ${downloadUrl}`)
39+
core.setOutput('downloadUrl', downloadUrl)
40+
}

0 commit comments

Comments
 (0)