Skip to content

Commit d06db2b

Browse files
committed
probe: retry the write, and do not narrate garbage while sweeping
Review caught that the probe treated any one-shot POST failure as a bad credential. GitHub answers 403 for secondary rate limiting as well as for refusal -- the publish step retries six times for exactly that reason -- and these repos return 504 on ordinary release listings often enough that one was hit while writing this change. A blip would have failed the nightly with "the token is wrong", sending whoever read it off to reissue a credential that was never the problem. The POST now retries three times with 5s and 10s backoff, and the error says "after 3 attempts ... if this is not a transient API error". Three rather than the publish step`s six because the value here is failing fast: a genuine misconfiguration still surfaces in well under a minute instead of after the whole matrix. Testing the retry then exposed a second defect, in the sweep added by the previous commit. gh writes its error body to STDOUT, so a failed list feeds the cleanup loop lines of JSON instead of release ids, and the log filled with `removing stranded probe draft {"status": "401"}`. The deletes were harmless -- they simply failed -- but a step whose entire purpose is to be believed must not narrate confident nonsense. Only numeric ids are acted on now. Verified against the live repo: happy path creates the draft, reports OK, the trap removes it, nothing is left behind; a refused credential retries three times and fails with the honest message; a failing list produces zero bogus removal lines.
1 parent df38594 commit d06db2b

1 file changed

Lines changed: 31 additions & 7 deletions

File tree

.github/workflows/build.yml

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -223,17 +223,41 @@ jobs:
223223
gh api "repos/${GH_REPO}/releases?per_page=10" \
224224
--jq '.[] | select(.draft and (.tag_name | startswith("ci-release-credential-probe-"))) | .id' \
225225
2>/dev/null | while read -r stale; do
226+
# gh writes its error body to STDOUT, so a failed list feeds this
227+
# loop lines of JSON rather than ids. Deleting them is harmless --
228+
# the calls just fail -- but logging "removing stranded probe
229+
# draft {"status": "401"}" is a confident lie in the log of a step
230+
# whose whole job is to be believed. Only act on real ids.
231+
case "$stale" in ''|*[!0-9]*) continue ;; esac
226232
echo "removing stranded probe draft $stale"
227233
gh api -X DELETE "repos/${GH_REPO}/releases/${stale}" >/dev/null 2>&1 || true
228234
done || true
229235
230-
if ! probe_id=$(gh api -X POST "repos/${GH_REPO}/releases" \
231-
-f tag_name="$PROBE_TAG" -f name="$PROBE_TAG" \
232-
-F draft=true --jq .id); then
233-
echo "::error::RELEASE_TOKEN cannot create releases in ${GH_REPO}."\
234-
"It needs Contents: read and write."
235-
exit 1
236-
fi
236+
# Retried, because a one-shot POST cannot tell a bad credential from
237+
# a bad minute. GitHub answers 403 for secondary rate limiting as
238+
# well as for refusal -- the publish step below retries six times for
239+
# exactly that reason -- and these repos return 504 on ordinary
240+
# release listings often enough to have been seen while writing this.
241+
# Reporting a blip as "the token is wrong" would send whoever reads
242+
# it to reissue a credential that was never the problem.
243+
#
244+
# Three attempts rather than the publish step's six: the value here is
245+
# failing fast, and 5s + 10s of backoff still absorbs a transient
246+
# while keeping a genuine misconfiguration well under a minute.
247+
attempt=0
248+
until probe_id=$(gh api -X POST "repos/${GH_REPO}/releases" \
249+
-f tag_name="$PROBE_TAG" -f name="$PROBE_TAG" \
250+
-F draft=true --jq .id); do
251+
attempt=$((attempt + 1))
252+
if [ "$attempt" -ge 3 ]; then
253+
echo "::error::RELEASE_TOKEN could not create a release in"\
254+
"${GH_REPO} after 3 attempts. If this is not a transient API"\
255+
"error, the token needs Contents: read and write."
256+
exit 1
257+
fi
258+
echo "attempt ${attempt} failed, retrying in $((attempt * 5))s"
259+
sleep $((attempt * 5))
260+
done
237261
echo "release credential OK"
238262
239263
buildroot:

0 commit comments

Comments
 (0)