Skip to content

Merge pull request #5 from ModernRelay/fix/mcp-repository-and-idempot… #2

Merge pull request #5 from ModernRelay/fix/mcp-repository-and-idempot…

Merge pull request #5 from ModernRelay/fix/mcp-repository-and-idempot… #2

Workflow file for this run

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