Skip to content

Commit 1507b64

Browse files
authored
ci: validate release packaging without publishing (#118)
* ci: add release packaging dry runs * ci: harden release dry-run gate
1 parent 09c40dd commit 1507b64

3 files changed

Lines changed: 67 additions & 1 deletion

File tree

‎.github/workflows/release.yml‎

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,22 @@ on:
44
push:
55
tags:
66
- "v*"
7+
pull_request:
8+
paths:
9+
- ".github/workflows/release.yml"
10+
- ".github/scripts/**"
11+
- "apps/headless/Dockerfile.linux"
12+
- "apps/headless/build.sh"
13+
- "apps/headless/build-linux.sh"
14+
- "apps/headless/install-linux.sh"
15+
- "apps/headless/Package.swift"
16+
workflow_dispatch:
17+
inputs:
18+
dry_run:
19+
description: Build and verify release packages without publishing
20+
required: true
21+
default: true
22+
type: boolean
723

824
permissions:
925
contents: read
@@ -13,9 +29,28 @@ jobs:
1329
runs-on: ubuntu-latest
1430
outputs:
1531
version: ${{ steps.version.outputs.version }}
32+
publish: ${{ steps.version.outputs.publish }}
1633
steps:
1734
- id: version
18-
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
35+
env:
36+
DRY_RUN: ${{ inputs.dry_run }}
37+
run: |
38+
set -eu
39+
if [ "$GITHUB_EVENT_NAME" = "push" ]; then
40+
case "$GITHUB_REF" in
41+
refs/tags/v*) ;;
42+
*) echo "release publishing requires a v* tag" >&2; exit 64 ;;
43+
esac
44+
echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
45+
echo "publish=true" >> "$GITHUB_OUTPUT"
46+
else
47+
if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ] && [ "$DRY_RUN" != "true" ]; then
48+
echo "manual release runs must use dry_run=true; publish by pushing a v* tag" >&2
49+
exit 64
50+
fi
51+
echo "version=0.0.${GITHUB_RUN_NUMBER}" >> "$GITHUB_OUTPUT"
52+
echo "publish=false" >> "$GITHUB_OUTPUT"
53+
fi
1954
2055
macos:
2156
needs: version
@@ -36,8 +71,14 @@ jobs:
3671
env:
3772
VERSION: ${{ needs.version.outputs.version }}
3873
run: |
74+
set -eu
3975
cd apps/headless
4076
ditto -c -k --keepParent Headless.app "Headless-${VERSION}-macos.zip"
77+
test -s "Headless-${VERSION}-macos.zip"
78+
unzip -t "Headless-${VERSION}-macos.zip"
79+
unzip -Z1 "Headless-${VERSION}-macos.zip" | grep -qx 'Headless.app/Contents/MacOS/Headless'
80+
unzip -Z1 "Headless-${VERSION}-macos.zip" | grep -qx 'Headless.app/Contents/Resources/bin/headless'
81+
unzip -Z1 "Headless-${VERSION}-macos.zip" | grep -qx 'Headless.app/Contents/Resources/bin/headless-mcp'
4182
- uses: actions/upload-artifact@v7
4283
with:
4384
name: macos
@@ -56,8 +97,15 @@ jobs:
5697
env:
5798
VERSION: ${{ needs.version.outputs.version }}
5899
run: |
100+
set -eu
59101
cp apps/headless/build/headless-linux-amd64.tar.gz \
60102
"apps/headless/build/headless-${VERSION}-linux-amd64.tar.gz"
103+
archive="apps/headless/build/headless-${VERSION}-linux-amd64.tar.gz"
104+
test -s "$archive"
105+
tar -tzf "$archive" > archive-contents.txt
106+
for expected in headless headless-host headless-mcp install-linux.sh Headless_HeadlessProtocol.resources/AgentRuntime.js; do
107+
grep -qx "$expected" archive-contents.txt
108+
done
61109
- uses: actions/upload-artifact@v7
62110
with:
63111
name: linux-amd64
@@ -76,15 +124,26 @@ jobs:
76124
env:
77125
VERSION: ${{ needs.version.outputs.version }}
78126
run: |
127+
set -eu
79128
cp apps/headless/build/headless-linux-arm64.tar.gz \
80129
"apps/headless/build/headless-${VERSION}-linux-arm64.tar.gz"
130+
archive="apps/headless/build/headless-${VERSION}-linux-arm64.tar.gz"
131+
test -s "$archive"
132+
tar -tzf "$archive" > archive-contents.txt
133+
for expected in headless headless-host headless-mcp install-linux.sh Headless_HeadlessProtocol.resources/AgentRuntime.js; do
134+
grep -qx "$expected" archive-contents.txt
135+
done
81136
- uses: actions/upload-artifact@v7
82137
with:
83138
name: linux-arm64
84139
path: apps/headless/build/headless-${{ needs.version.outputs.version }}-linux-arm64.tar.gz
85140

86141
publish:
87142
needs: [version, macos, linux-amd64, linux-arm64]
143+
if: >-
144+
github.event_name == 'push' &&
145+
startsWith(github.ref, 'refs/tags/v') &&
146+
needs.version.outputs.publish == 'true'
88147
runs-on: ubuntu-latest
89148
permissions:
90149
contents: write

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ Cutting that release is tracked in
7272

7373
### Changed
7474

75+
- The release workflow can now exercise and verify every package without
76+
publishing, manually or on pull requests that change packaging inputs.
7577
- macOS WebKit and Linux Chromium now share one `HostCore` dispatcher and
7678
lifecycle implementation behind small engine adapters, eliminating the two
7779
divergent copies of flow, capture, recording, report, trace, and error logic.

‎README.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ Assets: macOS `Headless.app` zip, Linux amd64/arm64 tarballs. See the Actions
214214
`Release` workflow and the release notes on each tag for install caveats
215215
(Gatekeeper; Linux Chromium/FFmpeg).
216216

217+
The `Release` workflow can also be run manually with `dry_run` enabled. That
218+
builds, verifies, and uploads all three workflow artifacts without creating a
219+
GitHub Release. Pull requests that change release packaging run the same dry
220+
run automatically.
221+
217222
## Tests
218223

219224
```sh

0 commit comments

Comments
 (0)