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..1bf1f9b2 --- /dev/null +++ b/scripts/publish-crate.sh @@ -0,0 +1,59 @@ +#!/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 + +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" +} + +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" + +wait_for_index listed > /dev/null +echo "$package $version is on crates.io"