#!/bin/bash # Gitea Client - Main script for interacting with Gitea API # Usage: gitea-client.sh [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 " >&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 [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 " >&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 [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 [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 " >&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 [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 <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 "$@"