Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/rules/release-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ If a future PR wants to "simplify" by re-merging a `prep` and `publish` pair, re
- **`cargo publish` uses `--no-verify`.** The verify-build runs `build.rs` of every transitive dependency with `CARGO_REGISTRY_TOKEN` in env; `--no-verify` skips that compile entirely. The tag's commit was already CI'd cleanly on `main`; the verify-build was a redundant safety net.
- **Every publishable workspace crate must appear in `publish-crates`'s `for crate in ...` list, in dependency order.** The list is hardcoded; a publishable crate omitted from it breaks the chain at the first dependent that cannot resolve it on the index (incident v2.103.0: the new `fallow-output` / `fallow-engine` / `fallow-api` crates were missing, so only `fallow-types` published and the rest stalled at the prior version). The invariant `list == { workspace crates with publish != false }` is enforced by `crates/cli/tests/release_publish_list.rs`. Adding a publishable crate means inserting it after its dependencies; retiring one or setting `publish = false` means removing it. To recover a partially-failed release, re-run the publish from the RELEASE TAG (not `main`, which may carry later commits at the same not-yet-bumped version) with the same idempotent `cargo publish -p <crate> --no-verify` loop; it skips already-uploaded crates.
- **`publish-crates` runs `setup-rust` with `cache-key: release-publish-crates`.** Dedicated cache scope so a poisoned workspace cache from a build job cannot influence `cargo package`.
- **`actions/checkout` carries `persist-credentials: false`** on every job EXCEPT where the job actually pushes git refs. The single exception is the `release` job's rolling `v1` tag push, which uses an explicit `https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}` URL to scope `GITHUB_TOKEN` to one step.
- **`actions/checkout` carries `persist-credentials: false`** on every job. No release.yml job pushes git tags anymore: the rolling `v1`/`v3` action tags are pushed by the maintainer's release flow (fallow-release skill step 8b), because `GITHUB_TOKEN` can never update a ref whose diff touches `.github/workflows/` (the `workflows` permission is not grantable to it), which made the old in-workflow `v1` push fail on the first release after any workflow edit (v3.4.2). The `docker-lockstep` job pushes a branch, but only via its explicitly-scoped token URL and never a tag.
- **`expected_names[]` in `npm-publish` is load-bearing.** The 18-row TSV manifest produced by `npm-prep` is validated against (a) row count = 18, (b) per-row expected name in publish order, (c) per-row version equal to tag-derived `VERSION`, (d) the tarball's own `package/package.json` (`tar -xOf <file> package/package.json | node -e ...`) matching the manifest row. Adding or removing a platform target requires updating BOTH the pack loops in `npm-prep` AND the `expected_names` array AND the `EXPECTED=18` constant.
- **Job name `npm-publish` and workflow filename `release.yml` are part of npm trusted-publishing config.** Renaming either silently breaks OIDC. The `vscode-publish` job similarly relies on the workflow path for any future OIDC-style publishing.
- **`shell: bash` on the `npm-publish` "Publish all tarballs" step is load-bearing.** The expected_names array lookup `${expected_names[$index]}` is 0-indexed in bash and 1-indexed in zsh; the explicit shell pin prevents a runner default change from silently breaking row matching.
Expand Down
14 changes: 5 additions & 9 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -427,15 +427,11 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Update stable action tags
env:
# GH_TOKEN is interpolated only into the git push URL below, never
# into shell metacharacters, and the checkout step does not persist
# credentials, so this token's lifetime is scoped to this step.
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git tag -f v1 "${GITHUB_SHA}"
git push "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}" refs/tags/v1 --force
# The rolling v1/v3 action tags are pushed by the maintainer's release
# flow, not from here: GITHUB_TOKEN can never update a ref whose diff
# touches .github/workflows/ (GitHub requires the workflows permission,
# which GITHUB_TOKEN cannot be granted), so the in-workflow push failed
# on the first release after any workflow edit (v3.4.2).

# The Dockerfile pins ARG FALLOW_VERSION plus two per-arch sha256 digests by
# hand. Nothing kept them in sync with releases: the pin sat on 2.94.0 for
Expand Down
Loading