Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 36 additions & 6 deletions scripts/cascade-publish.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,17 @@
# - Workspace version already bumped (Cargo.toml + per-crate Cargo.toml refs)
# - Cargo.lock regenerated (cargo check --workspace)
# - All workspace tests pass
# - CARGO_REGISTRY_TOKEN exported or `cargo login` already run
# - A VALID crates.io token in ~/.cargo/credentials.toml (`cargo login`).
#
# AUTH GOTCHA (v0.60.0, ~2h lost): if $CARGO_REGISTRY_TOKEN is exported with a
# STALE value, cargo uses it over the valid credentials file and every upload
# fails "403 authentication failed" (dry-runs pass — they skip upload). Run this
# with `unset CARGO_REGISTRY_TOKEN` unless you KNOW the env token is fresh.
#
# CONFIG GOTCHA (v0.60.0): publish from a tree with NO .cargo/config.toml. The
# dev-only [patch.crates-io] there points siblings at ../<repo> paths that don't
# exist in a git worktree → "failed to load source". Remove it first; the
# consolidated monorepo resolves siblings via in-tree path deps.
#
# This script bypasses `make publish` (which has a known issue with .cargo/config.toml
# stub interaction on some crates per the v0.34.0 cascade observation) and uses
Expand All @@ -20,7 +30,7 @@ set +e # don't exit on individual crate failures — track each and report at e

# Tier definitions per SPEC-HF-PUBLISH-001 § crates.io release cascade.
declare -A TIERS
TIERS[1]="aprender-contracts-macros aprender-quant aprender-gemm-codegen aprender-sparse aprender-solve aprender-rand aprender-fft aprender-image aprender-tensor aprender-cupti"
TIERS[1]="apr-format aprender-contracts-macros aprender-quant aprender-gemm-codegen aprender-sparse aprender-solve aprender-rand aprender-fft aprender-image aprender-tensor aprender-cupti"
TIERS[2]="aprender-contracts aprender-core aprender-profile-core aprender-graph"
TIERS[3]="aprender-profile"
TIERS[4]="aprender-gpu"
Expand All @@ -32,7 +42,7 @@ TIERS[9]="aprender-present-core aprender-present-layout aprender-present-yaml ap
TIERS[10]="apr-cli"
TIERS[11]="aprender"
TIERS[12]="aprender-tsp aprender-monte-carlo aprender-shell"
TIERS[13]="aprender-test-derive aprender-test-lib aprender-test-js-gen aprender-test-cli aprender-test-showcase aprender-zram-core aprender-zram-adaptive aprender-zram-generator aprender-zram-cli aprender-zram aprender-present-test-macros aprender-present-test aprender-present-lib aprender-present-cli aprender-db aprender-rag aprender-viz aprender-registry aprender-distribute aprender-simulate aprender-verify aprender-verify-ml aprender-train-shell aprender-train-inspect aprender-train-bench aprender-train-wasm aprender-contracts-cli"
TIERS[13]="aprender-test-derive aprender-test-lib aprender-test-js-gen aprender-test-cli aprender-test-showcase aprender-zram-core aprender-zram-adaptive aprender-zram-generator aprender-zram-cli aprender-zram aprender-present-test-macros aprender-present-test aprender-present-lib aprender-present-cli aprender-db aprender-rag aprender-viz aprender-registry aprender-distribute aprender-simulate aprender-verify aprender-verify-ml aprender-train-shell aprender-train-inspect aprender-train-bench aprender-train-wasm aprender-contracts-cli aprender-rag-cli"

TARGET_VERSION=$(grep -E '^version = "' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
[ -z "$TARGET_VERSION" ] && { echo "ERROR: could not detect target version from Cargo.toml"; exit 1; }
Expand All @@ -43,7 +53,12 @@ ONLY_TIER="${2:-}"

check_version() {
local crate=$1
curl -s "https://crates.io/api/v1/crates/$crate" 2>/dev/null \
# crates.io REJECTS requests without a User-Agent (returns an error page, not
# JSON) — omitting it made this always print "none", which silently broke the
# --check STATUS report AND the FINAL VERIFICATION gate (every crate looked
# unpublished). Always send a UA. (v0.60.0 cascade lesson.)
curl -s -H "User-Agent: aprender-cascade-publish (release automation)" \
"https://crates.io/api/v1/crates/$crate" 2>/dev/null \
| python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('crate',{}).get('max_version','none'))" 2>/dev/null
}

Expand All @@ -56,18 +71,33 @@ publish_crate() {
fi
echo -n " → $crate ($cur → $TARGET_VERSION): "
local out
out=$(cargo publish -p "$crate" --allow-dirty --locked 2>&1 | tail -3)
out=$(cargo publish -p "$crate" --allow-dirty --locked 2>&1 | tail -6)
if echo "$out" | grep -q "Published $crate"; then
echo "✓ PUBLISHED"
sleep 10 # let crates.io index settle before dependents try to fetch
return 0
elif echo "$out" | grep -qE "already.*upload|already exists"; then
echo "(already on registry)"
return 0
# Surface the two FATAL classes that are NOT dep-ordering deferrals — a bare
# "Caused by:" truncation hid both for ~2h in the v0.60.0 cascade:
# 1. 403 authentication failed — a STALE $CARGO_REGISTRY_TOKEN env var
# overrides a valid ~/.cargo/credentials.toml. Fix: `unset
# CARGO_REGISTRY_TOKEN` so the file token is used (or refresh the env one).
# 2. failed to load source for dependency `<sibling>` — a dev-only
# [patch.crates-io] in .cargo/config.toml points at ../<repo> paths that
# don't exist in a worktree. Fix: remove .cargo/config.toml before publish
# (the consolidated monorepo resolves siblings via in-tree path deps).
elif echo "$out" | grep -qiE "403|authentication failed"; then
echo "FATAL-AUTH (403 — unset stale \$CARGO_REGISTRY_TOKEN; use ~/.cargo/credentials.toml)"
return 1
elif echo "$out" | grep -qiE "failed to load source|no such file or directory"; then
echo "FATAL-CONFIG (dev [patch.crates-io] in .cargo/config.toml — remove it before publish)"
return 1
else
local err
err=$(echo "$out" | grep -oE "candidate versions found which didn't match:.*$" | head -1)
[ -z "$err" ] && err=$(echo "$out" | grep -oE "Caused by:.*$" | head -1)
[ -z "$err" ] && err=$(echo "$out" | grep -oiE "(error|caused by)[:].*$" | head -1)
[ -z "$err" ] && err=$(echo "$out" | head -1)
echo "DEFER ($err)"
return 1
Expand Down
Loading