ci: harden release workflow - #3
Conversation
The original release.yml only published the SDK, ran a thin gate (check-drift + build), pushed every tag to `latest`, and skipped npm provenance despite having `id-token: write`. Replace with a workflow that: - Runs the full CI gate (check-drift, check-coverage, build, typecheck, test) on the tag SHA — a stale CI run on the branch cannot bless a release. - Asserts the git tag matches both packages' manifest versions, so a v0.4.0 tag with a still-0.3.0 manifest fails fast. - Derives the npm dist-tag from the tag name: -alpha/-beta/-rc go to `next`, everything else to `latest`. Avoids clobbering `latest` with pre-releases. - Publishes both `@modernrelay/omnigraph` and the MCP package, in order (SDK first so the MCP's `workspace:*` resolves at rewrite time). - Adds `--provenance` for a verifiable supply-chain attestation linking the npm tarball to this workflow run. - Writes `.npmrc` directly instead of relying on setup-node's registry-url, which pnpm publish doesn't always honor. - Gates on a `release` GitHub Environment so a stray `v*` tag push requires a manual approval before anything ships. README gains a `Releasing` section with the one-time setup (NPM_TOKEN, Environment) and the steps to cut a release.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 144b85860f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| run: | | ||
| set -euo pipefail | ||
| ver="${GITHUB_REF_NAME#v}" | ||
| if [[ "$ver" =~ -(alpha|beta|rc)\. ]]; then |
There was a problem hiding this comment.
Route all prerelease tags to
next
The dist-tag check only matches prereleases that contain -alpha., -beta., or -rc.; valid semver prereleases like v1.2.3-alpha (no dot) fall through to latest. In that case, a prerelease publish would incorrectly move npm’s stable latest tag, which is exactly what this workflow is trying to prevent.
Useful? React with 👍 / 👎.
git push --follow-tags only pushes annotated tags reachable from the pushed commits; lightweight tags (the default for `git tag <name>`) are skipped, so the release command in the README would not trigger the tag-driven release workflow. Switch to `git tag -a -m` in both the README recipe and the release.yml header comment.
The previous regex only matched `-(alpha|beta|rc)\.`, so valid SemVer prereleases without a dot (`v1.2.3-alpha`, `v1.2.3-rc`) or with other labels (`v1.2.3-0`, `v1.2.3-next`) would fall through to `latest` — the exact behavior this step was meant to prevent. Match SemVer 2.0 instead: any `-` after the version is a prerelease. Strip build metadata (`+...`) first so a stray `+sha` can't sneak a prerelease past as `latest`. Verified by hand against `-alpha`, `-alpha.1`, `-beta.2`, `-rc`, `-rc.1`, `-0`, `-next`, plain `X.Y.Z`, `X.Y.Z+meta`, and `X.Y.Z-alpha+meta`.
Summary
Replaces the stub release workflow with one that meets the bar to actually ship
@modernrelay/omnigraph+@modernrelay/omnigraph-mcp.Before: SDK-only publish, drift+build only, every tag → `latest`, no provenance.
After: both packages, full CI gate, dist-tag derived from semver, npm provenance, manual approval gate.
What changes
README gains a `Releasing` section: one-time setup (NPM_TOKEN secret, `release` Environment) and the recipe to cut a release.
One-time setup before the first release
Test plan
```
pnpm --filter @modernrelay/omnigraph publish --dry-run --no-git-checks --tag next
pnpm --filter @modernrelay/omnigraph-mcp publish --dry-run --no-git-checks --tag next
```
🤖 Generated with Claude Code
Note
Medium Risk
Touches the release/publish pipeline and npm authentication/provenance, so misconfiguration could block releases or publish under the wrong dist-tag despite limited code impact.
Overview
Upgrades
.github/workflows/release.ymlfrom a basic publish step to a gated, manual-approval release job that reruns the full CI suite on the tag SHA before publishing.The workflow now verifies the
v*tag matches both package versions, derives the npm dist-tag (nextfor prereleases, otherwiselatest), writes an explicit npm auth.npmrc, and publishes both@modernrelay/omnigraphand@modernrelay/omnigraph-mcpwith--provenance(OIDCid-token: write).README.mdadds a Releasing section documenting one-time setup (NPM token +releaseenvironment) and the annotated-tag release procedure.Reviewed by Cursor Bugbot for commit 1bd444f. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Hardened the release workflow to safely publish both
@modernrelay/omnigraphand@modernrelay/omnigraph-mcpwith full CI gating, correct dist-tags (any SemVer prerelease →next), npm provenance, and annotated-tag docs sogit push --follow-tagstriggers releases. Added a concise Releasing guide to the README.New Features
v*tag version doesn’t match both package versions.-...) →next; elselatest(ignores+meta).--provenanceandid-token: write..npmrcwithNPM_TOKENto ensurepnpm publishauth.releaseGitHub Environment.--follow-tagspushes the release tag.Migration
NPM_TOKENrepo secret (Automation token recommended).releaseEnvironment with required reviewers.Written for commit 1bd444f. Summary will update on new commits.