From 3b17321f0d3c48cf0e7b896fc6024426bbbd1b39 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 1 Jun 2026 12:08:03 +0200 Subject: [PATCH 1/2] style: inline files array in package.json to satisfy biome The release version bump left "files": ["dist"] formatted multi-line, which biome check rejects. CI's test:ci script doesn't run biome check (only the local pre-commit hook does), so this slipped onto main. --- packages/react-router-devtools/package.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/react-router-devtools/package.json b/packages/react-router-devtools/package.json index e1a7d36..208a7d5 100644 --- a/packages/react-router-devtools/package.json +++ b/packages/react-router-devtools/package.json @@ -55,9 +55,7 @@ "default": "./dist/server.js" } }, - "files": [ - "dist" - ], + "files": ["dist"], "repository": { "type": "git", "url": "git+https://github.com/forge-42/react-router-devtools.git" From 81befa36f88b29795d807a673382736025f420b4 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Mon, 1 Jun 2026 12:20:42 +0200 Subject: [PATCH 2/2] ci: harden release with OIDC trusted publishing (no tokens), drop PAT Replaces the PAT-based approach with npm Trusted Publishing (OIDC), mirroring TanStack's release flow. This removes long-lived publishing secrets entirely and addresses the security review findings. - npm auth via OIDC: add .npmrc provenance=true + id-token:write, and remove the NPM_TOKEN secret usage. Requires a trusted publisher to be configured for react-router-devtools on npmjs.com. - Drop the RELEASE_GITHUB_TOKEN PAT; the changesets action uses only the ephemeral GITHUB_TOKEN (to open the Release PR + create GH releases). - Pin all action versions to commit SHAs (supply-chain hardening). - Guard the job to this repo + main only (covers workflow_dispatch), so a dispatch can never publish from a non-main ref or a fork. - Pin Node 24 (npm 11) so OIDC works if pnpm delegates to npm publish. - Drop unused actions:write permission; add concurrency (no cancel). - Keep workflow_dispatch as a guarded manual recovery valve. --- .github/workflows/publish.yaml | 110 +++++++++++++++++++-------------- .npmrc | 1 + 2 files changed, 63 insertions(+), 48 deletions(-) create mode 100644 .npmrc diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 212e8c7..08b1e25 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -1,48 +1,62 @@ -name: Release - -on: - push: - branches: - - main - -jobs: - release: - name: Release - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - actions: write - id-token: write - steps: - - name: Checkout Repo - uses: actions/checkout@v3 - - - name: Install pnpm - uses: pnpm/action-setup@v4 - - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version-file: "package.json" - - - name: Install Dependencies - run: pnpm install - - # - name: 🔐 Setup npm auth - # run: | - # echo "registry=https://registry.npmjs.org" >> ~/.npmrc - # echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc - - - name: Create Release Pull Request or Publish to npm - id: changesets - uses: changesets/action@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - with: - title: "🚀 Release PR" - commit: "chore: release" - version: pnpm run version - publish: pnpm run release - createGithubReleases: true +name: Release + +on: + push: + branches: + - main + # Manual safety valve: re-run publish for a version that was bumped but never + # published. Guarded below so a dispatch can only ever publish from main. + workflow_dispatch: + +concurrency: + # Never cancel an in-progress release; queue concurrent runs instead. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +permissions: + contents: write # push the version PR branch, create tags + GitHub releases + pull-requests: write # open/update the changesets "Release PR" + id-token: write # npm Trusted Publishing (OIDC) — no long-lived NPM_TOKEN needed + +jobs: + release: + name: Release + # Don't run on forks; only ever publish from main (incl. workflow_dispatch). + if: github.repository_owner == 'code-forge-io' && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + # Required so changesets/action can push the version PR branch. Only the + # ephemeral GITHUB_TOKEN is persisted (auto-expires at job end) — no PAT. + persist-credentials: true + + - name: Install pnpm + uses: pnpm/action-setup@739bfe42ca9233c5e6aca07c1a25a9d34aca49b0 # v6.0.7 + + - name: Setup Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + # Pin to Node 24 (ships npm 11.x) so OIDC Trusted Publishing works even + # if pnpm delegates publishing to npm. npm OIDC needs >= 11.5.1. + node-version: "24" + + - name: Install Dependencies + run: pnpm install + + - name: Create Release Pull Request or Publish to npm + id: changesets + uses: changesets/action@6a0a831ff30acef54f2c6aa1cbbc1096b066edaf # v1.7.0 + env: + # Only used to open/update the Release PR and create GitHub releases. + # npm authentication is handled by OIDC Trusted Publishing (.npmrc + # provenance=true + id-token:write) — there is intentionally no NPM_TOKEN. + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + title: "🚀 Release PR" + commit: "chore: release" + version: pnpm run version + publish: pnpm run release + createGithubReleases: true diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..268c392 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +provenance=true