diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a1f1255..9ab5860 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -226,7 +226,7 @@ jobs: contents: write # push release tag + chore(release) commit issues: write # comment on released issues pull-requests: write # comment on released PRs - id-token: write # npm provenance attestation + id-token: write # npm trusted publishing (OIDC) + provenance attestation steps: - name: Checkout (full history) @@ -239,8 +239,14 @@ jobs: uses: actions/setup-node@v4 with: node-version: '22' + registry-url: https://registry.npmjs.org cache: npm + # Trusted publishing (OIDC) requires npm >= 11.5.1. Node 22 ships npm + # 10.x, which fails the token exchange with a misleading 404. + - name: Upgrade npm for trusted publishing + run: npm install -g npm@latest + # semantic-release refuses to publish when local HEAD is behind origin. # Fast-forwarding here absorbs any commit that landed after github.sha # was captured (bots, rapid successive pushes). @@ -253,9 +259,12 @@ jobs: - name: Build run: npm run build + # No NPM_TOKEN: publishing authenticates via OIDC trusted publishing. + # This requires a trusted publisher for `exostate` on npmjs.com pointing + # at this repository and workflow file; without it the token exchange + # fails with "404 ... package not found". - name: Release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} NPM_CONFIG_PROVENANCE: true run: npx --yes -p semantic-release@25 -p @semantic-release/changelog@6 -p @semantic-release/git@10 -p conventional-changelog-conventionalcommits@8 semantic-release diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a9a0ed7..876579e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,8 +2,8 @@ name: Release (manual fallback) # The primary release path is the `release` job inside ci.yml. # This workflow is a manual escape hatch — use it to cut a release without -# pushing a new commit (e.g. after fixing a broken NPM_TOKEN, or recovering -# from a release that failed mid-flight). +# pushing a new commit (e.g. after configuring the npm trusted publisher, or +# recovering from a release that failed mid-flight). on: workflow_dispatch: @@ -32,17 +32,22 @@ jobs: uses: actions/setup-node@v4 with: node-version: '22' + registry-url: https://registry.npmjs.org cache: npm + # Trusted publishing (OIDC) requires npm >= 11.5.1; Node 22 ships npm 10.x. + - name: Upgrade npm for trusted publishing + run: npm install -g npm@latest + - name: Install dependencies run: npm ci - name: Build run: npm run build + # No NPM_TOKEN — authentication is OIDC trusted publishing. - name: Release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} NPM_CONFIG_PROVENANCE: true run: npx --yes -p semantic-release@25 -p @semantic-release/changelog@6 -p @semantic-release/git@10 -p conventional-changelog-conventionalcommits@8 semantic-release diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4136a67..0c75e9a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -152,6 +152,21 @@ version from commit history, updates `CHANGELOG.md`, publishes to npm with provenance, and creates a GitHub release. Maintainers never bump versions by hand. +**Authentication uses npm [trusted publishing](https://docs.npmjs.com/trusted-publishers) +(OIDC) — there is no `NPM_TOKEN` secret.** The release job requests an OIDC +token via `id-token: write` and exchanges it with the registry, so no +long-lived credential exists to leak or rotate. Two things this depends on: + +- A trusted publisher must be configured for the package on npmjs.com, bound to + this repository and workflow file. Without it the exchange fails with + `404 OIDC token exchange error - package not found`. +- npm >= 11.5.1 is required. Node 22 ships npm 10.x, so the workflow runs + `npm install -g npm@latest` before publishing. + +The next version is derived from git tags, not from the registry. If tags are +ever lost, recreate the baseline tag at the commit the last release was +published from — the npm registry records it as `gitHead` on each version. + ## Reporting bugs Open an issue with the [bug report template](https://github.com/webcoderspeed/exostate/issues/new?template=bug_report.yml). diff --git a/package.json b/package.json index 657e124..25c8c9d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "exostate", - "version": "1.0.0", + "version": "1.0.1", "description": "Type-safe state management for React, Vue, Svelte, Solid and vanilla JS — with a built-in async query cache (stale-while-revalidate, request deduplication, retries, SSR hydration), plugins, time-travel history, persistence and transactions. A Zustand + TanStack Query alternative in one dependency-free package.", "type": "module", "main": "./dist/index.js",