ci: separate build and publish jobs and pin release actions

Merged
DT
2d ago
+156-55

Splits the release workflows into build and publish jobs, pins every action by commit SHA, and tightens workflow token permissions.

  • npm publish (publish.yml): the build job (read-only token, no secrets) installs, builds and packs the tarball; the publish job runs in the release environment on main only and uploads that tarball with provenance through Trusted Publishing. The release: created trigger is removed so publishing has one path, the existing version-bump-on-main flow (see below).
  • Binaries (release-binaries.yml): build jobs get a read-only token instead of contents: write, and bun install runs with --ignore-scripts. A new package job (read-only token) builds the Linux packages and checksums, including on dry runs; the release job that holds contents: write runs only on main for a real release, in the release environment, and attaches build provenance attestations to every asset. Packaging installs a pinned nfpm verified against its published SHA-256 instead of whatever is latest.
  • All workflows: permissions: {} at the top with per-job grants, actions pinned by SHA, checkouts without persisted credentials where nothing is pushed.
  • pnpm: packageManager moves to pnpm 10.34.7, and a new pnpm-workspace.yaml sets an explicit build-script allowlist (allowBuilds, nothing allowed to run) and a three-day minimumReleaseAge for newly resolved dependencies, with the SDK excluded so its releases can be adopted the same day. pnpm install --frozen-lockfile passes against the existing lockfile.

Trigger: publishing stays on version bumps merged to main, which release-binaries.yml already turns into a v* tag and GitHub release. Moving publishing onto tags would make one workflow depend on a tag another workflow pushes with GITHUB_TOKEN, which GitHub does not use to start workflows, so it would silently stop publishing. The release environment's main-only branch policy and the github.ref guard restrict where publishing can run.

Before merging: create the release environment with a deployment branch policy of main.

Open in Capy


Summary by cubic

Splits npm publishing and binary releases into separate build and publish jobs, pins all GitHub Actions by commit SHA, and reduces workflow token permissions across the repo.

  • npm publishing: the build job installs, packs, and uploads the tarball with a read-only token; the publish job runs in a new release environment on main only and uploads that tarball with npm provenance. The release: created trigger is removed so version bumps on main become the single publishing path. Before merging, create the release environment with a deployment branch policy of main.
  • Binaries: build jobs use read-only tokens and bun install runs with --ignore-scripts; the unprivileged package job assembles tar, zip, and Linux package assets, including dry-run packaging. A separate release job, gated to main in the release environment, creates the tag and release, installs nfpm pinned and verified by SHA-256 instead of latest, and attaches build provenance attestations to every release asset.
  • Hardening: all workflows declare permissions: {} at the top with per-job grants, checkouts don't persist credentials where nothing is pushed, and actions are pinned by commit SHA.
  • Dependencies: pnpm moves to 10.34.7, and a new pnpm-workspace.yaml sets an allowBuilds allowlist (nothing allowed) plus a three-day minimumReleaseAge for new dependencies, with firecrawl excluded.