From 4656387af16c65b9653aaa44276272441d6c6309 Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Wed, 29 Jul 2026 09:47:17 +1200 Subject: [PATCH 1/2] ci: publish to npm on version tags via Trusted Publishing (OIDC) Adds a release workflow that triggers on v* tags, verifies the tag matches package.json, builds, and publishes with npm Trusted Publishing (no NPM_TOKEN secret; provenance attached automatically). RELEASING.md documents the one-time npm-side trusted-publisher setup and the release procedure. --- .github/workflows/release.yml | 67 +++++++++++++++++++++++++++++++++++ RELEASING.md | 56 +++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 .github/workflows/release.yml create mode 100644 RELEASING.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..191319e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,67 @@ +# Publishes @0xsequence/codegenie to npm on version tags (v*) using npm +# Trusted Publishing (OIDC) — no long-lived NPM_TOKEN secret. Provenance +# attestations are generated automatically under trusted publishing. +# +# One-time npm-side setup (package owner): on npmjs.com, add a Trusted +# Publisher to @0xsequence/codegenie pointing at this repository +# (0xPolygon/codegenie) and this workflow file (release.yml). See RELEASING.md. +name: Release + +on: + push: + tags: + - "v*" + +permissions: + contents: read + # Required for npm Trusted Publishing (OIDC token exchange) and provenance. + id-token: write + +jobs: + release: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Check out tag + uses: actions/checkout@v7 + + - name: Set up Node + uses: actions/setup-node@v7 + with: + node-version: "26" + registry-url: "https://registry.npmjs.org" + + - name: Set up pnpm + uses: pnpm/action-setup@v4 + with: + version: "11.15.1" + + - name: Verify tag matches package.json version + run: | + set -euo pipefail + pkg_version="$(node -p "require('./package.json').version")" + tag_version="${GITHUB_REF_NAME#v}" + if [ "${pkg_version}" != "${tag_version}" ]; then + echo "Tag ${GITHUB_REF_NAME} does not match package.json version ${pkg_version}" >&2 + exit 1 + fi + + - name: Ensure npm supports trusted publishing + # Trusted Publishing requires npm >= 11.5.1; upgrade to be safe. + run: | + npm install -g npm@latest + npm --version + + - name: Install dependencies + run: pnpm install --frozen-lockfile --config.ignore-scripts=false + + - name: Typecheck + run: pnpm run typecheck + + - name: Build + run: pnpm build + + - name: Publish to npm + # No NODE_AUTH_TOKEN: auth happens via the OIDC trusted-publisher + # exchange. Provenance is attached automatically. + run: npm publish --access public diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 0000000..7f0a68d --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,56 @@ +# Releasing + +`@0xsequence/codegenie` is published to npm automatically by +[`.github/workflows/release.yml`](.github/workflows/release.yml) when a +version tag is pushed. Publishing uses +[npm Trusted Publishing](https://docs.npmjs.com/trusted-publishers) (OIDC): +there is no `NPM_TOKEN` secret to manage, and provenance attestations are +generated automatically. + +## One-time setup (npm package owner) + +Someone with owner/maintainer access to `@0xsequence/codegenie` on npmjs.com +must connect the package to this repository: + +1. Go to the package on npmjs.com → **Settings** → **Trusted Publisher**. +2. Select **GitHub Actions** and enter: + - Organization or user: `0xPolygon` + - Repository: `codegenie` + - Workflow filename: `release.yml` + - Environment: leave empty (the workflow does not use one) +3. Save. Optionally set the package's publishing access to + *Require two-factor authentication or a trusted publisher* (or trusted + publisher only) so token-based publishes are disallowed. + +Until this is done, the release workflow will fail at the `npm publish` step +with an authentication error — everything else (version check, build) still +runs, so the workflow can be dry-run validated by pushing a tag before the +npm side is configured. Note: if the package later moves out of the +`@0xsequence` scope, the trusted-publisher entry must be recreated on the new +package name. + +## Cutting a release + +1. Bump `version` in `package.json` on `master` (via the normal PR flow). +2. Tag the release commit and push the tag: + + ```bash + git checkout master && git pull + git tag v$(node -p "require('./package.json').version") + git push origin v$(node -p "require('./package.json').version") + ``` + +3. The `Release` workflow verifies the tag matches `package.json`, builds, + and publishes with provenance. + +The tag must be `v` and match `package.json` exactly (e.g. `v0.5.2` +for version `0.5.2`); the workflow fails otherwise. + +## Notes + +- The full test suite is not re-run in the release workflow (it needs + actionlint and Foundry); CI on the PRs that land on `master` is the test + gate. The release workflow still typechecks and builds from scratch. +- The GitHub Action (`action.yml`) installs the npm package at the version + pinned in `package.json` of the referenced tag, so publishing to npm is the + only deployment step — action users pick it up by referencing the new tag. From 66a23dd27500a09dd0bbd753a3177d301661dad8 Mon Sep 17 00:00:00 2001 From: Michael Standen Date: Wed, 29 Jul 2026 09:50:49 +1200 Subject: [PATCH 2/2] ci: pin pnpm/action-setup to commit hash (CodeQL: unpinned 3rd-party action) --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 191319e..57a3203 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,7 @@ jobs: registry-url: "https://registry.npmjs.org" - name: Set up pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0 with: version: "11.15.1"