diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml deleted file mode 100644 index f6ca2b3..0000000 --- a/.github/actionlint.yaml +++ /dev/null @@ -1,2 +0,0 @@ -self-hosted-runner: - labels: [blacksmith-4vcpu-ubuntu-2404] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9b2ef36..90ed748 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ concurrency: jobs: check: name: Check and package - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 @@ -43,10 +43,13 @@ jobs: name: Publish to npm needs: check if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' - runs-on: blacksmith-4vcpu-ubuntu-2404 + # npm trusted publishing requires a GitHub-hosted runner. + # Publish only the archive produced and tested by the check job. + runs-on: ubuntu-latest timeout-minutes: 10 permissions: contents: write + id-token: write steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: @@ -65,19 +68,14 @@ jobs: - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 if: steps.package.outputs.published == 'false' with: - node-version: '22' + node-version: '24' registry-url: https://registry.npmjs.org - name: Publish the tested archive if: steps.package.outputs.published == 'false' env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} ARCHIVE: ${{ steps.package.outputs.archive }} run: | - if [ -z "$NODE_AUTH_TOKEN" ]; then - echo 'Set the NPM_TOKEN repository secret with a granular npm publish token.' >&2 - exit 1 - fi - npm publish "release/$ARCHIVE" --access public --ignore-scripts + npm publish "release/$ARCHIVE" --access public --ignore-scripts --provenance - name: Create GitHub release if: steps.package.outputs.published == 'false' env: diff --git a/README.md b/README.md index e8efaab..2cd9be9 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@
@@ -302,7 +302,7 @@ The interface follows the Agent964 design system and the Balanced playground dir Bug reports and focused PRs are welcome. See [CONTRIBUTING.md](https://github.com/malhashemi/workflow-observer/blob/main/CONTRIBUTING.md) for local setup and checks. Run `bun run demo` for an isolated workspace with synthetic workflows. -CI uses **Blacksmith runners**. To release, run `bun run release:prepare patch` on your PR branch and commit the version changes. Merging to `main` runs checks, publishes the tested npm archive and creates a GitHub release. Merges without a new version skip publishing. The [release guide](https://github.com/malhashemi/workflow-observer/blob/main/docs/releasing.md) covers setup and retries. +CI runs on **GitHub-hosted runners** and publishes through **npm trusted publishing**, with provenance and no stored npm token. To release, run `bun run release:prepare patch` on your PR branch and commit the version changes. Merging to `main` runs checks, publishes the tested npm archive and creates a GitHub release. Merges without a new version skip publishing. The [release guide](https://github.com/malhashemi/workflow-observer/blob/main/docs/releasing.md) covers setup and retries. ## License diff --git a/docs/releasing.md b/docs/releasing.md index f695962..f0b68c0 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -1,6 +1,6 @@ # Releasing -CI runs on Blacksmith. A push to `main`, including a merged PR, builds the app, runs TypeScript/OXC checks and tests, and exercises the packed CLI with isolated data. The release job publishes that tested archive when its version is absent from npm, then creates a matching GitHub tag and release. A version already on npm is skipped. PR checks never receive the publishing token. +CI runs on GitHub-hosted runners. A push to `main`, including a merged PR, builds the app, runs TypeScript/OXC checks and tests, and exercises the packed CLI with isolated data. A separate release job publishes that tested archive through npm trusted publishing, then creates a matching GitHub tag and release. A version already on npm is skipped. No npm token is stored in GitHub. ## Release a change @@ -18,12 +18,11 @@ Version preparation only changes package metadata and the lockfile. It does not ## One-time setup -1. Enable the Blacksmith GitHub App for this repository. Both jobs use `blacksmith-4vcpu-ubuntu-2404`. -2. Authenticate with npm and confirm ownership of `workflow-observer`. If this is the first publication, use the manual bootstrap below. -3. Create a granular npm token with read/write access to this package and **Bypass two-factor authentication** enabled for unattended publication. Store it as the repository Actions secret **NPM_TOKEN**. Set an expiration reminder and replace the secret when rotating the token. -4. Require **Check and package** before merging into `main` in the repository's branch rules. +1. Enable GitHub Actions for this repository. Both jobs use `ubuntu-latest`. +2. In [the npm package settings](https://www.npmjs.com/package/workflow-observer/access), add a **GitHub Actions** trusted publisher with owner **malhashemi**, repository **workflow-observer**, and workflow filename **ci.yml**. Leave the environment name empty and allow direct publishing. The package must already exist; use the manual bootstrap below for a new package. +3. Require **Check and package** before merging into `main` in the repository's branch rules. -[npm trusted publishing](https://docs.npmjs.com/trusted-publishers/) currently supports GitHub-hosted runners, not self-hosted runners. This workflow uses a token so publishing stays on Blacksmith. It does not request npm provenance or claim OIDC authentication. Node is used only by the CI npm publisher; Observer itself runs on Bun. +[npm trusted publishing](https://docs.npmjs.com/trusted-publishers/) currently supports GitHub-hosted runners, not self-hosted runners. The publishing job uses `id-token: write` and Node 24. npm exchanges the workflow's short-lived OIDC identity for permission to publish and attaches provenance. Observer itself runs on Bun. For the first publication, from a checked-out release commit: @@ -37,11 +36,11 @@ bun run test:package npm publish ./workflow-observer-0.9.4.tgz --access public --ignore-scripts ``` -Use the archive for the version in `package.json`. After bootstrap, the CI token can be restricted to the newly created package. +Use the archive for the version in `package.json`. After bootstrap, configure its trusted publisher once. Later releases require no npm login or token rotation. ## Retry a release -Fix a missing/expired `NPM_TOKEN` or Blacksmith access issue, then rerun the failed workflow from Actions. Transient registry errors fail explicitly instead of being treated as an unpublished version. +Fix the reported failure, then rerun the workflow from Actions. For authentication failures, check the exact owner, repository and workflow filename against npm's saved publisher. Transient registry errors fail explicitly instead of being treated as an unpublished version. If npm succeeded but GitHub release creation failed, the published version is immutable. Create the missing release against the original successful run's commit, and attach its `npm-package` artifact: diff --git a/package.json b/package.json index fca8089..2d5812b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "workflow-observer", - "version": "0.9.4", + "version": "0.9.5", "private": false, "type": "module", "scripts": { @@ -47,7 +47,14 @@ "bugs": { "url": "https://github.com/malhashemi/workflow-observer/issues" }, - "keywords": ["claude", "workflow", "agents", "observer", "local", "bun"], + "keywords": [ + "claude", + "workflow", + "agents", + "observer", + "local", + "bun" + ], "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/"