Skip to content

Publish the workspace in one cargo invocation, not crate by crate - #180

Merged
aterga merged 1 commit into
mainfrom
claude/fix-publish-crate-workspace-ordering
Sep 1, 2026
Merged

Publish the workspace in one cargo invocation, not crate by crate#180
aterga merged 1 commit into
mainfrom
claude/fix-publish-crate-workspace-ordering

Conversation

@aterga

@aterga aterga commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

publish-crate.yml's verify job cannot rehearse imcp2's package for any new
release, so the first real lockstep release would fail before reaching crates.io.
It runs:

cargo publish --locked --dry-run -p imcp2-core   # passes
cargo package --locked --no-verify -p imcp2      # fails

The second command fails because packaging imcp2 resolves its imcp2-core
requirement 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 problem and dropped the build; the
resolution half was left in, 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, which is the pending 0.3.0 (#179).

Related issues

Blocks the v0.3.0 release. #179 does the version bump; without this, tagging it
gets as far as verify and stops.

Changes

  • verify — one cargo publish --locked --dry-run --workspace in place of the two per-crate commands. Cargo resolves the pair together: it packages imcp2-core first, then verifies imcp2 against a temporary local registry holding it. The rehearsal now covers the same crates in the same order as the upload, and imcp2 gets a verify build again instead of being packaged sight-unseen.
  • publish — the matching cargo publish --locked --no-verify --workspace, one step instead of two. --workspace sequences the uploads in dependency order itself, so the ordering no longer has to be spelled out and the two commands cannot drift apart.
  • Comments rewritten to explain the new arrangement, and the header's one-time-setup note corrected — it still said imcp2-core's first release was pending, but 0.2.0 is on crates.io.

imcp2-local is publish = false, so --workspace leaves 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. verify keeps contents: read and no id-token;
publish keeps id-token: write, the release environment, and
CARGO_REGISTRY_TOKEN on the single upload step.

The load-bearing claim is that the credential-holding job still compiles
nothing. Verified — --no-verify --workspace emits no Compiling or
Verifying line at all:

$ cargo publish --locked --no-verify --workspace --dry-run
   Packaging imcp2-core v0.3.0 (…/crates/imcp2-core)
    Packaged 62 files, 1.5MiB (451.1KiB compressed)
   Packaging imcp2 v0.3.0 (…)
    Packaged 20 files, 518.2KiB (153.8KiB compressed)
   Uploading imcp2-core v0.3.0 (…)
warning: aborting upload due to dry run
   Uploading imcp2 v0.3.0 (…)
warning: aborting upload due to dry run

Testing

publish-crate.yml is tag-triggered, so CI on this PR does not exercise the
change
— the validation is local, run against a 0.3.0 tree (the #179 branch),
where the current commands fail and these succeed. On main the bug is
invisible, because imcp2-core 0.2.0 is already published.

  • Reproduced the failure first: cargo package --locked --no-verify -p imcp2 fails on the 0.3.0 tree with the resolution error above, and succeeds on unmodified main — confirming it is the version skew, not the tree.
  • cargo publish --locked --dry-run --workspace (the new verify command) — passes on the 0.3.0 tree; logs Unpacking imcp2-core v0.3.0 (registry …/tmp-registry) before verifying imcp2, which is the ordering fix doing its work.
  • cargo publish --locked --no-verify --workspace --dry-run (the new publish command) — passes, no compilation, output above.
  • Workflow YAML re-parsed; job names, step order, permissions: and environment: 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 --workspace needs a recent stable
cargo. Both jobs run rustup update --no-self-update stable before use, so CI
always has it; verified locally on 1.94.1.

Checklist

  • I have read the Contributing guidelines.
  • Docs updated — the workflow's own comments; CONTRIBUTING.md's release section describes verify as "runs the suite and a dry-run package", which stays accurate.
  • No secrets, credentials, or internal-only information are included.

One thing this cannot fix

Whether imcp2-core has a trusted publisher configured on crates.io is a
registry-side setting no workflow file can assert. imcp2 has one (it has
released through here); imcp2-core has only ever been hand-published. If it
was never configured against this repository/workflow/release environment,
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

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
@aterga
aterga requested a balanced review from Copilot September 1, 2026 16:38
@aterga
aterga marked this pull request as ready for review September 1, 2026 16:38
@aterga
aterga requested a review from a team September 1, 2026 16:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@aterga
aterga merged commit 9604334 into main Sep 1, 2026
13 checks passed
@aterga aterga mentioned this pull request Sep 1, 2026
10 tasks
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.

4 participants