Repository navigation
ci(release): remove the tag-push release workflow - #696
Conversation
Server releases go through the Manual Release workflow only. The tag-push workflow was an unused second path, and the tag that Manual Release pushes still started it: its jobs skipped, but the run waited in the deploy-prod concurrency group and took the group's one queued slot. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Drop the dead 'push a new tag' release path from the token rotation steps
The Rotating MCP_AUTH_TOKEN section still offers pushing a new tag as an alternative to dispatching Manual Release, but this PR deletes the only workflow that fired on Failure scenario: The maintainer rotates MCP_AUTH_TOKEN following this section and picks the tag branch: Suggested fixReduce the comment to the surviving path: `# Then dispatch manual_release.yml — CI takes care of the rest.`umm-actually · z-ai/glm-5.3-flash |
|
umm-actually re-reviewed at 1 new finding(s) posted (6 tracked finding(s) across all runs). Context notes
umm-actually · z-ai/glm-5.3-flash |
…o ci/remove-tag-push-release
With the tag-push release workflow removed, only release and deploy dispatches join the deploy-prod group. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Update GOVERNANCE.md's 'built from tagged commits' release claim
The Continuity section states releases are built by GitHub Actions from tagged commits, but with auto_release.yml deleted in this PR, a v* tag push no longer builds or deploys anything — releases are produced only by dispatching the Manual Release workflow. A successor or fork reading this would conclude pushing a tag cuts a release, which now silently does nothing. Failure scenario: A maintainer successor (the reader this section targets) cuts a release by pushing a v* tag per this sentence; nothing triggers, no image is published, and the release silently doesn't happen. Suggested fixRewrite the sentence to name the Manual Release workflow dispatch as the release path, e.g. 'Releases are built by GitHub Actions via the Manual Release workflow dispatch — there are no maintainer-local build steps.'umm-actually · z-ai/glm-5.3-flash |
|
Scope the signed-digest guarantee to releases since v0.38.0
Pre-existing: The Release Signing intro states every Failure scenario: A deployer or auditor picks an older release (e.g. v0.37.4) and follows SECURITY.md's verification instructions: Suggested fixRewrite the sentence to state the actual contract, e.g. "Releases since v0.38.0 include a signed digest file; earlier releases predate signing and carry no bundle."umm-actually · z-ai/glm-5.3-flash |
DEPLOY.md's MCP_AUTH_TOKEN rotation steps still offered pushing a new tag, which no longer starts a release. Ship-Check: pr-review · claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Register generate-cli-notes.sh in ShellCheck's glob list
Pre-existing: the base branch adds .github/scripts/generate-cli-notes.sh but never registers it in scripts/lint-shell.ts's SHELL_SCRIPT_GLOBS, violating AGENTS.md's rule that a new shell script's path is added there. npm run lint:shell therefore never checks the release-notes script, and the coverage test fails on this PR's merge ref, so the required checks job cannot go green until the registration lands. Failure scenario: This PR's merge ref contains the base branch's new script, so Suggested fixAdd `.github/scripts/generate-cli-notes.sh` to `SHELL_SCRIPT_GLOBS` in `scripts/lint-shell.ts` and to the expected list in `scripts/__tests__/lint-shell.test.ts` — in this PR or in the base branch's ci/cli-release-notes-filter PR, whichever merges first.umm-actually · z-ai/glm-5.3-flash |
- DEPLOY.md: the manual_release.yml row lists every called workflow and the signed digests; the MCP Registry note names the hardcoded server name a fork must rename and says a failed publish does not stop the Release; Cutting a release names the bumped files, skip_deploy, and which workflows push to main - CONTRIBUTING.md: the release-notes file exclusions become a list - SECURITY.md: the digest comparison names the tag for each target - Workflow comments name the workflows sharing the deploy-prod group, the re-dispatch remedy, and the caller job behind the registry tag Ship-Check: code-quality · claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ks change The workflows table now says the release job runs beside the registry and Docker Hub jobs after deploy, matching the needs graph and the fork note's "a failed publish does not stop the GitHub Release". The notes come from generate-notes.sh, not GitHub's auto-generated notes. The fork note names the hardcoded ghcr.io/aliasunder/vault-cortex path, and "Cutting a release" says workflow, since several jobs do the work. Ship-Check: bug-check · claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With tag pushes no longer starting a release, "built from tagged commits" could read as a release path. The Continuity list now names Manual Release and Release CLI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Responses to the PR-level findings:
🔍 ship-check · pr-monitor · claude-opus-5-5 |
|
Pin the prettier version the release bump step runs
Pre-existing: the bump step runs Failure scenario: A prettier release changes JSON formatting (or the registry-served package is tampered with): the release run's npx fetches it unpinned, the version-bump commit lands on main with server.json formatted differently than the pinned version produces, and the Suggested fixAdd an `npm ci` step before the bump step so `npx prettier` resolves the repo's locked devDependency, exactly as cli_release.yml already does before its own `npx prettier --write cli/package.json` step.umm-actually · z-ai/glm-5.3-flash |
…o ci/remove-tag-push-release
|
Verify the mcp-publisher tarball against a pinned checksum
Pre-existing: the Install step pipes the mcp-publisher tarball from a mutable GitHub release tag into execution without any checksum or digest verification, in the one job holding id-token: write. A re-uploaded asset or moved v1.7.9 tag executes attacker code that receives the repo's registry OIDC identity. The repo's own posture treats release assets as mutable — the Dockerfile digest-pins the s6 tarballs for exactly this reason, and the gitleaks workflow verifies its download's checksum. Failure scenario: The modelcontextprotocol/registry v1.7.9 release asset is replaced or its tag re-pointed (release assets on GitHub are mutable, per the repo's own Dockerfile rationale): the next Manual Release's publish job downloads and executes the trojaned binary with id-token: write; it receives the repo's registry OIDC identity and can publish an attacker-controlled server.json entry to the official MCP Registry under io.github.aliasunder/vault-cortex. Suggested fixPin the tarball's sha256 alongside MCP_PUBLISHER_VERSION and verify before extracting, mirroring the Dockerfile's s6 digest pins:
yaml
- name: Install mcp-publisher (pinned)
env:
# Bump together with MCP_PUBLISHER_VERSION; take the value from the release's .sha256 asset at bump time.
MCP_PUBLISHER_TARBALL_SHA256: "<sha256 of v1.7.9 mcp-publisher_linux_amd64.tar.gz>"
run: |
curl -sSLo /tmp/mcp-publisher.tar.gz \
"https://github.com/modelcontextprotocol/registry/releases/download/v${MCP_PUBLISHER_VERSION}/mcp-publisher_linux_amd64.tar.gz"
echo "${MCP_PUBLISHER_TARBALL_SHA256} /tmp/mcp-publisher.tar.gz" | sha256sum -c
tar xzf /tmp/mcp-publisher.tar.gz mcp-publisher
umm-actually · z-ai/glm-5.3-flash |
|
Responses to the PR-level findings:
🔍 ship-check · pr-monitor · claude-opus-5-5 |
Summary
Server releases go through the Manual Release workflow only, so this removes the unused tag-push release workflow and updates the docs to describe one release path. Removing it also frees a slot in the
deploy-prodconcurrency group: the tag that Manual Release pushes as the release App still startedauto_release.yml, whose jobs all skipped but whose run waited in the group and took its one queued slot (for v0.55.0 that run was cancelled two seconds after a CLI release was dispatched)..github/workflows/auto_release.yml: deleted.DEPLOY.md: CI/CD intro, workflow table (row removed; themanual_release.ymlanddockerhub-description.ymlrows describe the one release workflow), the "Why two release paths?" note removed, the MCP Registry note, and "Cutting a release" reduced to the Manual Release steps.CONTRIBUTING.md: Release Process describes Manual Release only; the branch-ruleset sentence no longer mentions a tag push's version-bump PR.SECURITY.md: thecosign verify-blobidentity regexp acceptsmanual_release.ymlonly..github/workflows/publish-registry.yml: the checkout comment names the one workflow that pushes the release tag.Signing identity
Every published
v*release that has adigests.txt.sigstore.jsonwas signed bymanual_release.yml. I downloaded the bundle for every server release and read the certificate's subject alternative name:https://github.com/aliasunder/vault-cortex/.github/workflows/manual_release.yml@refs/heads/main.No release was signed by
auto_release.yml, so the narrowed regexp still verifies every signed release.Test plan
actionlint .github/workflows/publish-registry.yml: no findings. A fullactionlintrun reports only the two existing shellcheck notes incli_release.yml.npx markdownlint-cli2 DEPLOY.md CONTRIBUTING.md SECURITY.md: 0 issues.npx prettier --checkon the changed files: all formatted.npm test: 5749 passed, 1 failed. The failure isscripts/__tests__/lint-shell.test.ts("checks every shell script in the repo when given no paths"): its expected list lacks.github/scripts/generate-cli-notes.sh, which the base branch adds. This PR does not touch that script or the test.CHANGELOG.md) forauto_release, "Auto Release" and "tag push": no references to the removed workflow remain. The two "tag push" hits left, inmanual_release.ymlandcli_release.yml, describe each workflow's own atomic push.🤖 Generated with Claude Code