Skip to content

Commit c1b606f

Browse files
charlielyeclaude
andauthored
fix(release): publish the Rust crates from staged copies, not the checkout (#25686)
## Problem Every nightly release since Oct 16 (#25362) has failed in the release stage, after ipc-runtime is published ([latest log](http://ci.aztec-labs.com/1792728566760151)): ``` + ipc-codegen/bootstrap.sh release ERROR: Noticed changes to rebuild patterns during CI run: ipc-runtime/rust/Cargo.toml ``` `ipc-runtime`'s `release_crate` wrote the release version into the tracked `rust/Cargo.toml` and copied the C++ sources into `rust/cpp`, all in place. `ipc-codegen` (`^ipc-runtime/rust/`) and `barretenberg/rust` (`^ipc-runtime/(rust|cpp)/`) both hash those paths, and in CI a content hash over modified files is a hard error. `barretenberg/rust`'s release also rewrote its own workspace and `barretenberg-rs` Cargo.toml in place, so it would have hit the same error once ipc-codegen got past it. ## Fix Publish both crates from staged copies in a temp dir, so the checkout is never modified during a release: - **ipc-runtime:** a new `stage_crate <version> <dir>` copies Cargo.toml, build.rs, `src/` and the C++ sources into `<dir>/ipc-runtime/rust` and sets the version there. `release_crate` publishes from that copy. Its verify build now runs without a `../cpp` sibling, so it checks that the crate is self-contained. - **barretenberg/rust:** stages ipc-runtime with `stage_crate` and copies its own workspace (without `target/`) beside it. The `../../../ipc-runtime/rust` path dependency then resolves to the staged ipc-runtime at the release version. Both version edits are made in the copy, and it publishes from there. The published crates are the same as before. The other release steps don't touch tracked files: noir's version edit goes to `noir/packages/*/package.json`, which is neither tracked nor hashed. ## Testing (local) - `cargo package` (with verify) on the staged ipc-runtime: compiles on its own. - `DRY_RUN=1 REF_NAME=v7.0.0-test.1 barretenberg/rust/bootstrap.sh release`: runs to the publish step, and `git status` stays clean. - `cargo package -p barretenberg-rs` on a staged workspace at `7.0.0-nightly.20261023` (already on crates.io): packages, and the manifest pins `ipc-runtime = "=7.0.0-nightly.20261023"`, as the old in-place edit did. Not run: a real `cargo publish`, and barretenberg-rs's full verify build, which needs the matching GitHub release. The next nightly will run both. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_016kciXnp1Yc2jptqABHLg2w Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 8bf338b commit c1b606f

2 files changed

Lines changed: 33 additions & 18 deletions

File tree

‎barretenberg/rust/bootstrap.sh‎

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,33 +74,40 @@ function release {
7474

7575
local version=${REF_NAME#v}
7676

77-
# Set the workspace version to match the release tag
78-
sed -i "s/^version = \".*\"/version = \"$version\"/" Cargo.toml
79-
8077
# Generated files must exist (created during build step, or generate now)
8178
if [ ! -d barretenberg-rs/src/generated ]; then
8279
echo "Generated files not found, generating..."
8380
generate
8481
fi
8582

86-
# ipc-runtime's release (which runs first) publishes its crate at this
87-
# version; pin that exact build.
88-
sed -i -E "s|^(ipc-runtime = \{ path = \"[^\"]*\", version = \")[^\"]*|\1=$version|" barretenberg-rs/Cargo.toml
89-
9083
# Check if this version is already published on crates.io (idempotent re-runs).
9184
if crate_published barretenberg-rs $version; then
9285
echo "barretenberg-rs@$version already published on crates.io. Skipping."
9386
return 0
9487
fi
9588

96-
# Publish to crates.io (--allow-dirty because version was just set and generated files are gitignored)
89+
# Publish from a staged copy so the checkout is left untouched. ipc-runtime's
90+
# crate is staged beside it, at the same relative path and at this version, so
91+
# the path dependency resolves; ipc-runtime's release (which runs first)
92+
# publishes that build, and the version pin below names it exactly.
93+
local stage=$(mktemp -d)
94+
local dest=$stage/barretenberg/rust
95+
"$root/ipc-runtime/bootstrap.sh" stage_crate $version $stage
96+
mkdir -p $dest
97+
tar -c --exclude=./target . | tar -x -C $dest
98+
sed -i "s/^version = \".*\"/version = \"$version\"/" $dest/Cargo.toml
99+
sed -i -E "s|^(ipc-runtime = \{ path = \"[^\"]*\", version = \")[^\"]*|\1=$version|" $dest/barretenberg-rs/Cargo.toml
100+
101+
# --allow-dirty because generated files are gitignored
97102
local extra_flags=""
98103
if ! gh release view "v$version" --repo AztecProtocol/barretenberg &>/dev/null; then
99104
# No matching GitHub release yet — skip verification build (which would try to download libbb-external.a)
100105
echo "No GitHub release found for v$version, adding --no-verify (pass REF_NAME matching a release for full verification)"
101106
extra_flags="--no-verify"
102107
fi
103-
BB_LIB_DIR="$(cd ../cpp/build/lib && pwd)" retry "denoise 'do_or_dryrun cargo publish --allow-dirty $extra_flags -p barretenberg-rs'"
108+
local bb_lib_dir="$(cd ../cpp/build/lib && pwd)"
109+
(cd $dest && BB_LIB_DIR="$bb_lib_dir" retry "denoise 'do_or_dryrun cargo publish --allow-dirty $extra_flags -p barretenberg-rs'")
110+
rm -rf $stage
104111
}
105112

106113
function test_download {

‎ipc-runtime/bootstrap.sh‎

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ function crate_published {
7171
curl -sf -H "User-Agent: aztec-packages-ci (tech@aztec-labs.com)" "https://crates.io/api/v1/crates/ipc-runtime/$1" | jq -e '.version.num' &>/dev/null
7272
}
7373

74+
# Stage the publishable crate, at <version>, in <dir>/ipc-runtime/rust. The
75+
# checkout is left untouched: other projects hash these files later in the run.
76+
# The crate compiles the C++ runtime itself, so it ships a copy of the sources.
77+
function stage_crate {
78+
local version=$1 dest=$2/ipc-runtime/rust
79+
mkdir -p $dest/cpp
80+
cp -r rust/Cargo.toml rust/build.rs rust/src $dest/
81+
cp -r cpp/ipc_runtime $dest/cpp/
82+
find $dest/cpp -name '*.test.cpp' -delete
83+
sed -i "0,/^version = \".*\"/s//version = \"$version\"/" $dest/Cargo.toml
84+
}
85+
7486
# Publish the Rust crate to crates.io. barretenberg-rs depends on it at the
7587
# same version, and its release runs after this one.
7688
function release_crate {
@@ -81,16 +93,12 @@ function release_crate {
8193
return 0
8294
fi
8395

84-
# The crate compiles the C++ runtime itself, so it ships a copy of the sources.
85-
rm -rf rust/cpp
86-
mkdir -p rust/cpp
87-
cp -r cpp/ipc_runtime rust/cpp/
88-
find rust/cpp -name '*.test.cpp' -delete
89-
sed -i "0,/^version = \".*\"/s//version = \"$version\"/" rust/Cargo.toml
90-
96+
local stage=$(mktemp -d)
97+
stage_crate $version $stage
9198
# Verification builds the packaged crate on its own, which proves the copied
92-
# sources are complete.
93-
(cd rust && retry "denoise 'do_or_dryrun cargo publish --allow-dirty'")
99+
# sources are complete. --allow-dirty in case the temp dir is inside a git repo.
100+
(cd $stage/ipc-runtime/rust && retry "denoise 'do_or_dryrun cargo publish --allow-dirty'")
101+
rm -rf $stage
94102
}
95103

96104
function release {

0 commit comments

Comments
 (0)