ci(release): add MCP release-candidate dry-run workflow and checks#379
Merged
JSONbored merged 3 commits intoJun 4, 2026
Merged
Conversation
Adds a single, non-publishing preflight maintainers can run before tagging an MCP release, so release mistakes are caught before the public package is touched. - scripts/mcp-release-candidate-core.mjs: pure, deterministic checks — tag format + version match, changelog target-version section, tarball allowlist + secret scan, and tokenless trusted-publishing verification (id-token + provenance, no npm token). redactSensitive() scrubs tokens, npm credentials, GitHub auth, and absolute local paths from any output. - scripts/check-mcp-release-candidate.mjs (npm run mcp:release-candidate): reads the package version, derives or accepts --tag, runs npm pack to gate tarball contents, runs a packed-tarball CLI smoke (install + gittensory-mcp --help), verifies npm-publish.yml stays tokenless, and prints redacted PASS/FAIL plus next steps. Exits non-zero on any failure and never publishes. - .github/workflows/mcp-release-candidate.yml: manual workflow_dispatch dry-run with an optional tag input, contents:read only. - test/unit/mcp-release-candidate.test.ts: success fixture plus failure fixtures for missing changelog section, unexpected/secret-bearing tarball files, and tag/package mismatch; tokenless-config and log-redaction/public-language invariants. Global coverage unchanged and above the 97% gate (branches 97.02%, lines 99.65%, statements 99.07%, functions 98.40%); no src behavior changes.
JSONbored
approved these changes
Jun 4, 2026
Owner
JSONbored
left a comment
There was a problem hiding this comment.
@web-dev0521 this is mergeable.
A few notes:
- The workflow is manual and read-oriented, which is the right shape for a release-candidate dry run.
- The added checks improve release confidence without adding expensive PR-path CI.
- No code changes requested.
Validation expected:
- Keep the current green CI 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes: #85
npm run mcp:release-candidate(and a manualMCP Release Candidate Dry-Runworkflow) validate package version + tag format, the changelog target-version section, the tarball allowlist + secret scan, a packed-tarball CLI smoke, and that the publish workflow stays tokenless — all without publishing.What was added
scripts/mcp-release-candidate-core.mjs(+.d.mts): pure, deterministic checks —checkTag(mcp-v format + match topackage.json),checkChangelog(real dated## mcp-v<version>section),checkTarball(publish allowlist + secret-content scan),checkTokenlessPublish(id-token: write+--provenance, no npm token),buildReleaseCandidateReport(pass/fail + non-publishing next steps), andredactSensitive(scrubs tokens/credentials/paths).scripts/check-mcp-release-candidate.mjs(npm run mcp:release-candidate): reads the package version, derives or accepts--tag, runsnpm packto gate tarball contents, performs a packed-tarball CLI smoke (install into a temp project +gittensory-mcp --help), verifiesnpm-publish.ymlis tokenless, prints redactedPASS/FAILwith next steps, and exits non-zero on any failure. Never publishes..github/workflows/mcp-release-candidate.yml: manualworkflow_dispatchdry-run with an optionaltaginput;contents: readonly.test/unit/mcp-release-candidate.test.ts: success fixture plus failure fixtures (missing changelog section, unexpected tarball file, secret-bearing file, tag/package mismatch), tokenless-config checks, and log-redaction / forbidden-public-language invariants.Scope
CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlint— clean (rangithub-actionlint .github/workflows/mcp-release-candidate.ymldirectly; the npm script's glob is a Windows-only shell limitation)npm run typecheck— cleannpm run test:coveragelocally — 976 pass (1 skipped); branch 97.02%, lines 99.65%, statements 99.07%, functions 98.40% (nosrc/behavior changed, so global coverage is unchanged and above the gate; the 3 pre-existing Windows-only spawn failuresmcp-cli,github-type-label,mcp-releasewere excluded locally and are unaffected)node scripts/check-mcp-release-candidate.mjs— all five checks PASS on the current tree (exit 0); a mismatched--tagfails with clear remediation (exit 1)npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderateIf any required check was skipped, explain why:
mcp-cli/mcp-release/type-labeltooling unrelated to this change.Safety
redactSensitivescrubs tokens/credentials/paths from all dry-run output; tested.)Notes
npm publish; the packed CLI smoke installs the tarball into a throwaway temp project and removes both the temp dir and the tarball afterward. The runner uses captured (not streamed) subprocess output and redacts it before printing.checkTokenlessPublishrequiresid-token: writeand--provenanceand fails if any npm auth token (NODE_AUTH_TOKEN/NPM_TOKEN/_authToken/secrets.NPM*) appears innpm-publish.yml, keeping trusted publishing intact.set -euo pipefail) fails loudly — without ever attempting a publish.src/, so the 97% global gate is unaffected; the suite still passes with branch coverage above the threshold.