220 lines
5.5 KiB
Bash
220 lines
5.5 KiB
Bash
#!/usr/bin/env bash
|
|
# Websimple Gitea API wrapper — read-only operations.
|
|
#
|
|
# Replaces the OpenClaw plugin's three Gitea tools:
|
|
# - websimple_gitea_orgs_repos_list
|
|
# - websimple_gitea_repos_actions_variables_list
|
|
# - websimple_gitea_repos_actions_variables_get
|
|
#
|
|
# Requires:
|
|
# - jq
|
|
# - curl
|
|
# - WEBSIMPLE_GITEA_API_TOKEN env var (or --token flag)
|
|
#
|
|
# Usage:
|
|
# gitea.sh repos-list [--org wp-sites]
|
|
# gitea.sh vars-list <owner> <repo>
|
|
# gitea.sh var-get <owner> <repo> <variable-name>
|
|
#
|
|
# Output: JSON to stdout. Errors to stderr. Exit non-zero on failure.
|
|
|
|
set -euo pipefail
|
|
|
|
GITEA_BASE_URL="https://gitea.websimple.com"
|
|
GITEA_API_BASE="${GITEA_BASE_URL}/api/v1"
|
|
PAGE_LIMIT=100
|
|
|
|
# ----- helpers -----
|
|
|
|
die() {
|
|
printf 'gitea.sh: %s\n' "$*" >&2
|
|
exit 1
|
|
}
|
|
|
|
require_token() {
|
|
if [[ -z "${WEBSIMPLE_GITEA_API_TOKEN:-}" ]]; then
|
|
die "WEBSIMPLE_GITEA_API_TOKEN is not set. Export it before calling this script."
|
|
fi
|
|
}
|
|
|
|
require_cmd() {
|
|
command -v "$1" >/dev/null 2>&1 || die "Required command not found: $1"
|
|
}
|
|
|
|
# Issue an authenticated GET. Echos response body, exits non-zero on HTTP error.
|
|
# Args: $1 = path beginning with /
|
|
gitea_get() {
|
|
local path="$1"
|
|
local url="${GITEA_API_BASE}${path}"
|
|
local response
|
|
local http_code
|
|
|
|
response="$(curl -sS \
|
|
--header "Authorization: token ${WEBSIMPLE_GITEA_API_TOKEN}" \
|
|
--header "Accept: application/json" \
|
|
--write-out "\n__HTTP_CODE__:%{http_code}" \
|
|
"${url}")"
|
|
|
|
http_code="${response##*__HTTP_CODE__:}"
|
|
response="${response%$'\n'__HTTP_CODE__:*}"
|
|
|
|
if [[ "${http_code}" -lt 200 || "${http_code}" -ge 300 ]]; then
|
|
die "Gitea API request failed: HTTP ${http_code} for ${url}"
|
|
fi
|
|
|
|
printf '%s' "${response}"
|
|
}
|
|
|
|
# Fetch all pages for an endpoint that supports ?page=&limit=.
|
|
# Args: $1 = base path (without query string); $2 = extra query params (may be empty)
|
|
# Echoes a single JSON array combining all pages.
|
|
gitea_get_paginated() {
|
|
local base_path="$1"
|
|
local extra_query="${2:-}"
|
|
local page=1
|
|
local combined='[]'
|
|
local page_json
|
|
local page_count
|
|
|
|
while (( page <= 10000 )); do
|
|
local sep="?"
|
|
[[ -n "${extra_query}" ]] && sep="?${extra_query}&"
|
|
local path="${base_path}${sep}page=${page}&limit=${PAGE_LIMIT}"
|
|
|
|
# If gitea_get fails (HTTP error), the subshell exits non-zero and the
|
|
# caller's `|| exit 1` handles propagation.
|
|
page_json="$(gitea_get "${path}")" || return 1
|
|
|
|
# Defensive: empty/null responses become []
|
|
if [[ -z "${page_json}" || "${page_json}" == "null" ]]; then
|
|
page_json='[]'
|
|
fi
|
|
|
|
combined="$(jq -c --argjson new "${page_json}" '. + $new' <<<"${combined}")"
|
|
page_count="$(jq 'length' <<<"${page_json}")"
|
|
|
|
if (( page_count < PAGE_LIMIT )); then
|
|
printf '%s' "${combined}"
|
|
return 0
|
|
fi
|
|
|
|
page=$(( page + 1 ))
|
|
done
|
|
|
|
die "Pagination safety limit exceeded for ${base_path}"
|
|
}
|
|
|
|
# ----- subcommands -----
|
|
|
|
cmd_repos_list() {
|
|
local org="wp-sites"
|
|
while (( $# > 0 )); do
|
|
case "$1" in
|
|
--org) org="$2"; shift 2 ;;
|
|
--org=*) org="${1#--org=}"; shift ;;
|
|
*) die "Unknown argument to repos-list: $1" ;;
|
|
esac
|
|
done
|
|
|
|
require_token
|
|
|
|
local repos
|
|
repos="$(gitea_get_paginated "/orgs/${org}/repos" "")" || exit 1
|
|
|
|
# Match the OpenClaw tool's output shape: filtered fields + metadata envelope.
|
|
jq -n \
|
|
--arg baseUrl "${GITEA_BASE_URL}" \
|
|
--arg org "${org}" \
|
|
--argjson pageSize "${PAGE_LIMIT}" \
|
|
--argjson repos "${repos}" \
|
|
'{
|
|
baseUrl: $baseUrl,
|
|
org: $org,
|
|
fetchedAll: true,
|
|
pageSize: $pageSize,
|
|
count: ($repos | length),
|
|
repos: ($repos
|
|
| sort_by((.full_name // .name // ""))
|
|
| map({
|
|
id, name, full_name, html_url, clone_url, ssh_url,
|
|
default_branch, private, archived, updated_at
|
|
}))
|
|
}'
|
|
}
|
|
|
|
cmd_vars_list() {
|
|
(( $# == 2 )) || die "Usage: gitea.sh vars-list <owner> <repo>"
|
|
local owner="$1" repo="$2"
|
|
require_token
|
|
|
|
local variables
|
|
variables="$(gitea_get_paginated "/repos/${owner}/${repo}/actions/variables" "")" || exit 1
|
|
|
|
jq -n \
|
|
--arg baseUrl "${GITEA_BASE_URL}" \
|
|
--arg owner "${owner}" \
|
|
--arg repo "${repo}" \
|
|
--argjson pageSize "${PAGE_LIMIT}" \
|
|
--argjson variables "${variables}" \
|
|
'{
|
|
baseUrl: $baseUrl,
|
|
owner: $owner,
|
|
repo: $repo,
|
|
fetchedAll: true,
|
|
pageSize: $pageSize,
|
|
count: ($variables | length),
|
|
variables: ($variables | sort_by(.name // ""))
|
|
}'
|
|
}
|
|
|
|
cmd_var_get() {
|
|
(( $# == 3 )) || die "Usage: gitea.sh var-get <owner> <repo> <variable-name>"
|
|
local owner="$1" repo="$2" name="$3"
|
|
require_token
|
|
|
|
local variable
|
|
variable="$(gitea_get "/repos/${owner}/${repo}/actions/variables/${name}")" || exit 1
|
|
|
|
jq -n \
|
|
--arg baseUrl "${GITEA_BASE_URL}" \
|
|
--arg owner "${owner}" \
|
|
--arg repo "${repo}" \
|
|
--argjson variable "${variable}" \
|
|
'{
|
|
baseUrl: $baseUrl,
|
|
owner: $owner,
|
|
repo: $repo,
|
|
variable: $variable
|
|
}'
|
|
}
|
|
|
|
usage() {
|
|
cat >&2 <<'EOF'
|
|
Websimple Gitea API wrapper — read-only.
|
|
|
|
Usage:
|
|
gitea.sh repos-list [--org <org>] (default org: wp-sites)
|
|
gitea.sh vars-list <owner> <repo>
|
|
gitea.sh var-get <owner> <repo> <variable-name>
|
|
|
|
Requires WEBSIMPLE_GITEA_API_TOKEN in the environment.
|
|
EOF
|
|
exit 2
|
|
}
|
|
|
|
# ----- dispatch -----
|
|
|
|
require_cmd jq
|
|
require_cmd curl
|
|
|
|
[[ $# -ge 1 ]] || usage
|
|
|
|
cmd="$1"; shift
|
|
case "${cmd}" in
|
|
repos-list) cmd_repos_list "$@" ;;
|
|
vars-list) cmd_vars_list "$@" ;;
|
|
var-get) cmd_var_get "$@" ;;
|
|
-h|--help|help) usage ;;
|
|
*) die "Unknown subcommand: ${cmd}" ;;
|
|
esac
|