Files
api-company/scripts/setup-sibling-repos-token.sh
T
0xWheatyz f841c2216b
Validate Flux manifests / kustomize-build (pull_request) Successful in 21s
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.
2026-06-20 18:04:16 -04:00

69 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# Create the Gitea PATs the build-docs workflow needs and store them as action
# secrets on leeworks-agents/api-company:
# - SIBLING_REPOS_TOKEN : read:repository (clone the sibling API repos)
# - REGISTRY_TOKEN : write:package + read:package
# (push the docs-site image to gitea.leeworks.dev)
#
# Why this script exists:
# - The auto-injected GITEA_TOKEN is scoped to THIS repo only (can't read
# sibling repos) and has no package-registry scope (can't push images).
# GITEA_TOKEN is also a reserved secret name that cannot be overridden.
# - `tea` cannot CREATE a PAT (no such command), and Gitea's token-creation
# API requires BASIC AUTH (your password) — a token cannot mint a token.
# - `tea` CAN set the action secrets using its existing login.
#
# So: this prompts for your password ONCE, mints both PATs via the API, and
# pipes each straight into `tea`. Token values are never written to disk.
#
# Usage: bash scripts/setup-sibling-repos-token.sh
set -euo pipefail
GITEA_URL="https://gitea.leeworks.dev"
GITEA_USER="0xWheatyz"
REPO="leeworks-agents/api-company"
# 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; }
command -v python3 >/dev/null || { echo "python3 required"; exit 1; }
echo "Gitea user: $GITEA_USER ($GITEA_URL)"
read -r -s -p "Gitea password (for $GITEA_USER): " GITEA_PASS
echo
failures=0
# mint_token <token-name> <json-scopes-array> <secret-name>
mint_token() {
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")"
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}')"
}
# 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 (${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 ]