Skip to content

release: keep Cargo.lock in step with the pinned busbar ref, and never publish an assetless release - #4

Merged
MattJackson merged 1 commit into
mainfrom
fix/relock-and-draft-release
Aug 8, 2026
Merged

release: keep Cargo.lock in step with the pinned busbar ref, and never publish an assetless release#4
MattJackson merged 1 commit into
mainfrom
fix/relock-and-draft-release

Conversation

@MattJackson

Copy link
Copy Markdown
Contributor

The v1.0.4 release run failed on all five targets with error: cannot update the lock file ... because --locked was passed, leaving a published Release with zero assets (since deleted by hand).

Root cause: two independent bugs in one log

1. Stale Cargo.lock vs --locked (the fatal one). Cargo.toml depends on the busbar crates as path deps into a sibling ../busbarAI checkout. release-on-upstream.yml re-pins that checkout by rewriting .busbar-ref, but never regenerated Cargo.lock. busbar 1.5.3 pulled valuable in behind tracing, so the committed lock described a graph that no longer resolved, and release.ymls --locked build refused to update it.

Reproduced exactly, then fixed and re-verified:

$ cargo metadata --locked      # before: exit 101, same error as CI
$ cargo metadata               # minimal refresh
$ cargo metadata --locked      # after: exit 0
$ cargo build --release --locked --lib   # the exact release command: Finished

--locked is deliberately kept. It is what guarantees a release builds exactly the graph resolved at pin time; dropping it would trade this loud failure for silent drift. Instead the lock is refreshed in the same step that re-pins, against the exact commit being pinned, and committed alongside .busbar-ref. Plain cargo (no --locked) is used so the resolution is minimal: 22 lines, only the valuable/tracing graph change. The refreshed lock is then proven to satisfy --locked before anything is committed or tagged, so a lock problem can no longer produce a tag at all.

Cargo.lock in this PR is that refresh for the busbar 1.5.3 ref already on main, which is otherwise unbuildable.

2. The doubled path segment is not a bug. webrequest-hook/webrequest-hook is just $GITHUB_WORKSPACE plus path: webrequest-hook. The separate could not find Cargo.toml in the parent line comes from Swatinem/rust-cache, which runs at the workspace root with no workspaces: input and so finds no manifest. It is non-fatal but means this repo has been getting no Rust caching at all. Left alone here to keep this PR to the release path; worth a follow-up (workspaces: webrequest-hook).

Structural fix: a release is now either complete or absent

create-release published the Release before the build matrix ran. verify-assets already detected the assetless result, but only after it was public, so releases/latest pointed at nothing in the meantime.

The Release is now created as a draft. Verified against a throwaway repo: a draft is invisible to releases/latest and releases/tags/<tag> (404), yet gh release upload and gh release view still resolve it by tag, and gh release edit --draft=false --latest promotes it. verify-assets promotes only once assets are provably attached.

Also: two fixtures brought up to busbar 1.5.3

Independent of the release path, and currently latent because CI pins busbar at main, which only became 1.5.3 around the time of the cascade:

  • RoutingRequest/Candidate gained request_id and signals. The fixtures pin a fixed id and an empty SignalBag; an empty bag serialises to nothing, so the forwarded envelope is unchanged.
  • Inline module entries under auth.admin_auth: were retired in 1.5.3; busbar now refuses to boot such a config. Migrated to a named identity-providers: definition referenced by bare name, matching busbars own config.yaml.

Known-red, deliberately not addressed here

Two pre-existing failures on main that this PR does not claim to fix:

  1. tests/full_stack_e2e.rs asserts one webhook call, now gets two. busbar 1.5.3 emits an additional notify carrying stage: {at: "candidate", remaining_candidates: 1}. Whether the webrequest hook should receive that candidate-stage notification is a question about the hook contract, not something to guess at. Flagged for a decision. With this PR the test at least boots and fails on that one assertion with a clear diagnostic, instead of dying at startup on the config gate.
  2. The PUBLIC-HYGIENE GATE fails on main (.github/scripts/next-version.sh and release-selftest.yml each cite an internal guard id). Fleet-wide, unrelated to this change.

Gate

cargo fmt --check, cargo clippy --all-targets -- -D warnings, cargo build --all-targets, cargo test --lib --test e2e (36 passed), and cargo build --release --locked --lib all green against a sibling busbar checkout at the pinned c8780349 (1.5.3).

…r publish an assetless release

The v1.0.4 release run failed on every target with:

  error: cannot update the lock file .../Cargo.lock because --locked was passed

Cargo.toml's busbar-* dependencies are path deps into a sibling ../busbarAI
checkout. release-on-upstream re-pins that checkout to a new commit in
.busbar-ref but never regenerated Cargo.lock, so when busbar 1.5.3 pulled
`valuable` in behind `tracing`, the committed lock described a graph that no
longer resolved and release.yml's `--locked` build correctly refused to
proceed.

`--locked` is kept deliberately: it is what makes a release build exactly the
graph that was resolved at pin time. Instead the lock is now refreshed in the
same step that re-pins, against the exact commit being pinned, and committed
alongside .busbar-ref so the two can never drift apart. Plain cargo (no
--locked) is used for that refresh so the resolution is minimal, and the result
is proven to satisfy --locked before anything is committed or tagged.

Cargo.lock here is that refresh for the busbar 1.5.3 ref already recorded on
main, which is otherwise unbuildable.

Separately, create-release published the Release before the build matrix ran,
so a total build failure left a tag whose releases/latest carried zero assets.
verify-assets already detected that, but only after the empty release was
public. The Release is now created as a draft, which releases/latest and
releases/tags/<tag> do not resolve, and verify-assets promotes it to published
only once assets are provably attached. A release is now either complete or
absent.

Also brings two test fixtures up to busbar 1.5.3: RoutingRequest/Candidate
gained request_id and signals, and inline module entries under auth.admin_auth
were retired in favour of a named identity-providers definition.
@MattJackson
MattJackson merged commit 30697b9 into main Aug 8, 2026
1 of 2 checks passed
@MattJackson
MattJackson deleted the fix/relock-and-draft-release branch August 8, 2026 19:18
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