lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

commit 910abf3ec8ef4d9dbdfd06935118ce73db78116f
parent 59024a1d7d24f1aca19eb5402ae57aa56c814a5c
Author: triesap <tyson@radroots.org>
Date:   Fri, 10 Apr 2026 01:44:31 +0000

release: remove local publish entrypoints

Diffstat:
Mcontract/README.md | 2+-
Mcontract/release/checklist-0.1.0.md | 4++--
Mcontract/release/runbook.md | 17+++++++++--------
Mdocs/nix.md | 3---
Mnix/apps.nix | 22----------------------
Mnix/common.nix | 1-
Dpublish-crates.sh | 32--------------------------------
Dscripts/ci/release_publish_order.sh | 187-------------------------------------------------------------------------------
8 files changed, 12 insertions(+), 256 deletions(-)

diff --git a/contract/README.md b/contract/README.md @@ -73,7 +73,7 @@ Primary commands: - `cargo run -q -p xtask -- sdk validate` - `cargo run -q -p xtask -- sdk release preflight` - `./scripts/ci/release_preflight.sh` -- `./scripts/ci/release_publish_order.sh dry-run` +- `scripts/release/rr-rs-preflight.sh <release-tag> [crate-list]` from the owning monorepo ## License diff --git a/contract/release/checklist-0.1.0.md b/contract/release/checklist-0.1.0.md @@ -4,8 +4,8 @@ - [ ] run `cargo check -q` - [ ] run `cargo test -q -p xtask` - [ ] run `./scripts/ci/release_preflight.sh` -- [ ] run `./scripts/ci/release_publish_order.sh dry-run` +- [ ] run `scripts/release/rr-rs-preflight.sh <release-tag> [crate-list]` from the owning monorepo - [ ] confirm crates.io owner and token access for the publish account -- [ ] run `./scripts/ci/release_publish_order.sh publish` +- [ ] run `scripts/release/rr-rs-publish.sh <release-tag> [crate-list]` from the owning monorepo - [ ] verify all publish-set crates are visible on crates.io at the configured release version - [ ] tag release in git and publish release notes diff --git a/contract/release/runbook.md b/contract/release/runbook.md @@ -7,17 +7,18 @@ This runbook applies to the crates listed in `contract/release/publish-set.toml` ## preflight ```bash -nix run .#release-preflight +scripts/release/rr-rs-preflight.sh <release-tag> [crate-list] ``` -This command validates: +Run preflight from the owning monorepo release surface. In `radroots-platform-v1`, the canonical entrypoint is `scripts/release/rr-rs-preflight.sh`. + +This validates: - sdk contract integrity and release policy parity - required crate coverage at `100/100/100/100` - publish crate metadata required for crates.io -The underlying repo-owned entrypoint is `./scripts/ci/release_preflight.sh`. -External release automation should call the canonical local preflight and must not replace it with forge-specific logic. +The underlying source-repo preflight lane remains `./scripts/ci/release_preflight.sh`, but publish orchestration is monorepo-owned and must not live in the source checkout. ## release tag @@ -32,18 +33,18 @@ git tag -a "v$(awk -F '\"' '/^version = / { print $2; exit }' contract/release/p ## publish simulation ```bash -nix run .#publish-dry-run +scripts/release/rr-rs-preflight.sh <release-tag> [crate-list] ``` -This runs `cargo publish --dry-run` in release order and reports deferred crates when they depend on earlier crates that are not yet published. +This runs `cargo publish --dry-run` in release order from the owning monorepo and reports deferred crates when they depend on earlier crates that are not yet published. ## publish ```bash -nix run .#publish-crates -- --publish +scripts/release/rr-rs-publish.sh <release-tag> [crate-list] ``` -This publishes in `publish_order` and waits for each crate version to become visible on crates.io before continuing. +This publishes in `publish_order` from the owning monorepo and waits for each crate version to become visible on crates.io before continuing. Set `CARGO_REGISTRY_TOKEN` or `CRATES_IO_TOKEN` in the runtime environment before the publish step. diff --git a/docs/nix.md b/docs/nix.md @@ -88,8 +88,6 @@ nix run .#coverage-report nix run .#wasm-builds nix run .#release-preflight nix run .#validate-sdk-typescript -- ./sdk-typescript -nix run .#publish-dry-run -nix run .#publish-crates -- --dry-run ``` `nix flake check` is intentionally limited to pure surfaces: @@ -121,7 +119,6 @@ nix run .#release-preflight - Flakes only see tracked files when the source is treated as a git checkout. If Nix appears to miss a new file, `git add` it first. - Do not put secrets in `flake.nix`. -- `publish-crates.sh` reads `CARGO_REGISTRY_TOKEN` or `CRATES_IO_TOKEN` from your runtime environment. ## Deferred Infrastructure diff --git a/nix/apps.nix b/nix/apps.nix @@ -98,28 +98,6 @@ in ''; }; - publish-crates = mkRepoApp { - name = "publish-crates"; - description = "Publish crates through the workspace release script"; - runtimeInputs = [ - pkgs.nix - ]; - command = coverageShellExec ''./publish-crates.sh "$@"''; - env = common.exportCoverageEnv; - pathPrefix = coveragePath; - }; - - publish-dry-run = mkRepoApp { - name = "publish-dry-run"; - description = "Run a dry-run crates publish through the workspace release script"; - runtimeInputs = [ - pkgs.nix - ]; - command = coverageShellExec ''./publish-crates.sh --dry-run "$@"''; - env = common.exportCoverageEnv; - pathPrefix = coveragePath; - }; - release-preflight = mkRepoApp { name = "release-preflight"; description = "Run release coverage refresh and preflight validation"; diff --git a/nix/common.nix b/nix/common.nix @@ -20,7 +20,6 @@ let ../Cargo.lock ../Makefile ../README.md - ../publish-crates.sh ../rust-toolchain.toml ../conformance ../contract diff --git a/publish-crates.sh b/publish-crates.sh @@ -1,32 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -cd "$root_dir" - -mode="publish" -case "${1:-}" in ---dry-run) - mode="dry-run" - shift - ;; ---publish) - mode="publish" - shift - ;; -"") ;; -*) ;; -esac - -requested="${*:-}" - -if [[ $mode == "publish" ]] && [[ -z ${CARGO_REGISTRY_TOKEN:-} ]] && [[ -n ${CRATES_IO_TOKEN:-} ]]; then - export CARGO_REGISTRY_TOKEN="${CRATES_IO_TOKEN}" -fi - -if [[ $mode == "publish" ]] && [[ -z ${CARGO_REGISTRY_TOKEN:-} ]]; then - echo "set CARGO_REGISTRY_TOKEN or CRATES_IO_TOKEN before publish" - exit 1 -fi - -exec ./scripts/ci/release_publish_order.sh "$mode" "$requested" diff --git a/scripts/ci/release_publish_order.sh b/scripts/ci/release_publish_order.sh @@ -1,187 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -cd "$root_dir" - -mode="${1:-publish}" -if [[ $mode != "publish" && $mode != "dry-run" ]]; then - echo "usage: scripts/ci/release_publish_order.sh [publish|dry-run] [crate names]" - exit 2 -fi - -requested_raw="${2:-}" -requested_raw="${requested_raw//,/ }" - -release_version="$( - awk ' - /^\[release\]/ { in_release = 1; next } - in_release && /^version = / { - gsub(/"/, "", $3); - print $3; - exit - } - ' contract/release/publish-set.toml -)" - -if [[ -z $release_version ]]; then - echo "failed to resolve release.version from contract/release/publish-set.toml" - exit 1 -fi - -order_file="$(mktemp)" - -awk ' - /^\[publish_order\]/ { in_order = 1; next } - /^\[/ && in_order { exit } - in_order && /"/ { - line = $0 - gsub(/[" ,]/, "", line) - if (length(line) > 0) print line - } -' contract/release/publish-set.toml >"$order_file" - -if [[ ! -s $order_file ]]; then - echo "publish_order.crates list is empty" - exit 1 -fi - -selected_file="$(mktemp)" -requested_file="$(mktemp)" -trap 'rm -f "$order_file" "$selected_file" "$requested_file"' EXIT - -crate_version_visible() { - local crate="$1" - curl -fsSL "https://crates.io/api/v1/crates/${crate}/${release_version}" >/dev/null 2>&1 -} - -seconds_until_http_date() { - local retry_after="$1" - python3 - "$retry_after" <<'PY' -import datetime -import email.utils -import sys - -retry_after = sys.argv[1].strip() -try: - target = email.utils.parsedate_to_datetime(retry_after) -except Exception: - print(0) - raise SystemExit(0) - -if target.tzinfo is None: - target = target.replace(tzinfo=datetime.timezone.utc) - -now = datetime.datetime.now(datetime.timezone.utc) -remaining = (target - now).total_seconds() -print(max(1, int(remaining) + 1)) -PY -} - -publish_with_retry() { - local crate="$1" - local attempt=1 - while true; do - local log_file - log_file="$(mktemp)" - if cargo publish --locked -p "$crate" >"$log_file" 2>&1; then - cat "$log_file" - rm -f "$log_file" - return 0 - fi - - cat "$log_file" - - if grep -Fq "already uploaded" "$log_file"; then - echo "crate ${crate} version ${release_version} is already uploaded" - rm -f "$log_file" - return 0 - fi - - if grep -Fq "429 Too Many Requests" "$log_file"; then - local retry_after - retry_after="$(sed -n 's/.*Please try again after \(.*GMT\).*/\1/p' "$log_file" | head -n1)" - local sleep_secs=0 - if [[ -n $retry_after ]]; then - sleep_secs="$(seconds_until_http_date "$retry_after")" - fi - if [[ $sleep_secs -le 0 ]]; then - sleep_secs=$((30 + attempt * 15)) - fi - echo "publish rate-limited for ${crate}; retry ${attempt} in ${sleep_secs}s" - rm -f "$log_file" - sleep "$sleep_secs" - attempt=$((attempt + 1)) - continue - fi - - rm -f "$log_file" - return 1 - done -} - -if [[ -n $requested_raw ]]; then - for token in $requested_raw; do - [[ -n $token ]] || continue - echo "$token" >>"$requested_file" - done - sort -u "$requested_file" -o "$requested_file" - - while IFS= read -r token; do - if ! grep -Fxq "$token" "$order_file"; then - echo "requested crate is not in publish_order.crates: ${token}" - exit 1 - fi - done <"$requested_file" - - while IFS= read -r crate; do - [[ -n $crate ]] || continue - if grep -Fxq "$crate" "$requested_file"; then - echo "$crate" >>"$selected_file" - fi - done <"$order_file" -else - cp "$order_file" "$selected_file" -fi - -while IFS= read -r crate; do - [ -n "$crate" ] || continue - if [[ $mode == "dry-run" ]]; then - log_file="$(mktemp)" - if cargo publish --dry-run --locked --allow-dirty -p "$crate" >"$log_file" 2>&1; then - cat "$log_file" - rm -f "$log_file" - continue - fi - - missing_dep="$(sed -n 's/.*no matching package named `\([^`]*\)`.*/\1/p' "$log_file" | head -n1)" - if [[ -n $missing_dep ]] && grep -Fxq "$missing_dep" "$order_file"; then - echo "dry-run defer for ${crate}: dependency ${missing_dep} is not yet published" - rm -f "$log_file" - continue - fi - - cat "$log_file" - rm -f "$log_file" - exit 1 - fi - - if crate_version_visible "$crate"; then - echo "skip ${crate}: version ${release_version} already visible on crates.io" - continue - fi - - publish_with_retry "$crate" - for attempt in $(seq 1 30); do - if crate_version_visible "$crate"; then - break - fi - if [[ $attempt == "30" ]]; then - echo "crate ${crate} version ${release_version} not visible on crates.io after publish" - exit 1 - fi - sleep 10 - done -done <"$selected_file" - -echo "publish sequence complete for release ${release_version}"