Merge pull request #5 from ModernRelay/fix/mcp-repository-and-idempot… #2
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: release | |
| # Publishes both workspace packages when a `v*` tag is pushed. The dist-tag | |
| # is derived from the tag name: pre-releases (`v1.2.3-alpha.1`, `-beta.x`, | |
| # `-rc.x`) ship under `next`; everything else under `latest`. | |
| # | |
| # Setup the first time: | |
| # 1. `gh secret set NPM_TOKEN` with an "Automation" token from npmjs.com | |
| # (Automation tokens bypass 2FA in CI; granular tokens scoped to the | |
| # `@modernrelay` packages are fine if your account has Automation | |
| # disabled). | |
| # 2. Repo Settings → Environments → create `release` → require manual | |
| # approval. Without this gate, any push of a `v*` tag publishes. | |
| # | |
| # To cut a release (note: the tag MUST be annotated so `git push --follow-tags` | |
| # actually pushes it — lightweight tags are skipped by --follow-tags): | |
| # pnpm --filter @modernrelay/omnigraph version 0.4.0-alpha.1 | |
| # pnpm --filter @modernrelay/omnigraph-mcp version 0.4.0-alpha.1 | |
| # git commit -am "Release 0.4.0-alpha.1" | |
| # git tag -a v0.4.0-alpha.1 -m "Release 0.4.0-alpha.1" | |
| # git push --follow-tags | |
| # # then approve the `release` environment in the Actions UI. | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| jobs: | |
| publish: | |
| runs-on: ubuntu-latest | |
| environment: release | |
| permissions: | |
| contents: read | |
| id-token: write # npm provenance attestation | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: pnpm/action-setup@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| # Gates — same bar as ci.yml, run again on the exact tag SHA so a stale | |
| # CI run cannot bless a release. | |
| - run: pnpm run check-drift | |
| - run: pnpm run check-coverage | |
| - run: pnpm run build | |
| - run: pnpm run typecheck | |
| - run: pnpm run test | |
| - name: Verify tag matches package versions | |
| run: | | |
| set -euo pipefail | |
| tag_version="${GITHUB_REF_NAME#v}" | |
| for pkg in packages/sdk packages/mcp; do | |
| pkg_version=$(node -p "require('./${pkg}/package.json').version") | |
| if [ "$tag_version" != "$pkg_version" ]; then | |
| echo "Tag ${GITHUB_REF_NAME} does not match ${pkg}/package.json version (${pkg_version})" | |
| exit 1 | |
| fi | |
| done | |
| - name: Derive npm dist-tag | |
| id: tag | |
| # SemVer 2.0: a `-` after the version is a prerelease, regardless of | |
| # the label (`-alpha`, `-rc.1`, `-0`, `-next`, etc.). Any prerelease | |
| # ships under `next`; only plain `X.Y.Z` (and `X.Y.Z+meta`) → `latest`. | |
| # Strip build metadata first so a stray `+sha` doesn't confuse the | |
| # check. | |
| run: | | |
| set -euo pipefail | |
| ver="${GITHUB_REF_NAME#v}" | |
| ver_no_meta="${ver%%+*}" | |
| if [[ "$ver_no_meta" == *-* ]]; then | |
| echo "dist=next" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "dist=latest" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Configure npm auth | |
| # `setup-node`'s registry-url doesn't reliably propagate the auth | |
| # token to pnpm publish; write the token explicitly. | |
| run: echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" > "$HOME/.npmrc" | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| # SDK first — MCP's workspace:* dependency resolves to the just-published | |
| # version once pnpm rewrites the manifest at publish time. | |
| # | |
| # Each step skips if `pkg@ver` is already on npm. Lets us re-run a tag | |
| # after a partial-failure (e.g. SDK published, MCP rejected on a manifest | |
| # issue) without npm rejecting the SDK with EPUBLISHCONFLICT. | |
| - name: Publish @modernrelay/omnigraph | |
| working-directory: packages/sdk | |
| run: | | |
| set -euo pipefail | |
| pkg=$(node -p "require('./package.json').name") | |
| ver=$(node -p "require('./package.json').version") | |
| existing=$(npm view "${pkg}@${ver}" version 2>/dev/null || true) | |
| if [ -n "$existing" ]; then | |
| echo "${pkg}@${ver} already on npm — skipping" | |
| else | |
| pnpm publish --no-git-checks --access public --provenance --tag ${{ steps.tag.outputs.dist }} | |
| fi | |
| - name: Publish @modernrelay/omnigraph-mcp | |
| working-directory: packages/mcp | |
| run: | | |
| set -euo pipefail | |
| pkg=$(node -p "require('./package.json').name") | |
| ver=$(node -p "require('./package.json').version") | |
| existing=$(npm view "${pkg}@${ver}" version 2>/dev/null || true) | |
| if [ -n "$existing" ]; then | |
| echo "${pkg}@${ver} already on npm — skipping" | |
| else | |
| pnpm publish --no-git-checks --access public --provenance --tag ${{ steps.tag.outputs.dist }} | |
| fi |