ci: arm publishing for @cipherstash/auth and the stack-* crates - #1009
Conversation
🦋 Changeset detectedLatest commit: ed14d04 The changes in this PR will be included in the next version bump. This PR includes changesets to release 19 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
d669946 to
db6b3b9
Compare
e78e71d to
dfa43c2
Compare
Delete the seven @cipherstash/auth entries from FROZEN_PUBLISHERS and FROZEN_ARTEFACT_DIGESTS. This arms release.yml's auth-artifacts and publish-auth jobs, which run when the gate reports auth=true, and release-plz.yml's release-crates job, whose switch keys on the @cipherstash/auth entry. It assumes npm and crates.io trusted publishing for the seven packages and the two crates now name cipherstash/stack. Remove the temporary lint-no-auth-changeset guard, its test, its lint:auth-changeset script and its tests.yml step, as its header asked. Its check that the changesets fixed group is exactly the seven auth workspace packages moves to auth-build-artifacts.test.mjs, so the lockstep stays covered. The gate keeps its `files` and `noTreeBytes` entry shapes. Their tests use the entries the auth packages carried as fixtures. New tests assert that no auth package is frozen, that an unpublished auth version passes the gate with auth=true, and that the crates line is armed. frozen-publisher-docs.test.mjs keeps its auth rows, with the wording each instruction was written for, so an assertion of absence can still fail. AGENTS.md, SECURITY.md, CONTRIBUTING.md and the workflow comments no longer describe the freeze, and docs/npm-releases.md is marked as the suite's history. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PaY5xYydZUWhv8Nex9Sw8a
Port require-auth-npm-changeset.yml from cipherstash-suite, with its paths renamed: packages/stack-auth's manifest and src/, and the auth and stack-auth-wasm binding folders. The job diffs the pull request against its base and passes the added or modified changesets to scripts/check-auth-npm-changeset.mjs, which fails unless one releases @cipherstash/auth with a patch, minor or major bump. The script imports @changesets/parse, which pnpm does not expose to the root as a dependency of @changesets/cli, so the root declares it at the 0.4.3 already in the lock and the job installs only the root. The script now skips .changeset/README.md, which the job's pathspec matches, and names `pnpm changeset`. The suite's release-plz exemption is dropped: nothing here opens a release-plz pull request. check-auth-npm-changeset.test.mjs drives the script and holds the job's pathspec and its paths filter to the same set. The workflow has only a pull_request trigger, which workflow-paths-filter-parity now records. AGENTS.md and CONTRIBUTING.md describe the rule, and note that a crates release trips it: stack-auth sends its own version in its user-agent. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PaY5xYydZUWhv8Nex9Sw8a
Copy the six changesets pending on cipherstash-suite main (f161a447f, the commit the import exported) into .changeset/, byte for byte. Each is a patch for @cipherstash/auth; the fixed group takes the six platform packages with it, to 0.44.1. The suite's last release PR closed without merging and the export left .changeset/ out, so the first auth release from this repository carries them. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PaY5xYydZUWhv8Nex9Sw8a
stack, stash, @cipherstash/wizard and the protect-ffi integration suite move the wrapper and the six platform packages from `catalog:repo` to `workspace:*`. The seven catalog entries, the two minimumReleaseAgeExclude entries and the two npm Dependabot ignores are dead config and go. The lock changes only the auth importers and entries, and `pnpm pack` still writes each range as the exact version. A workspace @cipherstash/auth ships source only, and its index.js loads the napi module on import, so every CI job that imports the SDK or runs the CLI now builds it: without a build, the stack, stash and wizard suites fail 26, 16 and 2 files with `Failed to load native binding`. .github/actions/build-auth-binding runs build:debug, and build:wasm with `wasm: 'true'`, then checks both load. It runs after each of the ten build-ffi-binding calls, with wasm where that call has it, and in tests-bench.yml, whose unit checks import the SDK and whose globalSetup runs `stash`. In tests.yml's run-tests it replaces the auth half of the binding build step. auth-binding-step-order.test.mjs holds the pairing and the filters. Every workflow that uses the action filters on it. The three integration workflows that saw auth bumps through pnpm-workspace.yaml now filter on the paths require-auth-npm-changeset.yml treats as what @cipherstash/auth ships. supply-chain.e2e.test.ts keeps the lockstep invariant in its new shape: no auth catalog entry, and `workspace:*` in every consumer. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PaY5xYydZUWhv8Nex9Sw8a
db6b3b9 to
2a38fb4
Compare
dfa43c2 to
931f359
Compare
yujiyokoo
left a comment
There was a problem hiding this comment.
LGTM
Reviewed with GPT-6-Luna medium
| - packages/stack-auth/Cargo.toml | ||
| - packages/stack-auth/src/** | ||
| - languages/typescript/packages/auth/** | ||
| - languages/typescript/packages/stack-auth-wasm/** |
There was a problem hiding this comment.
Non-blocking, possibly inherited from the suite: this set does not include all the inputs to the binary that @cipherstash/auth ships.
languages/typescript/packages/auth/Cargo.toml depends on stack-profile, and stack-auth depends on it too. Both resolve it by path to packages/stack-profile. The root Cargo.toml and Cargo.lock also set the reqwest, jsonwebtoken/aws_lc_rs, tokio and vitaminc versions that are compiled into the napi module.
Failure case: a PR that changes only packages/stack-profile/src/**, or a Dependabot cargo bump that changes only Cargo.lock, changes the shipped .node binary. But this workflow does not start, so no @cipherstash/auth release follows. The change then waits, unreleased, until some other auth change comes.
Suggestion: add packages/stack-profile/Cargo.toml, packages/stack-profile/src/**, Cargo.toml and Cargo.lock here and to the git diff pathspec below. check-auth-npm-changeset.test.mjs keeps the two lists equal. The root-manifest paths will also match changes that affect only the other crates. If that is too noisy, add only stack-profile now.
| # The runner's cargo, as build-ffi-binding uses for `index.node`. Writes | ||
| # the typings to the committed `native.d.ts`, so the tree stays clean. | ||
| - name: Build the napi module (cargo) | ||
| shell: bash |
There was a problem hiding this comment.
Non-blocking: unlike build-ffi-binding, this action has no cache. build-ffi-binding caches index.node on a hash of its Rust inputs, so a PR that changes no Rust only restores the file. Here, each of the ~11 jobs that use this action does a cold cargo build (debug) of stack-auth-node on every run. That build includes aws-lc-sys through jsonwebtoken, and also the wasm-pack build where the job passes wasm: true.
The result is correct, so this does not block the freeze. For a follow-up, the same actions/cache pattern as build-ffi-binding would apply here, keyed on the root Cargo.lock, the stack-auth/stack-profile sources and this binding crate. The "DO NOT USE FROM A PUBLISHING WORKFLOW" note above already covers the release-cache rule.
freshtonic
left a comment
There was a problem hiding this comment.
Approved. I read the four commits against the base ci/stack-crates-release-pipelines.
What I checked:
- Gate (commit 1).
FROZEN_PUBLISHERSandFROZEN_ARTEFACT_DIGESTSare now empty, and they change together. Thecratesswitch ineql-pipeline-armed.mjskeys on the@cipherstash/authentry, so the same deletion armsrelease-crates. ThefilesandnoTreeBytesshapes keep their tests. That is correct, because an empty map is a valid state. - Publish order.
releaseneedspublish-auth, and itsif:readsneeds.gate.outputs.authinstead of the result of a skipped job. Sochangeset publishcannot publish@cipherstash/stack,stashor@cipherstash/wizardwith an exact@cipherstash/auth@0.44.1dependency before that version is on npm. - Workspace switch (commit 4).
workspace:*packs the exact version, as the old exact catalog pin did. The changesetsfixedgroup keeps the seven auth packages in lockstep. The lockstep check moved from the catalog tosupply-chain.e2e.test.ts, so it is still enforced. Removing the Dependabot ignores and theminimumReleaseAgeExcludeentries is correct, because nothing resolves these packages from the registry now. - Carried changesets (commit 3). All six are
@cipherstash/auth: patchonly. The cascade to 19 packages in the changeset-bot comment is the expectedupdateInternalDependenciesresult.
I left two non-blocking inline notes: the changeset check does not watch packages/stack-profile or the root Cargo.lock, and build-auth-binding has no cache. Each one can be a follow-up after the freeze.
Also, as the description says: confirm that auth-preflight.yml passed on main after #1002 merges, before this PR merges. Then watch the release-plz.yml run that the merge starts.
…usl again @cipherstash/auth-linux-x64-musl 0.44.0 linked glibc, so the package did not load on musl systems such as Alpine Linux. #1018 fixes the build. None of the six carried changesets says so, and AGENTS.md asks for a changeset for a bug fix to a published package. It lives here because main's lint:auth-changeset refuses any @cipherstash/auth changeset until this PR removes the freeze. freshtonic raised it in review of #1018. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PaY5xYydZUWhv8Nex9Sw8a
This PR switches publishing on for
@cipherstash/authand its six platform packages on npm, and for thestack-authandstack-profilecrates on crates.io. The title calls this "arming". Each platform package holds the native binary for one platform, such asdarwin-arm64.Until now, the release gate has blocked any new version of the seven auth packages. The release gate,
scripts/release-gate.mjs, runs on every push tomainbefore anything publishes to npm. This PR removes the block, which also switches on the crates release job that PR D added.This is PR E of 6 in the stack crates import. The import moves six Rust crates, their bindings and the Go module here from the private
cipherstash/cipherstash-suiterepository, with their history. The stack crates import plan in Linear lists every step, and Linear issue CIP-4274 tracks the work.This PR is stacked on PR D, #1002. Its base branch is PR D's branch, so the diff shows only this PR's own changes. It stays a draft until the freeze on Friday 2 October 2026, Pacific time. The freeze is the window in which the six PRs merge in order: #1000, #1001, #1003, #1002, #1009, then #1010. The steps for that day are in §9.1 of the plan.
Read the five commits in order, and skim the copied changesets
Read commits 1, 2 and 4 in full. Commit 3 copies six files from the suite byte for byte, so you can skim it. In commit 4, the
pnpm-lock.yamlchanges touch only the@cipherstash/authentries.Each commit makes one change
66437857removes the seven@cipherstash/authentries from the release gate's two freeze lists,FROZEN_PUBLISHERSandFROZEN_ARTEFACT_DIGESTS. The gate fails if a package on those lists would publish a new version. Both lists end empty, as they are onmain. The commit also removes the temporarylint-no-auth-changesetcheck that PR B added.0efb59e3ports the suite's check that a change to what@cipherstash/authships comes with a changeset. A changeset is a file in.changeset/that says which packages a change releases, and how far each version moves. The check,require-auth-npm-changeset.yml, runs on pull requests only.e766c9a8copies the suite's six pending@cipherstash/authchangesets, byte for byte. The suite history that PR B imports leaves.changeset/out, so without this commit they would be lost. Each one is a patch, so the first auth release from this repository takes the seven packages to 0.44.1.931f359dmakes@cipherstash/stack,stash,@cipherstash/wizardand the protect-ffi integration tests take@cipherstash/authfrom this repository instead of npm. The copy in this repository has no built binary. So a new action,build-auth-binding, builds the native binding in every CI job that loads it. Without that build, 26, 16 and 2 test files fail in@cipherstash/stack,stashand@cipherstash/wizard. A guard test keeps everybuild-ffi-bindingcall paired with abuild-auth-bindingcall.ed14d047adds a seventh@cipherstash/authpatch changeset, for the musl fix in fix(ci): build the musl @cipherstash/auth binary in Alpine, and check every binary's C library #1018. In 0.44.0, thelinux-x64-muslbinary linked glibc, so the package did not load on musl systems such as Alpine Linux. None of the six copied changesets says so. It lives in this PR becausemain'slint:auth-changesetrefuses any@cipherstash/authchangeset until commit 1 removes that check. freshtonic raised it in review of fix(ci): build the musl @cipherstash/auth binary in Alpine, and check every binary's C library #1018.The steps before this merge are done
This PR could not merge before two freeze steps. Both are now done:
main.37c23d7b. Thenauth-preflight.ymlran against this branch's head,ed14d047, and passed: run 37064086035. That dry run builds all seven auth packages without publishing them. All seven builds passed, and thelinux-x64-muslbinary links musl and loads inside Alpine Linux.Trusted publishing is already in place. It lets a registry accept a publish from a named GitHub workflow, with no stored token. On npm, all seven auth packages trust
cipherstash/stack. On crates.io,stack-authandstack-profiletrust it too.Merge this PR with a merge commit, which keeps every commit, and never with a squash or a rebase. The crates release, #1010, is built on these exact commits.
Watch the release-plz run that this merge starts
Merging runs
release-plz.yml, because this PR edits that file. release-plz is the tool that publishes the Rust crates to crates.io. Itsrelease-cratesjob should find version 0.42.3 already published, and publish nothing. Watch that run.The checks pass locally and in CI
pnpm test:scriptspasses 1,142 tests.@cipherstash/authnow passes the release gate, which reportsauth=true. On PR D, the same bump makes the gate fail.🤖 Generated with Claude Code
https://claude.ai/code/session_01PaY5xYydZUWhv8Nex9Sw8a