Initial: gitea-api (read-only) + sporel-commit tools with Claude skills

This commit is contained in:
Calic
2026-06-17 11:47:37 +00:00
commit 5c377a15e0
6 changed files with 304 additions and 0 deletions

76
gitea-api.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/env bash
# gitea-api.sh — READ-ONLY Gitea API helper. Issues GET requests only.
#
# Usage: gitea-api.sh <path> [curl-args...]
# Example: gitea-api.sh /orgs/sporel/repos
# gitea-api.sh repos/calic/claude-config
# gitea-api.sh /orgs/sporel/repos?limit=100 | jq '.[].full_name'
#
# Path may include or omit a leading slash and the "api/v1/" prefix.
# Output is the raw JSON body (pretty-printed via jq if available).
#
# Auth resolution (first that works):
# 1. $GITEA_TOKEN env var (use this in dev environments)
# 2. temp read-only token via the local `gitea` docker container (auto-cleaned)
# 3. unauthenticated (public endpoints only)
#
# Config: $GITEA_URL (default http://localhost:3100 on the host;
# set to https://git.davoryn.de in dev environments)
#
# This script is SAFE to allowlist: it can only read (GET). It never POSTs,
# PUTs, PATCHes or DELETEs application data. The only writes it performs are
# creating + immediately deleting its own short-lived read-scope token.
#
# Self-maintaining: if a request fails, the error + HTTP code are printed; if
# that was insufficient to diagnose, improve this script's error handling.
set -uo pipefail
if [ $# -lt 1 ]; then
echo "usage: gitea-api.sh <path> [curl-args...]" >&2
exit 2
fi
PATH_ARG="$1"; shift
GITEA_URL="${GITEA_URL:-http://localhost:3100}"
GITEA_USER="${GITEA_USER:-calic}"
# normalise path -> api/v1/<path>
p="${PATH_ARG#/}"; p="${p#api/v1/}"
URL="${GITEA_URL%/}/api/v1/${p}"
TOKEN="${GITEA_TOKEN:-}"
TMP_TOKEN_NAME=""
cleanup() {
if [ -n "$TMP_TOKEN_NAME" ]; then
curl -s -X DELETE -u "${GITEA_USER}:${TOKEN}" \
"${GITEA_URL%/}/api/v1/users/${GITEA_USER}/tokens/${TMP_TOKEN_NAME}" >/dev/null 2>&1 || true
fi
}
trap cleanup EXIT
if [ -z "$TOKEN" ] && docker ps --format '{{.Names}}' 2>/dev/null | grep -qx gitea; then
TMP_TOKEN_NAME="claude-api-$$"
TOKEN=$(docker exec --user git gitea gitea admin user generate-access-token \
-u "$GITEA_USER" -t "$TMP_TOKEN_NAME" \
--scopes read:organization,read:repository,read:user,read:issue,read:misc \
--raw 2>/dev/null) || TOKEN=""
[ -z "$TOKEN" ] && TMP_TOKEN_NAME=""
fi
AUTH=()
[ -n "$TOKEN" ] && AUTH=(-H "Authorization: token $TOKEN")
BODY_FILE="$(mktemp)"; trap 'rm -f "$BODY_FILE"; cleanup' EXIT
CODE=$(curl -s -o "$BODY_FILE" -w "%{http_code}" -X GET "${AUTH[@]}" "$URL")
if [ "$CODE" != "200" ]; then
echo "ERROR: GET $URL -> HTTP $CODE" >&2
[ -z "$TOKEN" ] && echo "HINT: no token (set GITEA_TOKEN or run where the gitea container is reachable)" >&2
[ "$CODE" = "401" ] && echo "HINT: 401 — token missing/expired/insufficient scope" >&2
[ "$CODE" = "404" ] && echo "HINT: 404 — check the path (e.g. orgs/<org>/repos, repos/<owner>/<name>)" >&2
cat "$BODY_FILE" >&2
exit 1
fi
if command -v jq >/dev/null 2>&1; then jq . < "$BODY_FILE"; else cat "$BODY_FILE"; fi