1
+ name : ci-artifacts
2
+
3
+ on :
4
+ push :
5
+ branches :
6
+ - main
7
+ pull_request :
8
+
9
+ # For the continuous `ci-artifacts` release
10
+ permissions :
11
+ contents : write
12
+
13
+ env :
14
+ LC_CTYPE : C.UTF-8
15
+
16
+ jobs :
17
+ minimal-sdk-artifact :
18
+ if : github.event.repository.fork == false
19
+ runs-on : [Windows, ARM64]
20
+ steps :
21
+ - name : clone git-sdk-arm64
22
+ run : |
23
+ git init --bare git-sdk-arm64.git &&
24
+ git --git-dir=git-sdk-arm64.git remote add origin https://github.com/${{github.repository}} &&
25
+ git --git-dir=git-sdk-arm64.git config remote.origin.promisor true &&
26
+ git --git-dir=git-sdk-arm64.git config remote.origin.partialCloneFilter blob:none &&
27
+ git --git-dir=git-sdk-arm64.git fetch --depth=1 origin ${{github.sha}} &&
28
+ git --git-dir=git-sdk-arm64.git update-ref --no-deref HEAD ${{github.sha}}
29
+ - name : clone build-extra
30
+ run : git clone --depth=1 --single-branch -b main https://github.com/git-for-windows/build-extra
31
+ - name : build git-sdk-arm64-minimal-sdk
32
+ shell : bash
33
+ run : |
34
+ sh -x ./build-extra/please.sh create-sdk-artifact --sdk=git-sdk-arm64.git minimal-sdk &&
35
+ cygpath -aw minimal-sdk/usr/bin >>$GITHUB_PATH
36
+ - name : compress artifact
37
+ shell : bash
38
+ run : (cd minimal-sdk && tar cvf - * .[0-9A-Za-z]*) | gzip -1 >git-sdk-aarch64-minimal.tar.gz
39
+ - name : upload minimal-sdk artifact
40
+ uses : actions/upload-artifact@v4
41
+ with :
42
+ name : minimal-sdk
43
+ path : git-sdk-aarch64-minimal.tar.gz
44
+ - name : create zip and 7z SFX variants of the minimal SDK
45
+ if : github.event_name == 'push' && github.ref == 'refs/heads/main'
46
+ shell : bash
47
+ run : |
48
+ for path in clangarm64/bin/7z.exe clangarm64/bin/7z.dll clangarm64/lib/7zip/7zCon.sfx clangarm64/bin/libc++.dll
49
+ do
50
+ git --git-dir=git-sdk-arm64.git show HEAD:$path >${path##*/}
51
+ done &&
52
+ mkdir minimal-sdk-extra &&
53
+ (cd minimal-sdk && ../7z.exe a -mmt=on -mx9 ../minimal-sdk-extra/git-sdk-aarch64-minimal.zip * .?*) &&
54
+ (cd minimal-sdk && ../7z.exe a -t7z -mmt=on -m0=lzma -mqs -mlc=8 -mx=9 -md=256M -mfb=273 -ms=256M -sfx../7zCon.sfx \
55
+ ../minimal-sdk-extra/git-sdk-aarch64-minimal.7z.exe * .?*)
56
+ - name : upload minimal-sdk-extra artifacts
57
+ if : github.event_name == 'push' && github.ref == 'refs/heads/main'
58
+ uses : actions/upload-artifact@v4
59
+ with :
60
+ name : minimal-sdk-extra
61
+ path : minimal-sdk-extra
62
+ assorted-validations :
63
+ runs-on : [Windows, ARM64]
64
+ needs : [minimal-sdk-artifact]
65
+ steps :
66
+ - name : download minimal-sdk artifact
67
+ uses : actions/download-artifact@v4
68
+ with :
69
+ name : minimal-sdk
70
+ path : ${{github.workspace}}
71
+ - name : uncompress minimal-sdk
72
+ shell : bash
73
+ run : |
74
+ mkdir -p minimal-sdk &&
75
+ tar -C minimal-sdk -xzf git-sdk-aarch64-minimal.tar.gz &&
76
+ cygpath -aw minimal-sdk/usr/bin >>$GITHUB_PATH
77
+ - name : run some tests
78
+ shell : bash
79
+ run : |
80
+ set -x
81
+ . /etc/profile
82
+
83
+ # cygpath works
84
+ test "$(cygpath -aw /)" = "${{github.workspace}}\minimal-sdk" || exit 1
85
+
86
+ # comes with Clang and can compile a DLL
87
+ test "$(type -p clang)" = "/clangarm64/bin/clang" || exit 1
88
+ cat >dll.c <<-\EOF &&
89
+ __attribute__((dllexport)) int increment(int i)
90
+ {
91
+ return i + 1;
92
+ }
93
+ EOF
94
+
95
+ clang -Wall -g -O2 -shared -o sample.dll dll.c || exit 1
96
+ ls -la
97
+
98
+ # stat works
99
+ test "stat is /usr/bin/stat" = "$(type stat)" || exit 1
100
+ stat /usr/bin/stat.exe || exit 1
101
+
102
+ # unzip works
103
+ test "unzip is /usr/bin/unzip" = "$(type unzip)" || exit 1
104
+ git init unzip-test &&
105
+ echo TEST >unzip-test/README &&
106
+ git -C unzip-test add -A &&
107
+ git -C unzip-test -c user.name=A -c [email protected] commit -m 'Testing, testing...' &&
108
+ git --git-dir=unzip-test/.git archive -o test.zip HEAD &&
109
+ unzip -v test.zip >unzip-test.out &&
110
+ cat unzip-test.out &&
111
+ test "grep is /usr/bin/grep" = "$(type grep)" || exit 1
112
+ grep README unzip-test.out
113
+ publish-release-assets :
114
+ if : github.event_name == 'push' && github.ref == 'refs/heads/main'
115
+ runs-on : ubuntu-latest
116
+ needs : [assorted-validations]
117
+ steps :
118
+ - name : download minimal-sdk artifact
119
+ uses : actions/download-artifact@v4
120
+ with :
121
+ name : minimal-sdk
122
+ path : ${{github.workspace}}
123
+ - name : download minimal-sdk artifact
124
+ uses : actions/download-artifact@v4
125
+ with :
126
+ name : minimal-sdk-extra
127
+ path : ${{github.workspace}}
128
+ - name : publish release asset
129
+ uses : actions/github-script@v7
130
+ with :
131
+ script : |
132
+ const req = { owner: context.repo.owner, repo: context.repo.repo }
133
+ // find or create the GitHub release named `ci-artifacts`
134
+ const release = await (async () => {
135
+ try {
136
+ return await github.rest.repos.getReleaseByTag({ ...req, tag: 'ci-artifacts' });
137
+ } catch (e) {
138
+ if (e.status === 404) {
139
+ // create the `ci-artifacts` GitHub release based on the current revision
140
+ const workflowRunsURL = `${context.serverUrl}/${
141
+ process.env.GITHUB_WORKFLOW_REF.replace(/\/\.github\/workflows\/([^@]+).*/, '/actions/workflows/$1')
142
+ }`
143
+ return await github.rest.repos.createRelease({
144
+ ... req,
145
+ tag_name: 'ci-artifacts',
146
+ body: `Continuous release of \`ci-artifacts\`
147
+
148
+ This release is automatically updated by the [ci-artifacts](${workflowRunsURL}) workflow.
149
+
150
+ For technical reasons, allow up to a minute for release assets to be missing while they are updated.`,
151
+ });
152
+ }
153
+ throw e;
154
+ }
155
+ })()
156
+
157
+ const fs = require('fs')
158
+ for (const fileName of [
159
+ 'git-sdk-aarch64-minimal.tar.gz',
160
+ 'git-sdk-aarch64-minimal.zip',
161
+ 'git-sdk-aarch64-minimal.7z.exe',
162
+ ]) {
163
+ console.log(`Uploading ${fileName}`)
164
+ const uploadReq = {
165
+ ...req,
166
+ release_id: release.data.id,
167
+ name: fileName,
168
+ headers: {
169
+ 'content-length': (await fs.promises.stat(fileName)).size,
170
+ },
171
+ data: fs.createReadStream(fileName),
172
+ }
173
+
174
+ // if the asset does not yet exist, simply upload it
175
+ const originalAsset = release.data.assets.filter(asset => asset.name === fileName).pop()
176
+ if (!originalAsset) {
177
+ const asset = await github.rest.repos.uploadReleaseAsset(uploadReq)
178
+ console.log(`Uploaded to ${asset.data.browser_download_url}`)
179
+ continue
180
+ }
181
+
182
+ // otherwise upload it using a temporary file name,
183
+ // then delete the old asset
184
+ // and then rename the new asset;
185
+ // this way, the asset is not missing for a long time
186
+ const asset = await github.rest.repos.uploadReleaseAsset({ ...uploadReq, name: `tmp.${fileName}` })
187
+ await github.rest.repos.deleteReleaseAsset({ ...req, asset_id: originalAsset.id })
188
+ const updatedAsset = await github.rest.repos.updateReleaseAsset({...req,
189
+ asset_id: asset.data.id,
190
+ name: fileName,
191
+ label: fileName,
192
+ })
193
+ console.log(`Updated ${updatedAsset.data.browser_download_url}`)
194
+ }
195
+
196
+ await github.rest.git.updateRef({
197
+ ...req,
198
+ ref: 'tags/ci-artifacts',
199
+ sha: process.env.GITHUB_SHA,
200
+ })
0 commit comments