Files
Jyotisha/tools/agent-loop/gitea.sh
T

75 lines
3.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# Minimal Gitea issue API wrapper for the agent loop (Claude side, Linux).
# Token is read from a 0600 file and never echoed. Usage: gitea.sh <command> [args]
set -euo pipefail
set +x
GITEA_URL="${GITEA_URL:-https://git.copse.top}"
GITEA_REPO="${GITEA_REPO:-root/Jyotisha}"
TOKEN_FILE="${JYOTISHA_AGENT_TOKEN_FILE:-$HOME/.config/jyotisha-agent/gitea-token}"
API="$GITEA_URL/api/v1/repos/$GITEA_REPO"
_token() {
[[ -r "$TOKEN_FILE" ]] || { echo "gitea.sh: token file missing: $TOKEN_FILE" >&2; exit 2; }
tr -d '[:space:]' < "$TOKEN_FILE"
}
# _call METHOD PATH [JSON_BODY] — prints the response body; fails on HTTP >= 400
# without echoing request headers.
_call() {
local method="$1" path="$2" body="${3:-}" out code
out="$(mktemp)"
if [[ -n "$body" ]]; then
code="$(curl -sS -o "$out" -w '%{http_code}' -X "$method" \
-H "Authorization: token $(_token)" -H 'Content-Type: application/json' \
--data-binary "$body" "$API$path")"
else
code="$(curl -sS -o "$out" -w '%{http_code}' -X "$method" \
-H "Authorization: token $(_token)" "$API$path")"
fi
if [[ "$code" -ge 400 ]]; then
echo "gitea.sh: $method $path -> HTTP $code: $(head -c 300 "$out")" >&2
rm -f "$out"
return 1
fi
cat "$out"
rm -f "$out"
}
cmd="${1:-}"; shift || true
case "$cmd" in
whoami)
curl -sS -H "Authorization: token $(_token)" "$GITEA_URL/api/v1/user" | jq -r .login ;;
label-id) # label-id NAME
_call GET "/labels?limit=100" | jq -r --arg n "$1" '.[] | select(.name == $n) | .id' ;;
ensure-label) # ensure-label NAME COLOR DESCRIPTION
if [[ -z "$("$0" label-id "$1")" ]]; then
_call POST "/labels" "$(jq -nc --arg n "$1" --arg c "$2" --arg d "$3" '{name:$n,color:$c,description:$d}')" | jq -r '"created \(.name)"'
else
echo "exists $1"
fi ;;
issues) # issues LABEL — open issues carrying LABEL, oldest first, as JSON array
_call GET "/issues?state=open&type=issues&limit=50&labels=$(jq -rn --arg l "$1" '$l|@uri')" \
| jq -c 'sort_by(.created_at)' ;;
issue) # issue N
_call GET "/issues/$1" ;;
labels) # labels N — label names on issue N, one per line
_call GET "/issues/$1/labels" | jq -r '.[].name' ;;
add-label) # add-label N NAME
_call POST "/issues/$1/labels" "$(jq -nc --arg n "$2" '{labels:[$n]}')" >/dev/null ;;
remove-label) # remove-label N NAME (no-op when absent)
id="$("$0" label-id "$2")"
[[ -n "$id" ]] && _call DELETE "/issues/$1/labels/$id" >/dev/null || true ;;
comments) # comments N — JSON array
_call GET "/issues/$1/comments" ;;
comment) # comment N FILE — post FILE's content as a comment
_call POST "/issues/$1/comments" "$(jq -Rsc '{body:.}' < "$2")" >/dev/null ;;
create-issue) # create-issue TITLE FILE — prints the new issue number
_call POST "/issues" "$(jq -Rsc --arg t "$1" '{title:$t, body:.}' < "$2")" | jq -r .number ;;
close) # close N
_call PATCH "/issues/$1" '{"state":"closed"}' >/dev/null ;;
*)
echo "usage: gitea.sh whoami|label-id|ensure-label|issues|issue|labels|add-label|remove-label|comments|comment|create-issue|close" >&2
exit 64 ;;
esac