Skip to content

feat(release): npm trusted publishing (OIDC); flake dev shell with ziglint - #17

Merged
alleneubank merged 1 commit into
mainfrom
chore/flake-and-trusted-publishing
Aug 21, 2026
Merged

alleneubank merged 1 commit into
mainfrom
chore/flake-and-trusted-publishing

Conversation

@alleneubank

Copy link
Copy Markdown
Owner

Why

npm publishing has been broken for two releases and nothing surfaced it:

tag date result
v0.2.11 2026-02-01 publish job failed
v0.3.0 today publish job failed, 404 Not Found from the registry

A 404 on publish is npm's way of saying the token is not authorized. NPM_TOKEN was set 2025-11-28. Everything else about both releases looked green — tag, GitHub release, manifests — so npm quietly stayed on 0.2.11 while the repo moved on. Rotating the token would just reset the clock on the same failure.

What

Trusted publishing (OIDC) removes the secret. The publish job declares id-token: write, npm exchanges that short-lived workflow-scoped GitHub identity for publish rights, and each of the five packages names alleneubank/linear-cli + release.yml as its trusted publisher on npmjs.com.

Two things worth knowing:

  • The workflow filename is part of the trust relationship. Renaming release.yml breaks publishing until every package's config is updated. Noted in CLAUDE.md and in the job's comments.
  • It must be npm publish, not bun publish. bun cannot present an OIDC identity (oven-sh/bun#22423, open since 2025-09) and fails with missing authentication. bunfig.toml existed only to hand bun the token, so it goes too. No NPM_TOKEN fallback is left behind — a fallback would re-arm the exact failure mode this removes.

Publishing from a public repo with OIDC also produces provenance attestations automatically.

flake.nix

zig build lint has never been runnable: it shells out to ziglint, which is not installed anywhere, so it dies with FileNotFound — that is why the step is in neither CI nor any local run. The dev shell pins zig_0_16 (0.16.0, matching CI; the toolchain is not interchangeable), plus ziglint and the jq both release scripts parse manifests with.

zig build lint now executes and reports 14 pre-existing findings (11x Z030 deinit should set self.* = undefined, 2x Z010, 1x Z020; 8 of them in test files). Left alone in this PR — they are advisory and not a release gate.

Verification

  • nix flake check — passes
  • nix develop -c — zig 0.16.0, ziglint 0.5.3, jq 1.8.2
  • zig build lint — executes (previously FileNotFound)
  • both workflows parse; scripts/check-versions.sh --expect 0.3.0 and zig fmt --check pass

…glint

npm publishing has been broken for two releases. v0.2.11 (2026-02-01) and
v0.3.0 (today) both failed with a registry 404 — npm's way of saying the
token is not authorized — while the tag, the GitHub release, and the
manifests all looked correct. NPM_TOKEN was set 2025-11-28. A long-lived
secret that expires silently is the failure mode; rotating it would just
reset the clock.

Trusted publishing removes the secret entirely: the publish job declares
`id-token: write`, npm exchanges that short-lived workflow-scoped GitHub
identity for publish rights, and each package names
alleneubank/linear-cli + release.yml as its trusted publisher. The
workflow FILENAME is part of the trust relationship — renaming it breaks
publishing until every package's config is updated.

It has to be `npm publish`: bun cannot present an OIDC identity
(oven-sh/bun#22423, open since 2025-09) and fails with "missing
authentication". bunfig.toml existed only to hand bun the token, so it
goes with it. No NPM_TOKEN fallback is left behind — a fallback would
re-arm exactly the failure mode this removes. Publishing from a public
repo also gets provenance attestations for free.

Also adds flake.nix, which is what makes `zig build lint` runnable: the
step shells out to `ziglint` and dies with FileNotFound when it is
absent, which is why it never ran anywhere. The shell pins zig_0_16
(0.16.0, matching CI — the toolchain is not interchangeable) plus
ziglint and the jq both release scripts parse manifests with.

Verified: `nix flake check` passes; `nix develop -c` reports zig 0.16.0,
ziglint 0.5.3, jq 1.8.2; `zig build lint` now executes (it reports 14
pre-existing findings, left alone here); both workflows parse; the
version gate and `zig fmt --check` still pass.

The npmjs.com side (five packages) is configured separately in the web UI.
@alleneubank
alleneubank merged commit 3a3fb29 into main Aug 21, 2026
2 checks passed
@alleneubank
alleneubank deleted the chore/flake-and-trusted-publishing branch August 21, 2026 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant