From 5041f37bb9aa234e3333a2412cb165ddc92abdae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabr=C3=ADcio=20Bracht?= Date: Sun, 11 Oct 2026 17:40:24 -0700 Subject: [PATCH 1/2] wait for crates.io and fail on publish errors in release workflow --- .github/workflows/release.yml | 17 ++++---------- scripts/publish-crate.sh | 44 +++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 13 deletions(-) create mode 100755 scripts/publish-crate.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ab074369..0f74e0a0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,31 +32,22 @@ jobs: fi - name: Publish mqtt5-protocol to crates.io - run: cargo publish --package mqtt5-protocol || echo "Version already published, skipping" + run: scripts/publish-crate.sh mqtt5-protocol env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - - name: Wait for crates.io to update - run: sleep 30 - - name: Publish mqtt5 library to crates.io - run: cargo publish --package mqtt5 || echo "Version already published, skipping" + run: scripts/publish-crate.sh mqtt5 env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - - name: Wait for crates.io to update - run: sleep 30 - - name: Publish mqtt5-wasm to crates.io - run: cargo publish --package mqtt5-wasm || echo "Version already published, skipping" + run: scripts/publish-crate.sh mqtt5-wasm env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - - name: Wait for crates.io to update - run: sleep 30 - - name: Publish mqttv5-cli to crates.io - run: cargo publish --package mqttv5-cli || echo "Version already published, skipping" + run: scripts/publish-crate.sh mqttv5-cli env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/scripts/publish-crate.sh b/scripts/publish-crate.sh new file mode 100755 index 00000000..11fb036e --- /dev/null +++ b/scripts/publish-crate.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +set -euo pipefail + +package="$1" +wait_secs=600 + +version=$(cargo metadata --no-deps --format-version 1 \ + | jq -r --arg p "$package" '.packages[] | select(.name == $p) | .version') +if [ -z "$version" ]; then + echo "package $package not found in the workspace" >&2 + exit 1 +fi + +name=$(printf '%s' "$package" | tr '[:upper:]' '[:lower:]') +case ${#name} in + 1) index_path="1/$name" ;; + 2) index_path="2/$name" ;; + 3) index_path="3/${name:0:1}/$name" ;; + *) index_path="${name:0:2}/${name:2:2}/$name" ;; +esac +index_url="https://index.crates.io/$index_path" + +is_published() { + local entries + entries=$(curl -sf -A "LabOverWire/mqtt-lib release workflow" "$index_url") || return 1 + grep -q "\"vers\":\"$version\"" <<<"$entries" +} + +if is_published; then + echo "$package $version is already on crates.io, skipping" + exit 0 +fi + +cargo publish --package "$package" + +deadline=$((SECONDS + wait_secs)) +until is_published; do + if [ "$SECONDS" -ge "$deadline" ]; then + echo "$package $version did not appear in the crates.io index within ${wait_secs}s" >&2 + exit 1 + fi + sleep 10 +done +echo "$package $version is on crates.io" From 8dcbfed2fbd459a3234d3d777d396edd347baa5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabr=C3=ADcio=20Bracht?= Date: Sun, 11 Oct 2026 18:14:31 -0700 Subject: [PATCH 2/2] retry index errors, add curl timeouts and fixed-string version match in publish script --- scripts/publish-crate.sh | 59 +++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/scripts/publish-crate.sh b/scripts/publish-crate.sh index 11fb036e..1bf1f9b2 100755 --- a/scripts/publish-crate.sh +++ b/scripts/publish-crate.sh @@ -11,34 +11,49 @@ if [ -z "$version" ]; then exit 1 fi -name=$(printf '%s' "$package" | tr '[:upper:]' '[:lower:]') -case ${#name} in - 1) index_path="1/$name" ;; - 2) index_path="2/$name" ;; - 3) index_path="3/${name:0:1}/$name" ;; - *) index_path="${name:0:2}/${name:2:2}/$name" ;; -esac -index_url="https://index.crates.io/$index_path" - -is_published() { - local entries - entries=$(curl -sf -A "LabOverWire/mqtt-lib release workflow" "$index_url") || return 1 - grep -q "\"vers\":\"$version\"" <<<"$entries" +index_url="https://index.crates.io/${package:0:2}/${package:2:2}/$package" +entries=$(mktemp) +trap 'rm -f "$entries"' EXIT + +index_status() { + local code + code=$(curl -s --connect-timeout 10 --max-time 30 \ + -A "LabOverWire/mqtt-lib release workflow" \ + -o "$entries" -w '%{http_code}' "$index_url") || code="curl exit $?" + case $code in + 200) + if grep -qF "\"vers\":\"$version\"" "$entries"; then + echo listed + else + echo absent + fi + ;; + 404) echo absent ;; + *) echo "unreachable ($code)" ;; + esac +} + +wait_for_index() { + local wanted=$1 deadline=$((SECONDS + wait_secs)) status + status=$(index_status) + until [ "$status" = listed ] || { [ "$wanted" = known ] && [ "$status" = absent ]; }; do + if [ "$SECONDS" -ge "$deadline" ]; then + echo "$package $version: crates.io index still $status after ${wait_secs}s" >&2 + exit 1 + fi + sleep 10 + status=$(index_status) + done + echo "$status" } -if is_published; then +state=$(wait_for_index known) +if [ "$state" = listed ]; then echo "$package $version is already on crates.io, skipping" exit 0 fi cargo publish --package "$package" -deadline=$((SECONDS + wait_secs)) -until is_published; do - if [ "$SECONDS" -ge "$deadline" ]; then - echo "$package $version did not appear in the crates.io index within ${wait_secs}s" >&2 - exit 1 - fi - sleep 10 -done +wait_for_index listed > /dev/null echo "$package $version is on crates.io"