From 2deba0f7fa297fdfd42c6d1327b2654c7d1c8a59 Mon Sep 17 00:00:00 2001 From: Aviator 5 Date: Fri, 5 Jun 2026 15:47:29 +0300 Subject: [PATCH] fix(ci): send User-Agent when polling crates.io API is_published()/wait_visible() called the crates.io API via curl without a User-Agent header. crates.io's data-access policy rejects UA-less requests with HTTP 403, so the -sf curl failed silently, is_published always returned false, and wait_visible spun for 5 minutes before erroring out even though the crate had already been published. Send a descriptive UA header. Stopgap alongside the --workspace dry-run fix until the release pipeline is migrated off the hand-rolled publish logic to release-plz (#96). Signed-off-by: Aviator 5 --- .github/workflows/release.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cf92142..15834bc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -465,9 +465,16 @@ jobs: set -euo pipefail VERSION="${{ needs.validate.outputs.version }}" + # crates.io enforces an API data-access policy: requests without a descriptive + # User-Agent are rejected with HTTP 403. Without -H the -sf curl fails silently, + # is_published always returns false, and wait_visible spins for 5min then errors + # even though the crate is already live. Always send a UA identifying this workflow. + CRATES_UA="gts-rust release workflow (+https://github.com/GlobalTypeSystem/gts-rust)" + is_published() { local crate="$1" - curl -sf --max-time 15 --retry 3 "https://crates.io/api/v1/crates/${crate}/${VERSION}" \ + curl -sf --max-time 15 --retry 3 -H "User-Agent: ${CRATES_UA}" \ + "https://crates.io/api/v1/crates/${crate}/${VERSION}" \ | jq -e --arg v "${VERSION}" '.version.num == $v' > /dev/null 2>&1 }