Skip to content

Commit 8a17700

Browse files
committed
fix(release): scope publish-mcp.yml's validation gate to the MCP package
publish-engine.yml/publish-miner.yml/publish-ui-kit.yml already validate only their own package (a workspace test run + pack/smoke-test); publish-mcp.yml was the outlier, running the entire npm run test:ci (every workspace, every drift-check, ui:lint/build, migrations) as its gate. This coupled an MCP release to the health of the whole monorepo -- confirmed live when an unrelated packages/loopover-miner env-reference doc going stale blocked MCP's publish outright, despite MCP's own package code being completely unaffected and despite main's required CI already covering whole-repo health on every PR merge (including release-please's own release PRs). Scoped down to match its siblings: MCP's own syntax check (build:mcp) plus its own CLI test suite specifically -- npx vitest run mcp-cli-, i.e. test/unit/mcp-cli-*.test.ts (confirmed via import analysis: these import packages/loopover-mcp/package.json and spawn the built binary), not the sibling test/unit/mcp-*.test.ts files that exercise the Worker's separate remote MCP server (src/mcp/server.ts, a different deployable). Also added the "verify release commit is on main" safety check every other publish workflow already has, which publish-mcp.yml was missing in both its validate and publish jobs.
1 parent 2d62c82 commit 8a17700

1 file changed

Lines changed: 44 additions & 8 deletions

File tree

.github/workflows/publish-mcp.yml

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ concurrency:
2121
cancel-in-progress: false
2222

2323
jobs:
24-
# Unprivileged: resolves the version, runs the full test gate, and packs the tarball -- all with
24+
# Unprivileged: resolves the version, runs the MCP package's own build/test/pack, all with
2525
# contents: read only. npm ci here executes dependency lifecycle scripts; keeping that in a job
2626
# with no write/id-token permission means a compromised build dependency has nothing to abuse
2727
# (Superagent P2 / mirrors metagraphed's publish-client.yml "validate" job, codex #251).
@@ -40,6 +40,17 @@ jobs:
4040
fetch-depth: 0
4141
persist-credentials: false
4242

43+
- name: Verify release commit is on main
44+
env:
45+
RELEASE_SHA: ${{ github.sha }}
46+
run: |
47+
set -euo pipefail
48+
git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
49+
if ! git merge-base --is-ancestor "$RELEASE_SHA" refs/remotes/origin/main; then
50+
echo "::error::MCP package releases must be cut from a commit reachable from main."
51+
exit 1
52+
fi
53+
4354
- name: Setup Node
4455
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
4556
with:
@@ -77,16 +88,30 @@ jobs:
7788
- name: Install dependencies
7889
run: npm ci
7990

80-
# packages/loopover-mcp's own test suite pulls in src/mcp/find-opportunities.ts transitively
81-
# (via packages/loopover-miner/lib/opportunity-fanout.js), which imports @loopover/engine.
82-
# That package's dist/ is gitignored (see ci.yml's own build --workspace @loopover/engine
83-
# step for the same reason) -- without building it first, the MCP release validation gate below
84-
# fails with "Failed to resolve entry for package @loopover/engine" on every run.
91+
# packages/loopover-mcp's CLI test suite (test/unit/mcp-cli-*.test.ts) spawns the real binary,
92+
# which imports @loopover/engine. That package's dist/ is gitignored (see ci.yml's own
93+
# build --workspace @loopover/engine step for the same reason) -- without building it first,
94+
# the CLI test suite below fails with "Failed to resolve entry for package @loopover/engine".
8595
- name: Build loopover-engine
8696
run: npm run build --workspace @loopover/engine
8797

88-
- name: MCP release validation gate
89-
run: npm run test:release:mcp
98+
# engine/miner/ui-kit's own publish workflows only validate their OWN package (a workspace
99+
# test run + pack/smoke-test) -- mcp previously ran the full npm run test:ci (every workspace,
100+
# every drift-check, ui:lint/build, migrations, etc.), coupling an MCP release to the health of
101+
# the entire monorepo. Confirmed harmful live: an unrelated packages/loopover-miner env-reference
102+
# doc going stale blocked MCP's publish outright, even though MCP's own package code was
103+
# completely unaffected -- and main's required CI already re-verifies whole-repo health on
104+
# every PR, including release-please's own, so re-running all of it here is redundant with what
105+
# already gated the merge. Scoped down to match its siblings instead: MCP's own syntax check
106+
# (node --check, same as build:mcp) plus its own CLI test suite -- test/unit/mcp-cli-*.test.ts
107+
# specifically (imports packages/loopover-mcp and spawns the built binary), NOT the sibling
108+
# test/unit/mcp-*.test.ts files that exercise the Worker's separate remote MCP server
109+
# (src/mcp/server.ts, a different deployable entirely).
110+
- name: MCP package syntax validation
111+
run: npm run build:mcp
112+
113+
- name: MCP CLI test suite
114+
run: npx vitest run mcp-cli-
90115

91116
# Build + pack happen in THIS unprivileged job (no id-token). The privileged publish job below
92117
# never runs npm install/build, so a compromised build dependency can't reach the OIDC token.
@@ -138,6 +163,17 @@ jobs:
138163
fetch-depth: 0
139164
persist-credentials: false
140165

166+
- name: Verify release commit is on main
167+
env:
168+
RELEASE_SHA: ${{ github.sha }}
169+
run: |
170+
set -euo pipefail
171+
git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
172+
if ! git merge-base --is-ancestor "$RELEASE_SHA" refs/remotes/origin/main; then
173+
echo "::error::MCP package releases must be cut from a commit reachable from main."
174+
exit 1
175+
fi
176+
141177
- name: Setup Node
142178
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
143179
with:

0 commit comments

Comments
 (0)