1
0
mirror of git://f0xx.org/android_cast synced 2026-07-29 05:17:39 +03:00

sync infra

This commit is contained in:
Anton Afanasyeu
2026-06-10 22:34:59 +02:00
parent 37504abcb2
commit ce4e2e89f3
10 changed files with 439 additions and 57 deletions

View File

@@ -6,6 +6,18 @@ Scripts for the BE Gitea instance at `https://apps.f0xx.org/app/androidcast_proj
`/var/www/localhost/htdocs/apps/app/androidcast_project/android_cast`
is **never** modified. Only Gitea-owned paths from `/etc/gitea/app.ini` are backed up or reset.
## Temp files (/tmp)
Gitea scripts use `mktemp` work dirs for `git clone --mirror` fallbacks. Each `*.mirror.git` tree is **removed after every repo** (success or failure) and the work dir is removed on script exit.
Stale dirs (e.g. after `kill -9`) are pruned automatically on the next run (default: older than **60 minutes**). Manual cleanup:
```bash
sudo ./examples/crash_reporter/backend/scripts/gitea/gitea_cleanup_tmp.sh
# immediate wipe of all gitea-* temps:
GITEA_TMP_MAX_AGE_MIN=0 sudo ./gitea_cleanup_tmp.sh
```
## Prerequisites (Alpine BE)
- Gitea installed (`apk add gitea`), config at `/etc/gitea/app.ini`

View File

@@ -30,7 +30,7 @@ GITEA_OWNER="${GITEA_OWNER:-${GITEA_ORG:-AndroidCast}}"
GITEA_REPO="${GITEA_REPO:-android_cast}"
GITEA_MIRROR_INTERVAL="${GITEA_MIRROR_INTERVAL:-10m}"
GITEA_PRIVATE="${GITEA_PRIVATE:-false}"
WORK_DIR="${WORK_DIR:-/tmp/gitea-attach-$$}"
WORK_DIR="${WORK_DIR:-}"
# First positional argument = mirror URL (convenience).
if [ $# -ge 1 ] && [ -n "$1" ]; then
@@ -151,22 +151,25 @@ create_repo_via_api() {
[ -n "${GITEA_ADMIN_TOKEN:-}" ] || return 1
need_cmd curl
_api="$(gitea_api_base)"
_http="$(curl -sS -o /tmp/gitea-create-repo.json -w '%{http_code}' \
_resp="$(mktemp /tmp/gitea-create-repo-XXXXXX.json)"
_http="$(curl -sS -o "$_resp" -w '%{http_code}' \
-X POST "$_api/admin/users/$GITEA_OWNER/repos" \
-H "Authorization: token $GITEA_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"name\":\"$GITEA_REPO\",\"private\":$GITEA_PRIVATE}")"
_rc=1
if [ "$_http" = "201" ] || [ "$_http" = "200" ]; then
log "repo created via API"
return 0
fi
if [ "$_http" = "409" ]; then
_rc=0
elif [ "$_http" = "409" ]; then
log "repo already exists (API 409)"
return 0
_rc=0
else
warn "API create repo HTTP $_http"
cat "$_resp" >&2 2>/dev/null || true
fi
warn "API create repo HTTP $_http"
cat /tmp/gitea-create-repo.json >&2 2>/dev/null || true
return 1
gitea_rm_path "$_resp"
return "$_rc"
}
gitea_owner_uid() {
@@ -211,24 +214,28 @@ EOF
)
log "API migrate (pull mirror) uid=$_uid via $_api ..."
_http="$(curl -sS -o /tmp/gitea-migrate.json -w '%{http_code}' \
_resp="$(mktemp /tmp/gitea-migrate-XXXXXX.json)"
_http="$(curl -sS -o "$_resp" -w '%{http_code}' \
-X POST "$_api/repos/migrate" \
-H "Authorization: token $_token" \
-H "Content-Type: application/json" \
-d "$_payload")"
_rc=1
if [ "$_http" = "201" ] || [ "$_http" = "200" ]; then
log "mirror created via API (HTTP $_http)"
cat /tmp/gitea-migrate.json
cat "$_resp"
printf '\n'
return 0
_rc=0
else
if [ "$_http" = "409" ] || [ "$_http" = "422" ]; then
warn "migrate rejected HTTP $_http — repo may already exist; use mirror settings or delete repo first"
fi
warn "API migrate failed HTTP $_http:"
cat "$_resp" >&2
fi
if [ "$_http" = "409" ] || [ "$_http" = "422" ]; then
warn "migrate rejected HTTP $_http — repo may already exist; use mirror settings or delete repo first"
fi
warn "API migrate failed HTTP $_http:"
cat /tmp/gitea-migrate.json >&2
return 1
gitea_rm_path "$_resp"
return "$_rc"
}
ensure_gitea_repo_exists() {
@@ -237,27 +244,43 @@ ensure_gitea_repo_exists() {
mirror_via_git() {
need_cmd git
mkdir -p "$WORK_DIR"
gitea_prune_stale_tmp
if [ -n "$WORK_DIR" ]; then
mkdir -p "$WORK_DIR"
else
WORK_DIR="$(gitea_make_work_dir gitea-attach)"
fi
trap 'gitea_rm_path "$WORK_DIR"' EXIT INT HUP TERM
_mirror="$WORK_DIR/${GITEA_REPO}.mirror.git"
_rc=1
log "git clone --mirror $GITEA_MIRROR_URL"
rm -rf "$_mirror"
git clone --mirror "$GITEA_MIRROR_URL" "$_mirror"
gitea_rm_path "$_mirror"
if ! git clone --mirror "$GITEA_MIRROR_URL" "$_mirror"; then
gitea_rm_path "$WORK_DIR"
return 1
fi
ensure_gitea_repo_exists
_push_base="$(gitea_local_git_url)"
_token="$(resolve_push_token)" || die "need credentials: export GITEA_ADMIN_TOKEN=... or run as root with gitea CLI"
if _token="$(resolve_push_token)"; then
_auth_url="${_push_base#http://}"
_push_url="http://${_token}@${_auth_url}"
log "git push --mirror -> $_push_base (localhost, no subpath)"
if git -C "$_mirror" push --mirror "$_push_url"; then
_rc=0
log "one-time mirror push complete"
fi
else
die "need credentials: export GITEA_ADMIN_TOKEN=... or run as root with gitea CLI"
fi
_auth_url="${_push_base#http://}"
_push_url="http://${_token}@${_auth_url}"
log "git push --mirror -> $_push_base (localhost, no subpath)"
git -C "$_mirror" push --mirror "$_push_url"
log "one-time mirror push complete"
warn "for automatic updates, re-run with API migrate or enable pull mirror in Gitea UI"
rm -rf "$WORK_DIR"
gitea_rm_path "$WORK_DIR"
trap - EXIT INT HUP TERM
return "$_rc"
}
enable_mirror_sync_cron_hint() {

View File

@@ -0,0 +1,22 @@
#!/bin/ash
#
# Remove stale gitea script temp dirs under /tmp (mirror clones, work dirs, json).
# Safe to run anytime; does not touch running jobs younger than GITEA_TMP_MAX_AGE_MIN.
#
# Usage:
# sudo ./gitea_cleanup_tmp.sh
# GITEA_TMP_MAX_AGE_MIN=0 sudo ./gitea_cleanup_tmp.sh # aggressive (all ages)
#
set -eu
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck source=gitea_mirror_lib.sh
. "$SCRIPT_DIR/gitea_mirror_lib.sh"
_before="$(find /tmp -maxdepth 1 \( -name 'gitea-migrate-*' -o -name 'gitea-submodules-*' \
-o -name 'gitea-attach-*' -o -name 'gitea-mirror-*' -o -name 'gitea-*.json' \) 2>/dev/null | wc -l | tr -d ' ')"
gitea_prune_stale_tmp
_after="$(find /tmp -maxdepth 1 \( -name 'gitea-migrate-*' -o -name 'gitea-submodules-*' \
-o -name 'gitea-attach-*' -o -name 'gitea-mirror-*' -o -name 'gitea-*.json' \) 2>/dev/null | wc -l | tr -d ' ')"
printf '[gitea-cleanup] max_age_min=%s before=%s after=%s\n' \
"${GITEA_TMP_MAX_AGE_MIN:-60}" "$_before" "$_after"

View File

@@ -36,7 +36,7 @@ GITEA_SKIP_MAIN="${GITEA_SKIP_MAIN:-0}"
GITEA_SKIP_SUBMODULES="${GITEA_SKIP_SUBMODULES:-0}"
GITEA_SKIP_ORG_SETUP="${GITEA_SKIP_ORG_SETUP:-0}"
GITEA_SUBMODULES_CONF="${GITEA_SUBMODULES_CONF:-$SCRIPT_DIR/submodules.defaults.conf}"
WORK_DIR="${WORK_DIR:-/tmp/gitea-migrate-$$}"
WORK_DIR="${WORK_DIR:-}"
log() { printf '[gitea-migrate] %s\n' "$*"; }
warn() { printf '[gitea-migrate] WARN: %s\n' "$*" >&2; }
@@ -257,8 +257,13 @@ if command -v rc-service >/dev/null 2>&1; then
rc-service gitea status 2>/dev/null | grep -qi started || rc-service gitea start 2>/dev/null || true
fi
mkdir -p "$WORK_DIR"
trap 'rm -rf "$WORK_DIR"' EXIT INT HUP TERM
gitea_prune_stale_tmp
if [ -n "$WORK_DIR" ]; then
mkdir -p "$WORK_DIR"
else
WORK_DIR="$(gitea_make_work_dir gitea-migrate)"
fi
trap 'gitea_rm_path "$WORK_DIR"' EXIT INT HUP TERM
log "ini=$GITEA_APP_INI owner=$GITEA_OWNER ref=$GITEA_REF"

View File

@@ -21,6 +21,27 @@ gitea_api_base() {
printf '%s' "${GITEA_LOCAL_API:-http://127.0.0.1:3000/api/v1}"
}
# Remove abandoned gitea-* temp dirs/files (e.g. after kill -9). Default: older than 60 min.
gitea_prune_stale_tmp() {
_min="${GITEA_TMP_MAX_AGE_MIN:-60}"
command -v find >/dev/null 2>&1 || return 0
find /tmp -maxdepth 1 -type d \
\( -name 'gitea-migrate-*' -o -name 'gitea-submodules-*' \
-o -name 'gitea-attach-*' -o -name 'gitea-mirror-*' \) \
-mmin "+$_min" -exec rm -rf {} + 2>/dev/null || true
find /tmp -maxdepth 1 -type f -name 'gitea-*.json' \
-mmin "+$_min" -delete 2>/dev/null || true
}
gitea_make_work_dir() {
_prefix="${1:-gitea-work}"
mktemp -d "/tmp/${_prefix}-XXXXXX"
}
gitea_rm_path() {
rm -rf "$1" 2>/dev/null || true
}
gitea_resolve_push_token() {
if [ -n "${GITEA_ADMIN_TOKEN:-}" ]; then
printf '%s' "$GITEA_ADMIN_TOKEN"
@@ -103,23 +124,27 @@ gitea_migrate_mirror_api() {
}
EOF
)
_http="$(curl -sS -o /tmp/gitea-migrate-$$.json -w '%{http_code}' \
_resp="$(mktemp /tmp/gitea-migrate-XXXXXX.json)"
_http="$(curl -sS -o "$_resp" -w '%{http_code}' \
-X POST "$_api/repos/migrate" \
-H "Authorization: token $_token" \
-H "Content-Type: application/json" \
-d "$_payload")"
if [ "$_http" = "201" ] || [ "$_http" = "200" ]; then
gitea_rm_path "$_resp"
return 0
fi
if [ "$_http" = "409" ] || [ "$_http" = "422" ]; then
gitea_rm_path "$_resp"
return 2
fi
if [ -r "/tmp/gitea-migrate-$$.json" ]; then
if [ -r "$_resp" ]; then
printf '[gitea-mirror] migrate HTTP %s: ' "$_http" >&2
head -c 400 "/tmp/gitea-migrate-$$.json" >&2 || true
head -c 400 "$_resp" >&2 || true
printf '\n' >&2
fi
gitea_rm_path "$_resp"
return 1
}
@@ -131,15 +156,25 @@ gitea_mirror_push_git() {
command -v git >/dev/null 2>&1 || return 1
_mirror="$_work_dir/${_repo}.mirror.git"
rm -rf "$_mirror"
git clone --mirror "$_clone_url" "$_mirror" || return 1
_rc=1
gitea_rm_path "$_mirror"
if ! git clone --mirror "$_clone_url" "$_mirror"; then
gitea_rm_path "$_mirror"
return 1
fi
gitea_create_repo_cli "$_owner" "$_repo" "${GITEA_PRIVATE:-false}" || true
_push_base="$(gitea_local_git_url_for "$_owner" "$_repo")"
_token="$(gitea_resolve_push_token)" || return 1
_auth_url="${_push_base#http://}"
git -C "$_mirror" push --mirror "http://${_token}@${_auth_url}" || return 1
rm -rf "$_mirror"
return 0
if _token="$(gitea_resolve_push_token)"; then
_auth_url="${_push_base#http://}"
if git -C "$_mirror" push --mirror "http://${_token}@${_auth_url}"; then
_rc=0
fi
fi
gitea_rm_path "$_mirror"
return "$_rc"
}
gitea_repo_exists_api() {
@@ -193,11 +228,13 @@ gitea_mirror_set_interval_api() {
[ -n "$_token" ] || _token="$(gitea_resolve_push_token)" || return 1
_api="$(gitea_api_base)"
_payload="{\"mirror_interval\":\"$_interval\"}"
_http="$(curl -sS -o /tmp/gitea-mirror-interval-$$.json -w '%{http_code}' \
_resp="$(mktemp /tmp/gitea-mirror-interval-XXXXXX.json)"
_http="$(curl -sS -o "$_resp" -w '%{http_code}' \
-X PATCH "$_api/repos/$_owner/$_repo" \
-H "Authorization: token $_token" \
-H "Content-Type: application/json" \
-d "$_payload")"
gitea_rm_path "$_resp"
case "$_http" in
200|204) return 0 ;;
*) return 1 ;;
@@ -220,7 +257,13 @@ gitea_mirror_pull_repo() {
_repo="$2"
_owner="${3:-$GITEA_OWNER}"
_interval="${4:-${GITEA_MIRROR_INTERVAL:-10m}}"
_work_dir="${5:-/tmp/gitea-mirror-$$}"
_local_work=""
if [ $# -ge 5 ] && [ -n "$5" ]; then
_work_dir="$5"
else
_local_work="$(gitea_make_work_dir gitea-mirror)"
_work_dir="$_local_work"
fi
_rc=0
gitea_migrate_mirror_api "$_owner" "$_repo" "$_clone_url" "$_interval" "${GITEA_PRIVATE:-false}" \
@@ -237,5 +280,7 @@ gitea_mirror_pull_repo() {
fi
mkdir -p "$_work_dir"
gitea_mirror_push_git "$_owner" "$_repo" "$_clone_url" "$_work_dir" || _rc=1
gitea_rm_path "$_work_dir/${_repo}.mirror.git"
[ -n "$_local_work" ] && gitea_rm_path "$_local_work"
return "$_rc"
}

View File

@@ -26,7 +26,7 @@ GITEA_OWNER="${GITEA_OWNER:-${GITEA_ORG:-AndroidCast}}"
GITEA_MIRROR_INTERVAL="${GITEA_MIRROR_INTERVAL:-24h}"
GITEA_PRIVATE="${GITEA_PRIVATE:-false}"
GITEA_SUBMODULES_CONF="${GITEA_SUBMODULES_CONF:-$SCRIPT_DIR/submodules.defaults.conf}"
WORK_DIR="${WORK_DIR:-/tmp/gitea-submodules-$$}"
WORK_DIR="${WORK_DIR:-}"
SNIPPET_OUT="${SNIPPET_OUT:-$WORK_DIR/gitmodules.gitea-snippet.ini}"
log() { printf '[gitea-submodules] %s\n' "$*"; }
@@ -159,7 +159,13 @@ if ! gitea_owner_exists "$GITEA_OWNER"; then
GITEA_OWNER="$_fb"
fi
mkdir -p "$WORK_DIR"
gitea_prune_stale_tmp
if [ -n "$WORK_DIR" ]; then
mkdir -p "$WORK_DIR"
else
WORK_DIR="$(gitea_make_work_dir gitea-submodules)"
fi
trap 'gitea_rm_path "$WORK_DIR"' EXIT INT HUP TERM
: > "$WORK_DIR/entries.list"
if ! load_submodule_entries "$_gitmodules_arg" | while IFS= read -r _line; do
[ -n "$_line" ] || continue

View File

@@ -53,19 +53,21 @@ gitea_org_create_api() {
}
EOF
)
_http="$(curl -sS -o /tmp/gitea-org-create-$$.json -w '%{http_code}' \
_resp="$(mktemp /tmp/gitea-org-create-XXXXXX.json)"
_http="$(curl -sS -o "$_resp" -w '%{http_code}' \
-X POST "$_api/orgs" \
-H "Authorization: token $_token" \
-H "Content-Type: application/json" \
-d "$_payload")"
_rc=1
case "$_http" in
201|200) return 0 ;;
201|200) _rc=0 ;;
409|422)
gitea_org_exists "$_org" && return 0
return 1
gitea_org_exists "$_org" && _rc=0
;;
*) return 1 ;;
esac
gitea_rm_path "$_resp"
return "$_rc"
}
gitea_user_create_if_missing() {
@@ -156,19 +158,21 @@ gitea_transfer_repo_api() {
_token="$(gitea_api_token)" || return 1
_api="$(gitea_api_base)"
_payload="{\"new_owner\":\"$_to\",\"team_ids\":[]}"
_http="$(curl -sS -o /tmp/gitea-transfer-$$.json -w '%{http_code}' \
_resp="$(mktemp /tmp/gitea-transfer-XXXXXX.json)"
_http="$(curl -sS -o "$_resp" -w '%{http_code}' \
-X POST "$_api/repos/$_from/$_repo/transfer" \
-H "Authorization: token $_token" \
-H "Content-Type: application/json" \
-d "$_payload")"
_rc=1
case "$_http" in
200|201|202) return 0 ;;
200|201|202) _rc=0 ;;
409|422)
gitea_repo_exists_api "$_to" "$_repo" && return 0
return 1
gitea_repo_exists_api "$_to" "$_repo" && _rc=0
;;
*) return 1 ;;
esac
gitea_rm_path "$_resp"
return "$_rc"
}
# Move known project mirrors from GITEA_TRANSFER_FROM → org (no-op if absent).