Skip to content

AB#3142 Release: gate the PyPI publish on the exe verification - #4

Merged
vosesoftware merged 1 commit into
mainfrom
fix/3142-gate-pypi-on-exe
Aug 13, 2026
Merged

vosesoftware merged 1 commit into
mainfrom
fix/3142-gate-pypi-on-exe

Conversation

@vosesoftware

Copy link
Copy Markdown
Owner

publish-pypi depended on build alone. build-windows-exe — which packs the single-file exe and asserts it answers an MCP initialize handshake — produces no artifact the publish consumes, so it ran in parallel with the publish rather than before it. A PyInstaller or packaging break would have been reported by a red job while the release was already on PyPI.

That asymmetry matters because publishing is the only irreversible step here: a PyPI version number can never be reused. A bad publish costs a version and a follow-up release; a bad tag is just git tag -d.

Change

   publish-pypi:
-    needs: build
+    needs: [build, build-windows-exe]

Job graph after

job needs
build —
build-windows-exe —
publish-pypi build, build-windows-exe
github-release publish-pypi, build-windows-exe

The two build jobs still run concurrently; only the irreversible step waits. Verified by parsing release.yml and asserting the graph: all deps resolve, no cycles, publish-pypi gated on both, github-release still last, trigger unchanged (push on v*).

Why now

Found while releasing v0.0.31. The mcp 2.0 migration swapped the SDK underneath a frozen binary — new module tree, new transitive deps — which is exactly the shape of change that breaks PyInstaller. I packed the exe and ran the smoke test locally before tagging to compensate. That manual step is no longer load-bearing.

Note

release.yml only triggers on v* tags, so merging this does not exercise it. The next tag will be the first real run; the graph assertions above are the pre-merge evidence.

publish-pypi depended on `build` alone. build-windows-exe - which packs the
single-file exe and asserts it answers an MCP initialize handshake - has no
artifact the publish consumes, so it ran in PARALLEL with the publish rather
than before it. A PyInstaller or packaging break would have been reported by a
red job while the release was already on PyPI.

That asymmetry matters because publishing is the only irreversible step in this
workflow: a PyPI version number can never be reused, so a bad publish costs a
version and a follow-up release, whereas a bad tag is just `git tag -d`.

publish-pypi now needs [build, build-windows-exe]. The graph stays a DAG and
github-release still runs last; the cost is a few minutes of Windows-runner time
before the publish, which is the right trade for an action that cannot be undone.

Found while releasing v0.0.31: the mcp 2.0 migration swapped the SDK underneath
a frozen binary, so the exe was packed and smoke-tested locally before tagging
to compensate for exactly this gap. That manual step is no longer load-bearing.

Verified by parsing release.yml and asserting the job graph: deps all resolve,
no cycles, publish-pypi gated on both build and build-windows-exe, trigger
unchanged (push on v* tags).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vosesoftware
vosesoftware merged commit ff4359c into main Aug 13, 2026
2 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.

2 participants