Skip to content

Commit 4df043d

Browse files
committed
chore(release): harden packaging workflows
1 parent c555fb0 commit 4df043d

14 files changed

Lines changed: 602 additions & 90 deletions

File tree

.github/workflows/changesets.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ on:
55
branches:
66
- main
77

8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
12+
concurrency:
13+
group: changesets-${{ github.ref }}
14+
cancel-in-progress: true
15+
816
jobs:
917
version:
1018
runs-on: ubuntu-latest

.github/workflows/ci.yml

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,31 @@ on:
66
- main
77
pull_request:
88

9+
permissions:
10+
contents: read
11+
12+
concurrency:
13+
group: ci-${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
916
jobs:
17+
version-consistency:
18+
name: Version Consistency
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: actions/checkout@v4
22+
- uses: pnpm/action-setup@v4
23+
- uses: actions/setup-node@v4
24+
with:
25+
node-version: 22
26+
cache: pnpm
27+
- run: pnpm install --frozen-lockfile
28+
- run: pnpm version:check
29+
1030
cli-cross-platform:
1131
name: CLI Unit (${{ matrix.os }})
1232
runs-on: ${{ matrix.os }}
33+
needs: version-consistency
1334
strategy:
1435
fail-fast: false
1536
matrix:
@@ -30,6 +51,7 @@ jobs:
3051
verify-linux:
3152
name: Verify Linux Runtime
3253
runs-on: ubuntu-latest
54+
needs: version-consistency
3355
steps:
3456
- uses: actions/checkout@v4
3557
- name: Install Linux runtime dependencies
@@ -48,18 +70,26 @@ jobs:
4870
- uses: dtolnay/rust-toolchain@stable
4971
with:
5072
components: rustfmt, clippy
73+
- uses: Swatinem/rust-cache@v2
74+
with:
75+
workspaces: src-tauri -> target
5176
- uses: pnpm/action-setup@v4
5277
- uses: actions/setup-node@v4
5378
with:
5479
node-version: 22
5580
cache: pnpm
5681
- run: pnpm install --frozen-lockfile
82+
- run: pnpm test:cli
5783
- run: cargo fmt --manifest-path src-tauri/Cargo.toml --all --check
5884
- run: cargo clippy --manifest-path src-tauri/Cargo.toml --all-targets -- -D warnings
5985
- run: cargo check --manifest-path src-tauri/Cargo.toml
60-
- run: pnpm build:web
61-
- run: pnpm build:runtime
62-
- run: pnpm build:packages
86+
- run: cargo test --manifest-path src-tauri/Cargo.toml
87+
- run: pnpm pack:local
6388
- run: pnpm test:smoke
6489
- run: npx playwright install --with-deps chromium
6590
- run: pnpm test:e2e:release
91+
- uses: actions/upload-artifact@v4
92+
if: success()
93+
with:
94+
name: release-artifacts-linux
95+
path: .artifacts/*

.github/workflows/release.yml

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,35 @@ on:
77

88
permissions:
99
contents: write
10+
id-token: write
11+
12+
concurrency:
13+
group: release-${{ github.ref }}
14+
cancel-in-progress: false
1015

1116
jobs:
17+
preflight:
18+
name: Release Preflight
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 0
24+
- uses: pnpm/action-setup@v4
25+
- uses: actions/setup-node@v4
26+
with:
27+
node-version: 22
28+
cache: pnpm
29+
- run: pnpm install --frozen-lockfile
30+
- name: Verify tag matches package version
31+
run: |
32+
VERSION=$(node -e "console.log(require('./packages/coder-studio/package.json').version)")
33+
test "v$VERSION" = "$GITHUB_REF_NAME"
34+
- run: pnpm version:check
35+
1236
publish-platform:
1337
name: Publish ${{ matrix.package_slug }}
38+
needs: preflight
1439
runs-on: ${{ matrix.os }}
1540
strategy:
1641
fail-fast: false
@@ -41,21 +66,18 @@ jobs:
4166
patchelf \
4267
wget
4368
- uses: dtolnay/rust-toolchain@stable
69+
- uses: Swatinem/rust-cache@v2
70+
with:
71+
workspaces: src-tauri -> target
4472
- uses: pnpm/action-setup@v4
4573
- uses: actions/setup-node@v4
4674
with:
4775
node-version: 22
4876
cache: pnpm
4977
registry-url: 'https://registry.npmjs.org'
50-
- name: Verify tag matches package version
51-
shell: bash
52-
run: |
53-
VERSION=$(node -e "console.log(require('./packages/coder-studio/package.json').version)")
54-
test "v$VERSION" = "$GITHUB_REF_NAME"
5578
- run: pnpm install --frozen-lockfile
56-
- run: pnpm build:web
57-
- run: pnpm build:runtime
58-
- run: pnpm build:packages
79+
- run: pnpm release:check
80+
- run: node -e "require('fs').mkdirSync('.artifacts', { recursive: true })"
5981
- run: pnpm --dir packages/${{ matrix.package_slug }} pack --pack-destination ../../.artifacts
6082
- run: npm publish packages/${{ matrix.package_slug }} --access public
6183
env:
@@ -67,7 +89,9 @@ jobs:
6789

6890
publish-main:
6991
name: Publish @spencer-kit/coder-studio
70-
needs: publish-platform
92+
needs:
93+
- preflight
94+
- publish-platform
7195
runs-on: ubuntu-latest
7296
steps:
7397
- uses: actions/checkout@v4
@@ -77,14 +101,17 @@ jobs:
77101
node-version: 22
78102
cache: pnpm
79103
registry-url: 'https://registry.npmjs.org'
80-
- name: Verify tag matches package version
81-
run: |
82-
VERSION=$(node -e "console.log(require('./packages/coder-studio/package.json').version)")
83-
test "v$VERSION" = "$GITHUB_REF_NAME"
84104
- run: pnpm install --frozen-lockfile
105+
- run: pnpm version:check
106+
- run: node -e "require('fs').mkdirSync('.artifacts', { recursive: true })"
107+
- run: pnpm --dir packages/coder-studio pack --pack-destination ../../.artifacts
85108
- run: npm publish packages/coder-studio --access public
86109
env:
87110
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
111+
- uses: actions/upload-artifact@v4
112+
with:
113+
name: coder-studio-main
114+
path: .artifacts/*.tgz
88115

89116
github-release:
90117
name: Create GitHub Release
@@ -93,9 +120,19 @@ jobs:
93120
- publish-main
94121
runs-on: ubuntu-latest
95122
steps:
123+
- uses: actions/checkout@v4
124+
- uses: pnpm/action-setup@v4
125+
- uses: actions/setup-node@v4
126+
with:
127+
node-version: 22
96128
- uses: actions/download-artifact@v4
97129
with:
98130
path: .release-artifacts
131+
merge-multiple: true
132+
- run: node scripts/release/write-release-manifest.mjs .release-artifacts
99133
- uses: softprops/action-gh-release@v2
100134
with:
101-
files: .release-artifacts/**/*.tgz
135+
files: |
136+
.release-artifacts/*.tgz
137+
.release-artifacts/release-manifest.json
138+
.release-artifacts/SHA256SUMS.txt

docs/development/npm-release.en.md

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,24 @@ Use `CODER_STUDIO_HOME` to override the state directory for tests or isolated en
6060
## Build Commands
6161

6262
```bash
63+
pnpm version:check
6364
pnpm build:web
6465
pnpm build:runtime
6566
pnpm build:packages
6667
pnpm pack:local
68+
pnpm release:verify
69+
pnpm release:verify:full
6770
```
6871

6972
What they do:
7073

74+
- `version:check`: verifies the root package, main package, platform packages, `Cargo.toml`, and `tauri.conf.json` all share the same version
7175
- `build:web`: builds the frontend into `dist/`
7276
- `build:runtime`: builds the Rust/Tauri release binary
7377
- `build:packages`: assembles the current platform runtime package
74-
- `pack:local`: emits local tarballs into `.artifacts/`
78+
- `pack:local`: runs the release build and emits local tarballs into `.artifacts/`
79+
- `release:verify`: runs version checks, CLI tests, Rust tests, local packaging, and smoke validation
80+
- `release:verify:full`: adds release E2E on top of `release:verify`
7581

7682
## Versioning
7783

@@ -84,20 +90,97 @@ pnpm changeset
8490
pnpm changeset:version
8591
```
8692

93+
A recommended local flow:
94+
95+
```bash
96+
pnpm changeset
97+
pnpm changeset:version
98+
git add .
99+
git commit -m "chore(release): version packages"
100+
```
101+
87102
The version sync step updates:
88103

89104
- `packages/*/package.json`
90105
- `src-tauri/Cargo.toml`
91106
- `src-tauri/tauri.conf.json`
92107
- the root `package.json`
93108

109+
`changeset:version` now runs `pnpm version:check` after syncing so version drift fails immediately.
110+
111+
## Local Pre-Release Validation
112+
113+
Minimum validation:
114+
115+
```bash
116+
pnpm release:verify
117+
```
118+
119+
Full validation:
120+
121+
```bash
122+
pnpm release:verify:full
123+
```
124+
125+
Local artifacts:
126+
127+
```bash
128+
pnpm pack:local
129+
ls .artifacts
130+
```
131+
132+
`.artifacts/` now includes:
133+
134+
- the main package tarball
135+
- the current platform tarball
136+
- `release-manifest.json`
137+
- `SHA256SUMS.txt`
138+
94139
## GitHub Actions
95140

96141
The automation is split into three workflows:
97142

98-
- `ci.yml`: PR/main validation for CLI tests, Rust verification, builds, smoke tests, and release E2E
99-
- `changesets.yml`: creates version PRs from pending changesets on `main`
100-
- `release.yml`: publishes platform packages, publishes the main package, and creates a GitHub Release from `v*` tags
143+
- `ci.yml`
144+
- adds a `version-consistency` gate
145+
- runs cross-platform CLI unit tests
146+
- runs Rust fmt/clippy/check/test on Linux
147+
- runs `pnpm pack:local`
148+
- runs smoke and release E2E
149+
- uploads Linux release artifacts
150+
- `changesets.yml`
151+
- runs only on `main`
152+
- creates or updates the version PR
153+
- now has explicit `contents` / `pull-requests` write permissions
154+
- `release.yml`
155+
- starts with a `preflight` job that validates the tag and runs `pnpm version:check`
156+
- publishes the 4 platform runtime packages
157+
- publishes the main `@spencer-kit/coder-studio` package
158+
- aggregates tarballs and attaches `release-manifest.json` plus `SHA256SUMS.txt` to the GitHub Release
159+
160+
## Release Trigger
161+
162+
After the version PR is merged, push a tag that matches the package version:
163+
164+
```bash
165+
git tag v0.1.0
166+
git push origin v0.1.0
167+
```
168+
169+
The workflow then:
170+
171+
1. checks that the tag matches `packages/coder-studio/package.json`
172+
2. publishes platform packages
173+
3. publishes the main package
174+
4. creates the GitHub Release assets
175+
176+
## GitHub / npm Requirements
177+
178+
The current release workflow expects:
179+
180+
- the default GitHub `GITHUB_TOKEN`
181+
- a repository secret named `NPM_TOKEN`
182+
183+
`NPM_TOKEN` must be allowed to publish the `@spencer-kit/*` packages on npm.
101184

102185
## Local Test Matrix
103186

@@ -111,6 +194,7 @@ pnpm test:e2e:release
111194
Coverage:
112195

113196
- `test:cli`: configuration, platform resolution, and state handling
197+
- `test:cli` now also covers release version consistency and release manifest generation
114198
- `test:smoke`: installs local tarballs and runs `start/status/restart/stop`
115199
- `test:e2e`: development-mode frontend/backend integration
116200
- `test:e2e:release`: browser E2E against the built release runtime

0 commit comments

Comments
 (0)