From f841c2216b33fde7744eb6fd5e9ebf9983f5e757 Mon Sep 17 00:00:00 2001 From: Wyatt Date: Sat, 20 Jun 2026 18:04:16 -0400 Subject: [PATCH] fix(scripts): unique PAT names + show HTTP error body in token helper Re-running the helper hit Gitea 400 'token name has been used' because the token name was only date-stamped. Add time+pid to make names unique, surface the real HTTP status/body, and continue past a single token failure. --- scripts/setup-sibling-repos-token.sh | 35 ++++++++++++++++++---------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/scripts/setup-sibling-repos-token.sh b/scripts/setup-sibling-repos-token.sh index b80dd6a..0e55d1f 100755 --- a/scripts/setup-sibling-repos-token.sh +++ b/scripts/setup-sibling-repos-token.sh @@ -22,7 +22,9 @@ set -euo pipefail GITEA_URL="https://gitea.leeworks.dev" GITEA_USER="0xWheatyz" REPO="leeworks-agents/api-company" -STAMP="$(date +%Y%m%d)" +# Unique per run (date + seconds + pid) so re-runs never collide with an +# existing PAT name — Gitea returns 400 "token name has been used" otherwise. +STAMP="$(date +%Y%m%d-%H%M%S)-$$" command -v curl >/dev/null || { echo "curl required"; exit 1; } command -v tea >/dev/null || { echo "tea required"; exit 1; } @@ -32,26 +34,35 @@ echo "Gitea user: $GITEA_USER ($GITEA_URL)" read -r -s -p "Gitea password (for $GITEA_USER): " GITEA_PASS echo +failures=0 + # mint_token mint_token() { - local token_name="$1" scopes="$2" secret_name="$3" resp pat - resp="$(curl -fsS -X POST \ + local token_name="$1" scopes="$2" secret_name="$3" body code pat + # Capture body + HTTP status separately so 4xx errors show the real message. + body="$(curl -sS -o - -w $'\n%{http_code}' -X POST \ -u "${GITEA_USER}:${GITEA_PASS}" \ -H 'Content-Type: application/json' \ -d "{\"name\":\"${token_name}\",\"scopes\":${scopes}}" \ - "${GITEA_URL}/api/v1/users/${GITEA_USER}/tokens")" || { - echo "Token '${token_name}' creation failed. Check password / 2FA (2FA blocks basic-auth token creation)." >&2 - return 1 - } - pat="$(printf '%s' "$resp" | python3 -c 'import sys,json; print(json.load(sys.stdin)["sha1"])')" - [ -n "$pat" ] || { echo "Could not parse token from: $resp" >&2; return 1; } + "${GITEA_URL}/api/v1/users/${GITEA_USER}/tokens")" + code="${body##*$'\n'}" + body="${body%$'\n'*}" + if [ "$code" -lt 200 ] || [ "$code" -ge 300 ]; then + echo " ✗ ${secret_name}: token API returned HTTP ${code}: ${body}" >&2 + echo " (401/403 = wrong password or 2FA; 400 = duplicate name or bad scope)" >&2 + failures=$((failures+1)); return 1 + fi + pat="$(printf '%s' "$body" | python3 -c 'import sys,json; print(json.load(sys.stdin)["sha1"])' 2>/dev/null || true)" + [ -n "$pat" ] || { echo " ✗ ${secret_name}: could not parse token from: ${body}" >&2; failures=$((failures+1)); return 1; } printf '%s' "$pat" | tea actions secrets create "$secret_name" --repo "$REPO" --stdin echo " ✓ ${secret_name} set (PAT '${token_name}')" } -mint_token "sibling-repos-readonly-${STAMP}" '["read:repository"]' "SIBLING_REPOS_TOKEN" -mint_token "docs-registry-${STAMP}" '["write:package","read:package"]' "REGISTRY_TOKEN" +# Don't let one failure abort the rest. +mint_token "sibling-repos-readonly-${STAMP}" '["read:repository"]' "SIBLING_REPOS_TOKEN" || true +mint_token "docs-registry-${STAMP}" '["write:package","read:package"]' "REGISTRY_TOKEN" || true unset GITEA_PASS -echo "Done. Verify: tea actions secrets list --repo ${REPO}" +echo "Done (${failures} failure(s)). Verify: tea actions secrets list --repo ${REPO}" echo "Then re-run build-docs (push to main, or: tea actions workflows dispatch build-docs.yaml)" +[ "$failures" -eq 0 ]