101 lines
3.4 KiB
Bash
Executable File
101 lines
3.4 KiB
Bash
Executable File
#!/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."
|