@@ -84,12 +84,13 @@ jobs:
8484
8585 - name : Collect publishable rs-soroban-sdk crates
8686 run : |
87- # Collect the publishable rs-soroban-sdk crates and their directories once, from
88- # the authoritative cargo metadata, deriving the path from manifest_path rather
89- # than assuming the package name matches the directory name. The list is reused
90- # by the patching steps below.
87+ # Collect the publishable rs-soroban-sdk crates, their directories, and their
88+ # versions once, from the authoritative cargo metadata, deriving the path from
89+ # manifest_path rather than assuming the package name matches the directory
90+ # name. The list (name<TAB>dir<TAB>version) is reused by the patching steps
91+ # below.
9192 (cd ${{ github.workspace }}/rs-soroban-sdk && cargo metadata --format-version 1 --no-deps) \
92- | jq -r '.packages[] | select(.publish != []) | "\(.name)\t\(.manifest_path | sub("/Cargo.toml$"; ""))"' \
93+ | jq -r '.packages[] | select(.publish != []) | "\(.name)\t\(.manifest_path | sub("/Cargo.toml$"; ""))\t\(.version) "' \
9394 > "$RUNNER_TEMP/sdk-crates.tsv"
9495
9596 - name : Patch SDK versions
@@ -104,7 +105,7 @@ jobs:
104105 echo "$files" | sort -u | while read -r file; do
105106 echo Patching "$file" ...
106107 dir=$(dirname "$file")
107- while IFS=$'\t' read -r crate crate_dir; do
108+ while IFS=$'\t' read -r crate crate_dir version ; do
108109 rel_path=$(realpath --relative-to="$dir" "$crate_dir")
109110 sed -i 's|'"$crate"' = "\([^"]*\)"|'"$crate"' = { path = "'"$rel_path"'" }|g' "$file"
110111 sed -i 's|'"$crate"' = {.*version = "[^"]*"\(.*\)|'"$crate"' = { path = "'"$rel_path"'" \1|g' "$file"
@@ -138,25 +139,35 @@ jobs:
138139 # A [patch] entry adds the path crate's version to crates.io resolution,
139140 # but on its own it leaves a transitive edge the lock pinned to a
140141 # different registry version untouched.
141- # 2. cargo update each crate so that edge re-resolves onto the patched
142- # version, leaving a single local copy in the graph. (Can't rescue an
142+ # 2. Pin each patched crate that the lock already references to the local
143+ # checkout's version with `cargo update --precise`, so the transitive
144+ # edges move onto it. Pinning (rather than letting cargo pick the highest
145+ # compatible version) stops a newer *published* SDK from being chosen for a
146+ # transitive edge and re-splitting the graph. (Can't rescue an
143147 # incompatible-major transitive dep, so the matrix exclusion is still
144148 # needed.)
145149 workspace_root=$(cargo metadata --format-version 1 --no-deps | jq -r '.workspace_root')
146150 if [ -s "$RUNNER_TEMP/sdk-crates.tsv" ]; then
147151 # Don't emit a second [patch.crates-io] header if one already exists upstream.
148152 grep -q '^\[patch\.crates-io\]' "$workspace_root/Cargo.toml" || printf '\n[patch.crates-io]\n' >> "$workspace_root/Cargo.toml"
149- while IFS=$'\t' read -r crate crate_dir; do
153+ while IFS=$'\t' read -r crate crate_dir version ; do
150154 rel_path=$(realpath --relative-to="$workspace_root" "$crate_dir")
151155 echo "$crate = { path = \"$rel_path\" }" >> "$workspace_root/Cargo.toml"
152156 done < "$RUNNER_TEMP/sdk-crates.tsv"
153- # Re-resolve only the patched crates that are actually in the graph.
154- graph=$(cargo metadata --format-version 1 | jq -r '.packages[].name')
155- while IFS=$'\t' read -r crate crate_dir; do
156- if grep -qxF "$crate" <<< "$graph"; then
157- cargo update -p "$crate"
157+ # Build the -p specs from crates the committed lock already references.
158+ # All crates share one workspace version, so a single --precise re-resolves
159+ # everything in one pass (no stale intermediate locks).
160+ specs=()
161+ precise=
162+ while IFS=$'\t' read -r crate crate_dir version; do
163+ if grep -q "^name = \"$crate\"\$" "$workspace_root/Cargo.lock"; then
164+ specs+=( -p "$crate" )
165+ precise=$version
158166 fi
159167 done < "$RUNNER_TEMP/sdk-crates.tsv"
168+ if [ "${#specs[@]}" -gt 0 ]; then
169+ cargo update "${specs[@]}" --precise "$precise"
170+ fi
160171 fi
161172
162173 - name : Diff
0 commit comments