-
Notifications
You must be signed in to change notification settings - Fork 0
412 lines (355 loc) · 16.2 KB
/
Copy pathrelease-linux.yml
File metadata and controls
412 lines (355 loc) · 16.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
# RunDock — Linux Release Workflow
# Triggers on version tags (v*) → builds Linux binaries → packages .deb → publishes APT repo on GitHub Pages
# https://github.com/damingishere-coder/RunDock
name: Release (Linux)
on:
push:
tags:
- "v*"
permissions:
contents: read
# APT publication uses one shared gh-pages branch, so releases must not overlap.
concurrency:
group: release-linux-publication
cancel-in-progress: false
env:
CARGO_TERM_COLOR: always
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
NPM_VERSION: 11.12.1
jobs:
validate-release-tag:
name: Validate release tag
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Require a matching semantic version
env:
RELEASE_REF: ${{ github.ref_name }}
run: |
printf '%s\n' "$RELEASE_REF" | grep -Eq '^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z]+([.-][0-9A-Za-z]+)*)?(\+[0-9A-Za-z]+([.-][0-9A-Za-z]+)*)?$' || {
echo "::error::Release tag must be a strict v-prefixed semantic version"
exit 1
}
TAG_VERSION="${RELEASE_REF#v}"
CARGO_VERSION="$(sed -n 's/^version *= *"\([^"]*\)"/\1/p' Cargo.toml | head -n 1)"
test "$TAG_VERSION" = "$CARGO_VERSION" || {
echo "::error::Release tag version does not match Cargo.toml"
exit 1
}
quality:
name: Required quality gate
uses: ./.github/workflows/quality.yml
needs: validate-release-tag
# ─────────────────────────────────────────────────────────────────────────────
# Build web UI (shared asset, embedded into the binary via rust-embed)
# ─────────────────────────────────────────────────────────────────────────────
build-web-ui:
name: Build Web UI
runs-on: ubuntu-22.04
needs: quality
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 24.15.0
cache: npm
cache-dependency-path: web-ui/package-lock.json
- name: Build web UI
run: |
npm install --global "npm@$NPM_VERSION"
test "$(npm --version)" = "$NPM_VERSION"
cd web-ui
npm ci
npm run build
- name: Upload web UI artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: web-ui-dist
path: web-ui/dist/
# ─────────────────────────────────────────────────────────────────────────────
# Build Linux amd64 binary
# ─────────────────────────────────────────────────────────────────────────────
build-linux-amd64:
name: Build (Linux amd64)
runs-on: ubuntu-22.04
needs: build-web-ui
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Restore web UI
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: web-ui-dist
path: web-ui/dist/
- name: Install pinned Rust toolchain
run: rustup toolchain install 1.98.0 --profile minimal --target x86_64-unknown-linux-gnu
- name: Cache Cargo registry
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: linux-amd64-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: linux-amd64-cargo-
- name: Build release binary
env:
GH_OAUTH_CLIENT_ID: ${{ secrets.GH_OAUTH_CLIENT_ID }}
run: cargo build --release --locked --target x86_64-unknown-linux-gnu
- name: Upload binary artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: alter-linux-amd64
path: target/x86_64-unknown-linux-gnu/release/alter
# ─────────────────────────────────────────────────────────────────────────────
# Build Linux arm64 binary (cross-compiled)
# ─────────────────────────────────────────────────────────────────────────────
build-linux-arm64:
name: Build (Linux arm64)
runs-on: ubuntu-22.04
needs: build-web-ui
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Restore web UI
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: web-ui-dist
path: web-ui/dist/
- name: Install cross-compilation toolchain
run: |
sudo apt-get update -q
sudo apt-get install -y gcc-aarch64-linux-gnu
- name: Install pinned Rust toolchain
run: rustup toolchain install 1.98.0 --profile minimal --target aarch64-unknown-linux-gnu
- name: Cache Cargo registry
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: linux-arm64-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: linux-arm64-cargo-
- name: Build release binary
env:
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
GH_OAUTH_CLIENT_ID: ${{ secrets.GH_OAUTH_CLIENT_ID }}
run: cargo build --release --locked --target aarch64-unknown-linux-gnu
- name: Upload binary artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: alter-linux-arm64
path: target/aarch64-unknown-linux-gnu/release/alter
# ─────────────────────────────────────────────────────────────────────────────
# Package: build .deb for each arch and attach to GitHub Release
# ─────────────────────────────────────────────────────────────────────────────
package-deb:
name: Package .deb
runs-on: ubuntu-22.04
needs: [build-linux-amd64, build-linux-arm64]
concurrency:
group: github-release-${{ github.ref }}
cancel-in-progress: false
outputs:
version: ${{ steps.version.outputs.VERSION }}
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Extract version from tag
id: version
env:
RELEASE_REF: ${{ github.ref_name }}
run: |
printf '%s\n' "$RELEASE_REF" | grep -Eq '^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z]+([.-][0-9A-Za-z]+)*)?(\+[0-9A-Za-z]+([.-][0-9A-Za-z]+)*)?$' || exit 1
TAG="$RELEASE_REF"
VERSION="${TAG#v}"
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"
- name: Download amd64 binary
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: alter-linux-amd64
path: binaries/amd64/
- name: Download arm64 binary
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: alter-linux-arm64
path: binaries/arm64/
- name: Make binaries executable
run: |
chmod +x binaries/amd64/alter
chmod +x binaries/arm64/alter
- name: Make build script executable
run: chmod +x scripts/build-deb.sh
- name: Build amd64 .deb
env:
RELEASE_VERSION: ${{ steps.version.outputs.VERSION }}
run: ./scripts/build-deb.sh binaries/amd64/alter "$RELEASE_VERSION" amd64
- name: Build arm64 .deb
env:
RELEASE_VERSION: ${{ steps.version.outputs.VERSION }}
run: ./scripts/build-deb.sh binaries/arm64/alter "$RELEASE_VERSION" arm64
- name: Generate and sign checksum manifest (required)
env:
APT_GPG_KEY: ${{ secrets.APT_GPG_KEY }}
APT_GPG_FINGERPRINT: ${{ vars.APT_GPG_FINGERPRINT }}
run: |
if [ -z "$APT_GPG_KEY" ]; then
echo "::error::APT_GPG_KEY is required; refusing to publish unverifiable packages."
exit 1
fi
if [ -z "$APT_GPG_FINGERPRINT" ]; then
echo "::error::APT_GPG_FINGERPRINT repository variable is required."
exit 1
fi
printf '%s' "$APT_GPG_KEY" | gpg --batch --import
KEY_ID=$(gpg --list-secret-keys --with-colons --fingerprint | awk -F: '/^fpr/{print $10; exit}')
test -n "$KEY_ID" || { echo "::error::No signing key was imported"; exit 1; }
test "$KEY_ID" = "$APT_GPG_FINGERPRINT" || {
echo "::error::Imported signing key fingerprint does not match APT_GPG_FINGERPRINT"
exit 1
}
sha256sum ./*.deb > SHA256SUMS
gpg --batch --yes --armor --default-key "$KEY_ID" \
--detach-sign --output SHA256SUMS.asc SHA256SUMS
gpg --armor --export "$KEY_ID" > rundock-release-key.asc
- name: Upload .deb artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: alter-deb-packages
path: |
*.deb
SHA256SUMS
SHA256SUMS.asc
rundock-release-key.asc
publish-release-assets:
name: Publish Linux release assets
runs-on: ubuntu-22.04
needs: package-deb
permissions:
contents: write
steps:
- name: Download signed .deb packages
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: alter-deb-packages
path: release-assets/
- name: Attach .deb files to GitHub Release
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 # v2.3.2
with:
files: |
release-assets/*.deb
release-assets/SHA256SUMS
release-assets/SHA256SUMS.asc
release-assets/rundock-release-key.asc
# ─────────────────────────────────────────────────────────────────────────────
# Publish: update APT repository on gh-pages branch
# ─────────────────────────────────────────────────────────────────────────────
publish-apt-repo:
name: Publish APT Repository
runs-on: ubuntu-22.04
needs: [package-deb, publish-release-assets]
permissions:
contents: write
steps:
- name: Checkout main repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: Checkout or create gh-pages branch
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if git ls-remote --exit-code origin gh-pages; then
git fetch origin gh-pages:refs/remotes/origin/gh-pages
git worktree add -b publish-gh-pages gh-pages origin/gh-pages
else
echo "gh-pages branch does not exist — creating orphan branch"
git worktree add --orphan gh-pages
cd gh-pages
git commit --allow-empty -m "chore: initialise gh-pages"
git push origin gh-pages
cd ..
fi
- name: Download .deb packages
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: alter-deb-packages
path: new-debs/
- name: Set up APT repo directory structure
run: |
mkdir -p gh-pages/apt/pool/main
mkdir -p gh-pages/apt/dists/stable/main/binary-amd64
mkdir -p gh-pages/apt/dists/stable/main/binary-arm64
- name: Copy .deb files into pool
run: cp new-debs/*.deb gh-pages/apt/pool/main/
- name: Generate Packages files
run: |
cd gh-pages/apt
dpkg-scanpackages --arch amd64 pool/main > dists/stable/main/binary-amd64/Packages
dpkg-scanpackages --arch arm64 pool/main > dists/stable/main/binary-arm64/Packages
gzip -k -f dists/stable/main/binary-amd64/Packages
gzip -k -f dists/stable/main/binary-arm64/Packages
- name: Generate Release file
run: |
cd gh-pages/apt
apt-ftparchive \
-o APT::FTPArchive::Release::Origin=RunDock \
-o APT::FTPArchive::Release::Label=RunDock \
-o APT::FTPArchive::Release::Suite=stable \
-o APT::FTPArchive::Release::Codename=stable \
-o APT::FTPArchive::Release::Architectures="amd64 arm64" \
-o APT::FTPArchive::Release::Components=main \
-o APT::FTPArchive::Release::Description="RunDock process manager APT repository" \
release dists/stable > dists/stable/Release
- name: Sign Release (required)
env:
APT_GPG_KEY: ${{ secrets.APT_GPG_KEY }}
APT_GPG_FINGERPRINT: ${{ vars.APT_GPG_FINGERPRINT }}
run: |
if [ -z "$APT_GPG_KEY" ]; then
echo "::error::APT_GPG_KEY secret is required; refusing to publish an unsigned repository."
exit 1
fi
if [ -z "$APT_GPG_FINGERPRINT" ]; then
echo "::error::APT_GPG_FINGERPRINT repository variable is required."
exit 1
fi
echo "$APT_GPG_KEY" | gpg --batch --import
KEY_ID=$(gpg --list-secret-keys --with-colons --fingerprint | awk -F: '/^fpr/{print $10; exit}')
test -n "$KEY_ID"
test "$KEY_ID" = "$APT_GPG_FINGERPRINT" || {
echo "::error::Imported signing key fingerprint does not match APT_GPG_FINGERPRINT"
exit 1
}
cd gh-pages/apt
gpg --batch --yes --default-key "$KEY_ID" \
--clearsign -o dists/stable/InRelease dists/stable/Release
gpg --batch --yes --default-key "$KEY_ID" \
--detach-sign -o dists/stable/Release.gpg dists/stable/Release
# Export public key for users to download
gpg --armor --export "$KEY_ID" > ../gpg-key.asc
test -s dists/stable/InRelease
test -s dists/stable/Release.gpg
test -s ../gpg-key.asc
- name: Commit and push to gh-pages
env:
RELEASE_VERSION: ${{ needs.package-deb.outputs.version }}
run: |
cd gh-pages
test -s gpg-key.asc
git add apt/
git add gpg-key.asc
if git diff --cached --quiet; then
echo "No APT repository changes to publish"
else
git commit -m "apt: release $RELEASE_VERSION"
fi
git fetch origin gh-pages
git rebase origin/gh-pages
git push origin HEAD:gh-pages
git fetch origin gh-pages
test "$(git rev-parse HEAD)" = "$(git rev-parse origin/gh-pages)"