Publish the workspace in one cargo invocation, not crate by crate - #180
Merged
Conversation
The verify job cannot rehearse imcp2's package for any new release. It runs
cargo publish --locked --dry-run -p imcp2-core
cargo package --locked --no-verify -p imcp2
and the second command fails, because packaging imcp2 resolves
`imcp2-core = "=<this release>"` against crates.io — where only the PREVIOUS
release exists. The version being released is uploaded by the publish job,
which verify gates, so the requirement cannot be satisfied at the moment it
is checked:
error: failed to select a version for the requirement `imcp2-core = "^0.3.0"`
candidate versions found which didn't match: 0.2.0
`--no-verify` is not the escape hatch it looks like: it skips the compile, not
the dependency resolution that packaging performs. The step's comment
anticipated the verify-build half of this and dropped the build; the
resolution half was left, and it is the half that fails.
This has never fired because imcp2-core has never been released through this
workflow — 0.2.0 was hand-published, and the lockstep pin has named an
already-published version ever since. It fires on the first real lockstep
release.
Publish the workspace in one invocation instead. Cargo then resolves the two
crates together: it packages imcp2-core first and verifies imcp2 against a
temporary local registry holding it, so the rehearsal covers the same crates
in the same order as the upload, and imcp2 gets a verify build again rather
than being packaged sight-unseen. The publish job takes the matching
`--workspace` form, which sequences the uploads in dependency order itself —
one step instead of two that could drift apart.
The job split that keeps dependency code away from the credential is
unchanged, and the rewritten comments say why it still holds: `--no-verify`
on a workspace publish emits no Compiling or Verifying step at all, so the
credential-holding job still compiles nothing. Verified against a 0.3.0 tree,
where the current commands fail and these succeed.
Also correct the header's one-time-setup note, which still said imcp2-core's
first release was pending; 0.2.0 is on crates.io. Whether its trusted
publisher is configured is a crates.io-side setting this file cannot assert,
so the note now says each crate needs its own or its upload 403s.
Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GqhkbpCwxs67F5E2EzyDwh
sea-snake
approved these changes
Sep 1, 2026
There was a problem hiding this comment.
Pull request overview
Updates the crates.io release workflow to publish interdependent workspace crates in one Cargo invocation.
Changes:
- Verifies all publishable crates together with
cargo publish --dry-run --workspace. - Publishes crates in dependency order using
cargo publish --no-verify --workspace. - Clarifies trusted-publisher setup and credential-isolation comments.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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
publish-crate.yml'sverifyjob cannot rehearseimcp2's package for any newrelease, so the first real lockstep release would fail before reaching crates.io.
It runs:
The second command fails because packaging
imcp2resolves itsimcp2-corerequirement against crates.io, where only the previous release exists. The
version being released is uploaded by the
publishjob — whichverifygates —so the requirement cannot be satisfied at the moment it is checked:
--no-verifyis not the escape hatch it looks like: it skips the compile, notthe dependency resolution that packaging performs. The step's comment
anticipated the verify-build half of this problem and dropped the build; the
resolution half was left in, and it is the half that fails.
This has never fired because
imcp2-corehas never been released through thisworkflow — 0.2.0 was hand-published, and the lockstep pin has named an
already-published version ever since. It fires on the first real lockstep
release, which is the pending 0.3.0 (#179).
Related issues
Blocks the
v0.3.0release. #179 does the version bump; without this, tagging itgets as far as
verifyand stops.Changes
verify— onecargo publish --locked --dry-run --workspacein place of the two per-crate commands. Cargo resolves the pair together: it packagesimcp2-corefirst, then verifiesimcp2against a temporary local registry holding it. The rehearsal now covers the same crates in the same order as the upload, andimcp2gets a verify build again instead of being packaged sight-unseen.publish— the matchingcargo publish --locked --no-verify --workspace, one step instead of two.--workspacesequences the uploads in dependency order itself, so the ordering no longer has to be spelled out and the two commands cannot drift apart.imcp2-core's first release was pending, but 0.2.0 is on crates.io.imcp2-localispublish = false, so--workspaceleaves it out on its own — confirmed in the runs below.The job split is unchanged
The supply-chain property this file is built around still holds, and the
rewritten comments say why.
verifykeepscontents: readand noid-token;publishkeepsid-token: write, thereleaseenvironment, andCARGO_REGISTRY_TOKENon the single upload step.The load-bearing claim is that the credential-holding job still compiles
nothing. Verified —
--no-verify --workspaceemits noCompilingorVerifyingline at all:Testing
publish-crate.ymlis tag-triggered, so CI on this PR does not exercise thechange — the validation is local, run against a 0.3.0 tree (the #179 branch),
where the current commands fail and these succeed. On
mainthe bug isinvisible, because
imcp2-core 0.2.0is already published.cargo package --locked --no-verify -p imcp2fails on the 0.3.0 tree with the resolution error above, and succeeds on unmodifiedmain— confirming it is the version skew, not the tree.cargo publish --locked --dry-run --workspace(the newverifycommand) — passes on the 0.3.0 tree; logsUnpacking imcp2-core v0.3.0 (registry …/tmp-registry)before verifyingimcp2, which is the ordering fix doing its work.cargo publish --locked --no-verify --workspace --dry-run(the newpublishcommand) — passes, no compilation, output above.permissions:andenvironment:blocks unchanged apart from the two steps described.cargo build/cargo test/npm test— not applicable, no Rust or dashboard code in this diff.One dependency worth naming:
cargo publish --workspaceneeds a recent stablecargo. Both jobs run
rustup update --no-self-update stablebefore use, so CIalways has it; verified locally on 1.94.1.
Checklist
CONTRIBUTING.md's release section describesverifyas "runs the suite and a dry-run package", which stays accurate.One thing this cannot fix
Whether
imcp2-corehas a trusted publisher configured on crates.io is aregistry-side setting no workflow file can assert.
imcp2has one (it hasreleased through here);
imcp2-corehas only ever been hand-published. If itwas never configured against this repository/workflow/
releaseenvironment,its upload will 403 on the first run — worth checking before tagging, since by
then the tag is spent. The header note now says so.
🤖 Generated with Claude Code
https://claude.ai/code/session_01GqhkbpCwxs67F5E2EzyDwh
Generated by Claude Code