Skip to content

ci: publish bridges on a merged version bump, and flag drift when they aren't - #35

Merged
SanjithSambath merged 3 commits into
mainfrom
fix/release-drift-check
Jul 28, 2026
Merged

ci: publish bridges on a merged version bump, and flag drift when they aren't#35
SanjithSambath merged 3 commits into
mainfrom
fix/release-drift-check

Conversation

@SanjithSambath

@SanjithSambath SanjithSambath commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Why

agentmail-mcp 1.0.1 fixed a silent-startup regression on 2026-07-21, then sat on main unpublished for a week while npm kept serving the broken 1.0.0. Both publish workflows were workflow_dispatch-only, so shipping depended on someone remembering, and "merged but never published" produced no signal anywhere. A customer (T-590) found it before we did.

The startup bug itself was already covered — artifact.test.mjs spawns the bridge through a real symlink and asserts it starts. The gap was entirely the release step.

What

Publish on the merged version bump. The bump is the release intent and is already reviewed in the PR, so publish-npm.yml and publish-pypi.yml now trigger on pushes to main touching their respective manifests. Dispatch still works for out-of-band releases.

Don't misfire. If the version is already on the registry, publishing is skipped — so a dependency or description edit to package.json / pyproject.toml is a no-op instead of an EPUBLISHCONFLICT or a rejected PyPI re-upload. A dispatch whose typed version disagrees with package.json now fails instead of publishing something nobody asked for.

Prove it starts. After publishing, npm runs npx -y agentmail-mcp@<version> from a clean cache and requires it to reach its own argument check. 1.0.0 exited 0 with no output through the bin symlink npx uses, so "the publish succeeded" never implied "it runs". release.md documented this as a manual step; with no human left in the loop it has to run in CI. PyPI already installs each distribution into a clean virtualenv and runs the console script pre-publish, so it needs no post-publish equivalent.

Unpin the PyPI smoke test. It asserted == "1.0.0", which would have failed the build job on the first bump — i.e. on every release this automation now fires for. It reads the expected version from pyproject.toml instead.

Backstop. The public-surface audit now compares both bridges against npm's and PyPI's latest and names the workflow to run when they disagree, catching a failed publish or a bump that never released. It runs daily rather than weekly — a weekly window is the same blind spot that hid this for seven days.

Verification

  • Replaying the 2026-07-27 state (npm 1.0.0, repo 1.0.1) with a stubbed fetch: npm publishes 1.0.0 but the repo ships 1.0.1 — run the 'Publish npm bridge' workflow. PyPI was genuinely in sync and correctly stays quiet; a 503 from either registry is reported, not swallowed.
  • Resolve-step shell logic simulated for all three paths: already-published skips, version mismatch exits 1, unpublished version proceeds.
  • smoke-artifacts.sh run end-to-end via uv as CI does — builds both distributions, installs each, passes with the version read from pyproject.toml.
  • --self-test covers the local version reads, so a moved path or renamed key fails fast instead of quietly reporting agreement.

Note live-surfaces is schedule/dispatch-only and so skips on PRs; the drift check was verified locally as above.

🤖 Generated with Claude Code

https://claude.ai/code/session_01544GeWAAQvSawpyS7BbnqV

agentmail-mcp 1.0.1 fixed a silent-startup regression on 2026-07-21 and then
sat on main unpublished for a week while npm kept serving the broken 1.0.0.
Both publish workflows are workflow_dispatch, so nothing turned "merged but
unreleased" into a signal — the customer found it before we did.

- Compare packages/npm-stdio-bridge and python/stdio-bridge versions against
  npm's and PyPI's latest in the existing public-surface audit, naming the
  workflow to run when they disagree.
- Run the live surface audit daily instead of weekly; a weekly window is the
  same blind spot that hid this for seven days.
- Self-test covers the local version reads, so a moved path or renamed key
  fails fast instead of silently reporting agreement.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01544GeWAAQvSawpyS7BbnqV
@mcp-use

mcp-use Bot commented Jul 28, 2026

Copy link
Copy Markdown

Deployment #101 deployed successfully

StatusLogsURLUpdated
ReadyBuild Logs | Runtime Logs🔗 MCP URLJul 28 2026 9:29 pm

View deployment details


Deployed on Manufact.com

SanjithSambath and others added 2 commits July 28, 2026 14:24
Detection alone still left a human to remember the dispatch. The merged
version bump is the release intent and is already reviewed in the PR, so
publish on it and keep dispatch for out-of-band releases.

- Trigger on pushes to main that touch packages/npm-stdio-bridge/package.json.
- Resolve the version from package.json; a dispatch that disagrees with it
  fails instead of publishing something nobody asked for.
- Skip publishing when the version is already on npm, so a dependency or
  description edit to package.json is a no-op rather than an EPUBLISHCONFLICT.
- Smoke-test npx -y agentmail-mcp@<version> from a clean cache and require it
  to reach its own argument check. 1.0.0 exited 0 with no output through the
  bin symlink npx uses, so "the publish succeeded" never meant "it starts".
  This was a documented manual step; with no human left in the loop it has to
  run here.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01544GeWAAQvSawpyS7BbnqV
Same treatment as publish-npm.yml so neither bridge depends on someone
remembering a dispatch.

- Trigger on pushes to main that touch python/stdio-bridge/pyproject.toml.
- Skip the publish job when the version is already on PyPI, so an edit that
  doesn't bump the version is a no-op instead of a rejected re-upload.
- Stop pinning 1.0.0 in the artifact smoke test and read the expected version
  from pyproject instead. Pinned, it would have failed the build job on the
  first bump — that is, on every release the automation now fires for.

The existing pre-publish smoke test already installs each distribution into a
clean virtualenv and runs the console script, so there is no post-publish check
here as there is for npm.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01544GeWAAQvSawpyS7BbnqV
@SanjithSambath SanjithSambath changed the title ci: flag bridge versions that were merged but never published ci: publish bridges on a merged version bump, and flag drift when they aren't Jul 28, 2026
@SanjithSambath
SanjithSambath merged commit 39ab34a into main Jul 28, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant