#!/usr/bin/env bash set -euo pipefail # Config via env GITEA_URL="${GITEA_URL:-https://git.biohazardvfx.com}" OWNER="${OWNER:-Nicholai}" REPO="${REPO:-bandit-runner}" : "${TOKEN:?Set TOKEN env var with a Gitea API token}" # curl wrapper: returns body on stdout, sets HTTP_CODE global api() { # $1=METHOD $2=/path $3=[json-body] local m="$1" p="$2" body="${3:-}" tmp http tmp="$(mktemp)" if [[ -n "$body" ]]; then http="$(curl -fsS -o "$tmp" -w '%{http_code}' -X "$m" \ "${GITEA_URL%/}/api/v1${p}" \ -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ -d "$body")" || { rm -f "$tmp"; echo "curl failed $m $p" >&2; exit 1; } else http="$(curl -fsS -o "$tmp" -w '%{http_code}' -X "$m" \ "${GITEA_URL%/}/api/v1${p}" \ -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json")" || { rm -f "$tmp"; echo "curl failed $m $p" >&2; exit 1; } fi HTTP_CODE="$http" cat "$tmp" rm -f "$tmp" } # Get existing labels once (map name->id) declare -A LABEL_IDS load_labels() { local body; body="$(api GET "/repos/$OWNER/$REPO/labels")" if [[ "$HTTP_CODE" != "200" ]]; then echo "List labels failed: HTTP $HTTP_CODE" >&2; echo "$body" >&2; exit 1 fi # requires jq while IFS=$'\t' read -r id name; do LABEL_IDS["$name"]="$id" done < <(jq -r '.[] | "\(.id)\t\(.name)"' <<<"$body") } json() { # name color desc -> compact JSON jq -c -n --arg n "$1" --arg c "$2" --arg d "$3" '{name:$n, color:$c, description:$d}' } # Gitea accepts hex with or without leading '#'. We'll strip '#'. hex() { echo "${1#\#}"; } upsert() { # name color desc local n="$1" c="$(hex "$2")" d="$3" payload code body id id="${LABEL_IDS[$n]:-}" payload="$(json "$n" "$c" "$d")" if [[ -n "$id" ]]; then body="$(api PATCH "/repos/$OWNER/$REPO/labels/$id" "$payload")" code="$HTTP_CODE" if [[ "$code" != "200" ]]; then echo "Update $n failed: HTTP $code $body" >&2; exit 1; fi echo "updated: $n (#$c)" else body="$(api POST "/repos/$OWNER/$REPO/labels" "$payload")" code="$HTTP_CODE" if [[ "$code" == "201" ]]; then echo "created: $n (#$c)" elif [[ "$code" == "422" ]]; then # race/exists: reload ids, patch load_labels id="${LABEL_IDS[$n]:-}" [[ -z "$id" ]] && { echo "cannot find $n after 422"; exit 1; } body="$(api PATCH "/repos/$OWNER/$REPO/labels/$id" "$payload")" [[ "$HTTP_CODE" == "200" ]] || { echo "update after 422 failed: $body"; exit 1; } echo "updated: $n (#$c)" else echo "create $n failed: HTTP $code $body" >&2; exit 1 fi fi } # ---- run ---- command -v jq >/dev/null || { echo "jq not found"; exit 1; } load_labels upsert "type:feat" "#3b82f6" "new feature" upsert "type:fix" "#ef4444" "bug fix" upsert "type:docs" "#10b981" "documentation" upsert "type:chore" "#64748b" "internal chore" upsert "area:ui" "#a855f7" "frontend UI" upsert "area:runner" "#f59e0b" "run coordination" upsert "area:infra" "#0ea5e9" "infra and deploy" upsert "area:tooling" "#14b8a6" "dev tooling" upsert "prio:high" "#dc2626" "high priority" upsert "prio:med" "#d97706" "medium priority" upsert "prio:low" "#16a34a" "low priority" upsert "status:blocked" "#111827" "blocked" upsert "status:ready" "#22c55e" "ready to pick up" upsert "status:in-progress" "#2563eb" "in progress" echo "done."