Skip to content

Commit 26f3828

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 ef2667a commit 26f3828

File tree

3 files changed

+351
-0
lines changed

3 files changed

+351
-0
lines changed

.github/workflows/git-artifacts.yml

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