Skip to content

Commit 86d485a

Browse files
lwshangclaude
andauthored
ci: make crates.io publish idempotent and retry index lag (#735)
* ci: make crates.io publish idempotent and retry index lag The publish job ran six `cargo publish` commands unguarded under `set -e`. Two failure modes broke it: 1. Partial release: if a later crate fails, the already-uploaded crates can't be re-published — a re-dispatch aborts immediately on the first `cargo publish` ("crate version already uploaded"). 2. Index lag: a dependent crate (e.g. icx -> ic-utils) can fail to resolve a just-uploaded dependency until the crates.io index catches up, which can take a minute or two. Both hit the 0.48.0 release: ic-transport-types, ic-agent, ic-identity-hsm, and ic-utils published, then `icx` failed to resolve `ic-utils = ^0.48.0` because the index hadn't surfaced it yet. Wrap each publish in a helper that treats "already uploaded/exists" as success (idempotent re-runs) and retries other failures up to 6x with a 30s backoff (rides out index lag). Re-dispatching now finishes icx and icx-cert without re-publishing the four crates already live. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: skip final-attempt sleep in publish retry loop Don't sleep 30s after the last attempt fails — it only delayed the job's failure. Gate the backoff on there being another attempt to come, and include attempt count in the messages. Addresses Copilot review feedback on #735. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 7e8dc0e commit 86d485a

1 file changed

Lines changed: 33 additions & 6 deletions

File tree

.github/workflows/publish.yml

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,38 @@ jobs:
1111
- uses: rust-lang/crates-io-auth-action@b7e9a28eded4986ec6b1fa40eeee8f8f165559ec # v1
1212
id: auth
1313
- run: |
14-
cargo publish -p ic-transport-types
15-
cargo publish -p ic-agent
16-
cargo publish -p ic-identity-hsm
17-
cargo publish -p ic-utils
18-
cargo publish -p icx
19-
cargo publish -p icx-cert
14+
set -euo pipefail
15+
16+
# Publish one crate, tolerating the two things that make a naive
17+
# `cargo publish` loop brittle:
18+
# 1. Re-running after a partial release: a crate already uploaded at
19+
# this version is a success, not a failure (lets a re-dispatch
20+
# finish the crates that didn't make it the first time).
21+
# 2. crates.io index lag: a dependent crate can fail to resolve a
22+
# just-uploaded dependency for up to a minute or two. Retry.
23+
publish() {
24+
local crate="$1" attempt max=6
25+
for attempt in $(seq 1 "$max"); do
26+
if cargo publish -p "$crate" 2>&1 | tee /tmp/publish.log; then
27+
echo "== $crate published"
28+
return 0
29+
fi
30+
if grep -qiE "already (uploaded|exists)" /tmp/publish.log; then
31+
echo "== $crate already published at this version; skipping"
32+
return 0
33+
fi
34+
if [ "$attempt" -lt "$max" ]; then
35+
echo "== $crate publish attempt $attempt/$max failed (likely dependency index lag); retrying in 30s"
36+
sleep 30
37+
fi
38+
done
39+
echo "== ERROR: $crate failed to publish after $max attempts" >&2
40+
return 1
41+
}
42+
43+
# Order matters: dependencies before dependents.
44+
for crate in ic-transport-types ic-agent ic-identity-hsm ic-utils icx icx-cert; do
45+
publish "$crate"
46+
done
2047
env:
2148
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}

0 commit comments

Comments
 (0)