Files
dance-lessons-coach/.vibe/skills/gitea-client/scripts/gitea-client.sh
Gabriel Radureau 99b2e410f2 📝 docs: rewrite AGENTS.md and README.md for clarity and brevity
Cut AGENTS.md from 1296 to ~210 lines: removed development timeline,
changelog, stale AI agent section, verbose architecture examples, and
duplicate content. Kept tech stack, project structure, key commands,
config reference, API table, ADR index, and commit conventions.

Cut README.md from 423 to ~80 lines: removed duplicate CI/CD sections
(one had merge conflict markers), non-existent Cobra CLI and
documentation/ references, and the AI agent usage section. Kept
features, quick start, config table, API table, testing, and Gitea
client setup.

Also includes gitea-client.sh fixes from earlier session:
create-pr sub-command and safe jq-based JSON body in comment-pr.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 20:18:25 +02:00

578 lines
17 KiB
Bash
Executable File

#!/bin/bash
# Gitea Client - Main script for interacting with Gitea API
# Usage: gitea-client.sh <command> [args...]
set -e
# Configuration
GITEA_API_BASE="https://gitea.arcodange.lab/api/v1"
# Get authentication token
get_auth_token() {
if [[ -n "${GITEA_API_TOKEN_FILE:-}" ]]; then
if [[ -f "$GITEA_API_TOKEN_FILE" ]]; then
cat "$GITEA_API_TOKEN_FILE"
return
else
echo "Error: Token file $GITEA_API_TOKEN_FILE not found" >&2
exit 1
fi
fi
if [[ -n "${GITEA_API_TOKEN:-}" ]]; then
echo "$GITEA_API_TOKEN"
return
fi
echo "Error: No Gitea API token provided" >&2
echo "Set either GITEA_API_TOKEN or GITEA_API_TOKEN_FILE environment variable" >&2
exit 1
}
# Make API request
api_request() {
local method="$1"
local endpoint="$2"
local data="${3:-}"
local token=$(get_auth_token)
local url="${GITEA_API_BASE}${endpoint}"
local headers=(
"Authorization: token ${token}"
"Accept: application/json"
"Content-Type: application/json"
)
if [[ "$method" == "GET" ]]; then
curl -s -X GET "$url" -H "${headers[0]}" -H "${headers[1]}"
else
curl -s -X "$method" "$url" -H "${headers[0]}" -H "${headers[1]}" -H "${headers[2]}" -d "$data"
fi
}
# List workflows
cmd_list_workflows() {
local owner="$1"
local repo="$2"
if [[ -z "$owner" || -z "$repo" ]]; then
echo "Usage: $0 list-workflows <owner> <repo>" >&2
exit 1
fi
local endpoint="/repos/${owner}/${repo}/actions/workflows"
api_request "GET" "$endpoint"
}
# List jobs
cmd_list_jobs() {
local owner="$1"
local repo="$2"
local workflow_id="$3"
local limit="${4:-10}"
if [[ -z "$owner" || -z "$repo" || -z "$workflow_id" ]]; then
echo "Usage: $0 list-jobs <owner> <repo> <workflow_id> [limit]" >&2
exit 1
fi
local endpoint="/repos/${owner}/${repo}/actions/workflows/${workflow_id}/runs?limit=${limit}"
api_request "GET" "$endpoint"
}
# Get job status
cmd_job_status() {
local owner="$1"
local repo="$2"
local job_id="$3"
if [[ -z "$owner" || -z "$repo" || -z "$job_id" ]]; then
echo "Usage: $0 job-status <owner> <repo> <job_id>" >&2
exit 1
fi
local endpoint="/repos/${owner}/${repo}/actions/runs/${job_id}"
api_request "GET" "$endpoint"
}
# Get job logs
cmd_job_logs() {
local owner="$1"
local repo="$2"
local job_id="$3"
local output_file="${4:-}"
if [[ -z "$owner" || -z "$repo" || -z "$job_id" ]]; then
echo "Usage: $0 job-logs <owner> <repo> <job_id> [output_file]" >&2
exit 1
fi
local endpoint="/repos/${owner}/${repo}/actions/jobs/${job_id}/logs"
local logs=$(api_request "GET" "$endpoint")
if [[ -n "$output_file" ]]; then
echo "$logs" > "$output_file"
echo "Logs saved to: $output_file"
else
echo "$logs"
fi
}
# Get action job logs
cmd_action_logs() {
local owner="$1"
local repo="$2"
local action_job_id="$3"
local output_file="${4:-}"
if [[ -z "$owner" || -z "$repo" || -z "$action_job_id" ]]; then
echo "Usage: $0 action-logs <owner> <repo> <action_job_id> [output_file]" >&2
exit 1
fi
local endpoint="/repos/${owner}/${repo}/actions/jobs/${action_job_id}/logs"
local logs=$(api_request "GET" "$endpoint")
if [[ -n "$output_file" ]]; then
echo "$logs" > "$output_file"
echo "Logs saved to: $output_file"
else
echo "$logs"
fi
}
# List workflow jobs
cmd_list_workflow_jobs() {
local owner="$1"
local repo="$2"
local workflow_run_id="$3"
if [[ -z "$owner" || -z "$repo" || -z "$workflow_run_id" ]]; then
echo "Usage: $0 list-workflow-jobs <owner> <repo> <workflow_run_id>" >&2
exit 1
fi
local endpoint="/repos/${owner}/${repo}/actions/runs/${workflow_run_id}/jobs"
api_request "GET" "$endpoint"
}
# Wait for job completion
cmd_wait_job() {
local owner="$1"
local repo="$2"
local job_id="$3"
local timeout="${4:-300}"
if [[ -z "$owner" || -z "$repo" || -z "$job_id" ]]; then
echo "Usage: $0 wait-job <owner> <repo> <job_id> [timeout]" >&2
exit 1
fi
local start_time=$(date +%s)
local end_time=$((start_time + timeout))
echo "Waiting for job ${job_id} to complete (timeout: ${timeout}s)..."
while [[ $(date +%s) -lt $end_time ]]; do
local status=$(cmd_job_status "$owner" "$repo" "$job_id" | jq -r '.status')
case "$status" in
"completed")
echo "Job completed successfully"
return 0
;;
"failed")
echo "Job failed"
return 1
;;
"cancelled")
echo "Job was cancelled"
return 2
;;
*)
echo "Current status: ${status}"
sleep 5
;;
esac
done
echo "Timeout reached"
return 3
}
# Comment on PR
# Create a pull request
cmd_create_pr() {
local owner="$1"
local repo="$2"
local title="$3"
local body="$4"
local head="$5"
local base="${6:-main}"
if [[ -z "$owner" || -z "$repo" || -z "$title" || -z "$head" ]]; then
echo "Usage: $0 create-pr <owner> <repo> <title> <body> <head_branch> [base_branch]" >&2
exit 1
fi
local endpoint="/repos/${owner}/${repo}/pulls"
local data
data=$(jq -n \
--arg title "$title" \
--arg body "$body" \
--arg head "$head" \
--arg base "$base" \
'{title: $title, body: $body, head: $head, base: $base}')
api_request "POST" "$endpoint" "$data"
}
cmd_comment_pr() {
local owner="$1"
local repo="$2"
local pr_number="$3"
local comment="$4"
if [[ -z "$owner" || -z "$repo" || -z "$pr_number" || -z "$comment" ]]; then
echo "Usage: $0 comment-pr <owner> <repo> <pr_number> <comment>" >&2
exit 1
fi
local endpoint="/repos/${owner}/${repo}/issues/${pr_number}/comments"
local data
data=$(jq -n --arg body "$comment" '{body: $body}')
api_request "POST" "$endpoint" "$data"
}
# Get PR status
cmd_pr_status() {
local owner="$1"
local repo="$2"
local pr_number="$3"
if [[ -z "$owner" || -z "$repo" || -z "$pr_number" ]]; then
echo "Usage: $0 pr-status <owner> <repo> <pr_number>" >&2
exit 1
fi
local endpoint="/repos/${owner}/${repo}/pulls/${pr_number}"
api_request "GET" "$endpoint"
}
# Main command routing
main() {
local command="${1:-}"
shift || true
case "$command" in
list-workflows) cmd_list_workflows "$@" ;;
list-jobs) cmd_list_jobs "$@" ;;
job-status) cmd_job_status "$@" ;;
job-logs) cmd_job_logs "$@" ;;
action-logs) cmd_action_logs "$@" ;;
list-workflow-jobs) cmd_list_workflow_jobs "$@" ;;
wait-job) cmd_wait_job "$@" ;;
monitor-workflow) cmd_monitor_workflow "$@" ;;
diagnose-job) cmd_diagnose_job "$@" ;;
recent-workflows) cmd_recent_workflows "$@" ;;
create-pr) cmd_create_pr "$@" ;;
comment-pr) cmd_comment_pr "$@" ;;
pr-status) cmd_pr_status "$@" ;;
list-issues) cmd_list_issues "$@" ;;
create-issue) cmd_create_issue "$@" ;;
show-issue) cmd_show_issue "$@" ;;
comment-issue) cmd_comment_issue "$@" ;;
list-wiki) cmd_list_wiki "$@" ;;
create-wiki) cmd_create_wiki "$@" ;;
get-wiki) cmd_get_wiki "$@" ;;
trigger-workflow) cmd_trigger_workflow "$@" ;;
*)
echo "Usage: $0 <command> [args...]" >&2
echo "" >&2
echo "Commands:" >&2
echo " list-workflows <owner> <repo>" >&2
echo " list-jobs <owner> <repo> <workflow_id> [limit]" >&2
echo " job-status <owner> <repo> <job_id>" >&2
echo " job-logs <owner> <repo> <job_id> [output_file]" >&2
echo " action-logs <owner> <repo> <action_job_id> [output_file]" >&2
echo " list-workflow-jobs <owner> <repo> <workflow_run_id>" >&2
echo " wait-job <owner> <repo> <job_id> [timeout]" >&2
echo " monitor-workflow <owner> <repo> <workflow_run_id> [interval_seconds]" >&2
echo " diagnose-job <owner> <repo> <job_id>" >&2
echo " recent-workflows <owner> <repo> [limit] [status_filter]" >&2
echo " create-pr <owner> <repo> <title> <body> <head_branch> [base_branch]" >&2
echo " comment-pr <owner> <repo> <pr_number> <comment>" >&2
echo " pr-status <owner> <repo> <pr_number>" >&2
echo " list-issues <owner> <repo> [state]" >&2
echo " create-issue <owner> <repo> <title> <description>" >&2
echo " show-issue <owner> <repo> <issue_number>" >&2
echo " comment-issue <owner> <repo> <issue_number> <comment>" >&2
echo " list-wiki <owner> <repo>" >&2
echo " create-wiki <owner> <repo> <title> <content> [message]" >&2
echo " get-wiki <owner> <repo> <page_name>" >&2
echo " trigger-workflow <owner> <repo> <workflow_file> <branch>" >&2
exit 1
;;
esac
}
# List issues
cmd_list_issues() {
local owner="$1"
local repo="$2"
local state="${3:-open}"
if [[ -z "$owner" || -z "$repo" ]]; then
echo "Usage: $0 list-issues <owner> <repo> [state]" >&2
exit 1
fi
local endpoint="/repos/$owner/$repo/issues?state=$state"
api_request "GET" "$endpoint"
}
# Create a new issue
cmd_create_issue() {
local owner="$1"
local repo="$2"
local title="$3"
local description="$4"
if [[ -z "$owner" || -z "$repo" || -z "$title" || -z "$description" ]]; then
echo "Usage: $0 create-issue <owner> <repo> <title> <description>" >&2
exit 1
fi
local endpoint="/repos/$owner/$repo/issues"
local data=$(jq -n --arg title "$title" --arg body "$description" '{
title: $title,
body: $body
}')
api_request "POST" "$endpoint" "$data"
}
# Show issue details
cmd_show_issue() {
local owner="$1"
local repo="$2"
local issue_number="$3"
if [[ -z "$owner" || -z "$repo" || -z "$issue_number" ]]; then
echo "Usage: $0 show-issue <owner> <repo> <issue_number>" >&2
exit 1
fi
local endpoint="/repos/$owner/$repo/issues/$issue_number"
api_request "GET" "$endpoint"
}
# Comment on an issue
cmd_comment_issue() {
local owner="$1"
local repo="$2"
local issue_number="$3"
local comment="$4"
if [[ -z "$owner" || -z "$repo" || -z "$issue_number" || -z "$comment" ]]; then
echo "Usage: $0 comment-issue <owner> <repo> <issue_number> <comment>" >&2
exit 1
fi
local endpoint="/repos/$owner/$repo/issues/$issue_number/comments"
local data=$(jq -n --arg body "$comment" '{
body: $body
}')
api_request "POST" "$endpoint" "$data"
}
# List wiki pages
cmd_list_wiki() {
local owner="$1"
local repo="$2"
if [[ -z "$owner" || -z "$repo" ]]; then
echo "Usage: $0 list-wiki <owner> <repo>" >&2
exit 1
fi
local endpoint="/repos/$owner/$repo/wiki/pages"
api_request "GET" "$endpoint"
}
# Create wiki page
cmd_create_wiki() {
local owner="$1"
local repo="$2"
local title="$3"
local content="$4"
local message="${5:-Initial creation}"
if [[ -z "$owner" || -z "$repo" || -z "$title" || -z "$content" ]]; then
echo "Usage: $0 create-wiki <owner> <repo> <title> <content> [message]" >&2
exit 1
fi
local content_b64=$(echo "$content" | base64)
local endpoint="/repos/$owner/$repo/wiki/new"
local data=$(jq -n --arg title "$title" --arg content "$content_b64" --arg msg "$message" '{
title: $title,
content_base64: $content,
message: $msg
}')
api_request "POST" "$endpoint" "$data"
}
# Get wiki page
cmd_get_wiki() {
local owner="$1"
local repo="$2"
local page_name="$3"
if [[ -z "$owner" || -z "$repo" || -z "$page_name" ]]; then
echo "Usage: $0 get-wiki <owner> <repo> <page_name>" >&2
exit 1
fi
local endpoint="/repos/$owner/$repo/wiki/page/$page_name"
local response=$(api_request "GET" "$endpoint")
# Extract and decode the content_base64 field
local content_b64=$(echo "$response" | jq -r '.content_base64')
if [[ "$content_b64" != "null" && -n "$content_b64" ]]; then
echo "$content_b64" | base64 --decode
else
echo "$response"
fi
}
# Trigger workflow
cmd_trigger_workflow() {
local owner="$1"
local repo="$2"
local workflow_file="$3"
local branch="$4"
if [[ -z "$owner" || -z "$repo" || -z "$workflow_file" || -z "$branch" ]]; then
echo "Usage: $0 trigger-workflow <owner> <repo> <workflow_file> <branch>" >&2
exit 1
fi
local endpoint="/repos/${owner}/${repo}/actions/workflows/${workflow_file}/dispatches"
local data="{\"ref\": \"${branch}\"}"
echo "Triggering workflow: ${workflow_file} on branch: ${branch}"
api_request "POST" "$endpoint" "$data"
echo "Workflow triggered successfully!"
}
# Monitor workflow run until completion
cmd_monitor_workflow() {
local owner="$1"
local repo="$2"
local workflow_run_id="$3"
local interval="${4:-30}"
if [[ -z "$owner" || -z "$repo" || -z "$workflow_run_id" ]]; then
echo "Usage: $0 monitor-workflow <owner> <repo> <workflow_run_id> [interval_seconds]" >&2
exit 1
fi
echo "Monitoring workflow run $workflow_run_id (interval: ${interval}s)..."
echo "Press Ctrl+C to stop monitoring"
while true; do
local endpoint="/repos/${owner}/${repo}/actions/runs/${workflow_run_id}"
local status=$(api_request "GET" "$endpoint" | jq -r '.status')
local conclusion=$(api_request "GET" "$endpoint" | jq -r '.conclusion')
local updated_at=$(api_request "GET" "$endpoint" | jq -r '.updated_at')
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Status: $status, Conclusion: ${conclusion:-not completed}, Updated: $updated_at"
# List jobs in this workflow
local jobs_endpoint="/repos/${owner}/${repo}/actions/runs/${workflow_run_id}/jobs"
local jobs=$(api_request "GET" "$jobs_endpoint")
echo "Jobs:"
echo "$jobs" | jq -r '.jobs[] | " \(.id): \(.name) - \(.status) \(if .conclusion then "(\(.conclusion))" else "" end)"'
# Check if workflow is completed
if [[ "$status" != "queued" && "$status" != "in_progress" && "$status" != "waiting" ]]; then
echo "Workflow run $workflow_run_id has completed with status: $status and conclusion: ${conclusion:-none}"
break
fi
sleep "$interval"
done
}
# Diagnose failed job
cmd_diagnose_job() {
local owner="$1"
local repo="$2"
local job_id="$3"
if [[ -z "$owner" || -z "$repo" || -z "$job_id" ]]; then
echo "Usage: $0 diagnose-job <owner> <repo> <job_id>" >&2
exit 1
fi
echo "Diagnosing job $job_id..."
# Get job details
local job_endpoint="/repos/${owner}/${repo}/actions/jobs/${job_id}"
local job_details=$(api_request "GET" "$job_endpoint")
echo "Job Details:"
echo "$job_details" | jq '. | {id, name, status, conclusion, started_at, completed_at, runner_name}'
# Get job logs
local logs_endpoint="/repos/${owner}/${repo}/actions/jobs/${job_id}/logs"
echo -e "\nLast 50 lines of logs:"
api_request "GET" "$logs_endpoint" | tail -50
# Look for errors
echo -e "\nError analysis:"
api_request "GET" "$logs_endpoint" | grep -i "error\|fail\|panic\|exception" | tail -10
# Get workflow run details
local run_id=$(echo "$job_details" | jq -r '.run_id')
local run_endpoint="/repos/${owner}/${repo}/actions/runs/${run_id}"
local run_details=$(api_request "GET" "$run_endpoint")
echo -e "\nWorkflow Run Details:"
echo "$run_details" | jq '. | {id, display_title, status, conclusion, head_branch, head_sha}'
}
# Get recent workflow runs summary
cmd_recent_workflows() {
local owner="$1"
local repo="$2"
local limit="${3:-10}"
local status_filter="${4:-}"
if [[ -z "$owner" || -z "$repo" ]]; then
echo "Usage: $0 recent-workflows <owner> <repo> [limit] [status_filter]" >&2
echo "Status filter options: all, completed, in_progress, queued, waiting" >&2
exit 1
fi
local endpoint="/repos/${owner}/${repo}/actions/runs?limit=${limit}"
if [[ -n "$status_filter" ]]; then
endpoint="$endpoint&status=$status_filter"
fi
local workflows=$(api_request "GET" "$endpoint")
echo "Recent Workflow Runs (showing $limit most recent):"
echo "$workflows" | jq -r '.workflow_runs[] | "\(.id): \(.display_title) - \(.status) \(if .conclusion then "(\(.conclusion))" else "" end) - \(.updated_at)"'
# Show summary statistics
echo -e "\nSummary:"
echo "$workflows" | jq -r '.workflow_runs | group_by(.conclusion) | .[] | " \(.[0].conclusion // "in_progress"): \(length)"'
}
main "$@"