tools: archive coulomb Gitea org for read-only mirror policy
Script uses Gitea API to set archived=true on all org repos after Forgejo cutover (RAIL-HO-WP-0005). Ran 2026-07-08: 79/79 archived on coulombcore.
This commit is contained in:
parent
5f7b63490a
commit
608cc742a5
1 changed files with 112 additions and 0 deletions
112
tools/gitea-set-readonly.sh
Executable file
112
tools/gitea-set-readonly.sh
Executable file
|
|
@ -0,0 +1,112 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Archive all coulomb org repos on coulombcore Gitea (read-only mirror policy).
|
||||||
|
# Per RAIL-HO-WP-0005 / forgejo-tier3 playbook org-wide operator action.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
CONF="${GITEA_CONF:-$HOME/.railiance_gitea.conf}"
|
||||||
|
API="${GITEA_API:-https://gitea.coulomb.social}"
|
||||||
|
ORG="${GITEA_ORG:-coulomb}"
|
||||||
|
DRY_RUN="${DRY_RUN:-0}"
|
||||||
|
LIMIT="${PAGE_LIMIT:-50}"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'USAGE'
|
||||||
|
Usage: gitea-set-readonly.sh [repo ...]
|
||||||
|
|
||||||
|
With no args: archive every repo in org coulomb (idempotent).
|
||||||
|
With slugs: archive only those coulomb/<slug> repos.
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
GITEA_CONF Token file (default: ~/.railiance_gitea.conf)
|
||||||
|
GITEA_API HTTPS API base (default: https://gitea.coulomb.social)
|
||||||
|
DRY_RUN=1 Print actions only
|
||||||
|
USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ -f "$CONF" ]]; then
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$CONF"
|
||||||
|
fi
|
||||||
|
: "${GITEA_TOKEN:?Set GITEA_TOKEN or provide $CONF}"
|
||||||
|
|
||||||
|
auth=(-H "Authorization: token ${GITEA_TOKEN}")
|
||||||
|
|
||||||
|
fetch_all_repos() {
|
||||||
|
local page=1
|
||||||
|
local out=/tmp/gitea-readonly-repos.jsonl
|
||||||
|
: >"$out"
|
||||||
|
while true; do
|
||||||
|
local http body
|
||||||
|
body=$(mktemp)
|
||||||
|
http=$(curl -sS --max-time 30 -o "$body" -w '%{http_code}' \
|
||||||
|
"${auth[@]}" "${API}/api/v1/orgs/${ORG}/repos?limit=${LIMIT}&page=${page}")
|
||||||
|
if [[ "$http" != "200" ]]; then
|
||||||
|
echo "FAIL list page=${page} http=${http}" >&2
|
||||||
|
cat "$body" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
local count
|
||||||
|
count=$(python3 -c "import json; print(len(json.load(open('$body'))))")
|
||||||
|
python3 -c "import json; [print(r['name']) for r in json.load(open('$body'))]" >>"$out"
|
||||||
|
rm -f "$body"
|
||||||
|
[[ "$count" -lt "$LIMIT" ]] && break
|
||||||
|
page=$((page + 1))
|
||||||
|
done
|
||||||
|
sort -u "$out"
|
||||||
|
}
|
||||||
|
|
||||||
|
archive_repo() {
|
||||||
|
local name="$1"
|
||||||
|
local http archived
|
||||||
|
http=$(curl -sS --max-time 30 -o /tmp/gitea-get.json -w '%{http_code}' \
|
||||||
|
"${auth[@]}" "${API}/api/v1/repos/${ORG}/${name}")
|
||||||
|
if [[ "$http" == "404" ]]; then
|
||||||
|
echo "SKIP ${name} (not found)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if [[ "$http" != "200" ]]; then
|
||||||
|
echo "FAIL ${name} GET http=${http}" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
archived=$(python3 -c "import json; print(json.load(open('/tmp/gitea-get.json')).get('archived', False))")
|
||||||
|
if [[ "$archived" == "True" ]]; then
|
||||||
|
echo "OK ${name} (already archived)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if [[ "$DRY_RUN" == "1" ]]; then
|
||||||
|
echo "DRY ${name} -> archived"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
http=$(curl -sS --max-time 30 -o /tmp/gitea-patch.json -w '%{http_code}' \
|
||||||
|
-X PATCH "${auth[@]}" -H "Content-Type: application/json" \
|
||||||
|
-d '{"archived":true}' "${API}/api/v1/repos/${ORG}/${name}")
|
||||||
|
if [[ "$http" == "200" ]]; then
|
||||||
|
echo "ARCH ${name}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "FAIL ${name} PATCH http=${http}" >&2
|
||||||
|
cat /tmp/gitea-patch.json >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $# -gt 0 ]]; then
|
||||||
|
mapfile -t TARGETS < <(printf '%s\n' "$@")
|
||||||
|
else
|
||||||
|
mapfile -t TARGETS < <(fetch_all_repos)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== Gitea read-only: archive ${#TARGETS[@]} repo(s) in ${ORG} ==="
|
||||||
|
echo "API: ${API}"
|
||||||
|
|
||||||
|
failed=0
|
||||||
|
for name in "${TARGETS[@]}"; do
|
||||||
|
archive_repo "$name" || failed=$((failed + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "=== Done (failed=${failed}) ==="
|
||||||
|
[[ "$failed" -eq 0 ]]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue