1
0
mirror of git://f0xx.org/android_cast synced 2026-07-29 02:59:00 +03:00

gitea pain

This commit is contained in:
Anton Afanasyeu
2026-06-10 22:18:28 +02:00
parent 91cac577e8
commit 37504abcb2
11 changed files with 338 additions and 19 deletions

View File

@@ -154,6 +154,44 @@ DEFAULT_MIRROR_INTERVAL = 10m
MIRROR_UPDATE_INTERVAL = 10m
```
## AndroidCast organization (team repos)
Project mirrors live under the **`AndroidCast`** org (not personal `admin/`):
`https://apps.f0xx.org/app/androidcast_project/git/AndroidCast`
| Role | Who | Access |
|------|-----|--------|
| **Site admin** | Gitea user `admin` | Instance users/settings + org **Owners** |
| **Org Owners** | `admin`, `foxx` | Full control of all `AndroidCast/*` repos |
| **Future members** | Add to org teams in UI | Read/write per team (create e.g. Developers later) |
**One-time org setup** (idempotent; org already created in UI is fine):
```bash
sudo ./examples/crash_reporter/backend/scripts/gitea/gitea_migrate_org_setup.sh
```
This will:
- Ensure org **AndroidCast** exists (skip create if you made it in UI)
- Create Gitea user **`foxx`** if missing (`--must-change-password` — set password or SSH key in UI later)
- Add **`admin`** and **`foxx`** to org **Owners** team (org-admin on all repos)
- **Transfer** existing `admin/android_cast`, `admin/libvpx`, … → `AndroidCast/*` when present
Then migrate mirrors under the org:
```bash
cd /var/www/.../androidcast_project/android_cast
GITEA_OWNER=AndroidCast sudo ./examples/crash_reporter/backend/scripts/gitea/gitea_migrate_project.sh .
```
Defaults: `GITEA_OWNER=AndroidCast`, `GITEA_ORG_OWNERS="admin foxx"`, `GITEA_TRANSFER_FROM=admin`.
Clone URLs become:
`https://apps.f0xx.org/app/androidcast_project/git/AndroidCast/android_cast.git`
## Full project migration (main + external submodules)
**`gitea_migrate_project.sh`** — one script for BE:
@@ -192,7 +230,7 @@ sudo ./examples/crash_reporter/backend/scripts/gitea/gitea_migrate_project.sh .
sudo ./examples/crash_reporter/backend/scripts/gitea/gitea_mirror_submodules.sh .gitmodules
```
Expect **4 repos** under `admin`: `android_cast`, `libvpx`, `opus`, `speex`. If migrate summary shows `submodules ok=0` and a WARN about empty discovery, `.gitmodules` is missing on the BE checkout — the updated migrate script falls back to `submodules.defaults.conf`.
Expect **4 repos** under **`AndroidCast`**: `android_cast`, `libvpx`, `opus`, `speex`. If migrate summary shows `submodules ok=0` and a WARN about empty discovery, `.gitmodules` is missing on the BE checkout — the updated migrate script falls back to `submodules.defaults.conf`.
In Gitea UI, use **Explore** or **Site Administration → Repositories** if the profile counter hides mirror repos.

View File

@@ -13,7 +13,7 @@
# --- B) curl Gitea API on BE loopback via FE→BE nginx/internal URL ---
# Create a long-lived token in Gitea UI (admin, scope: write repository).
# GITEA_SYNC_CMD='curl -fsS -X POST -H "Authorization: token YOUR_TOKEN" http://artc0.intra.raptor.org:3000/api/v1/repos/admin/android_cast/mirror-sync'
# GITEA_SYNC_CMD='curl -fsS -X POST -H "Authorization: token YOUR_TOKEN" http://artc0.intra.raptor.org:3000/api/v1/repos/AndroidCast/android_cast/mirror-sync'
# --- C) curl public apps URL (only if you add a protected internal endpoint) ---
# GITEA_SYNC_CMD='curl -fsS -X POST -H "Authorization: Bearer ..." https://apps.f0xx.org/.../gitea_mirror_sync'

View File

@@ -20,9 +20,13 @@ set -eu
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck source=gitea_ini.sh
. "$SCRIPT_DIR/gitea_ini.sh"
# shellcheck source=gitea_mirror_lib.sh
. "$SCRIPT_DIR/gitea_mirror_lib.sh"
# shellcheck source=gitea_org_lib.sh
. "$SCRIPT_DIR/gitea_org_lib.sh"
GITEA_MIRROR_URL="${GITEA_MIRROR_URL:-git://f0xx.org/android_cast}"
GITEA_OWNER="${GITEA_OWNER:-admin}"
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}"
@@ -80,11 +84,15 @@ test_remote_reachable() {
}
resolve_gitea_owner() {
if gitea_user_exists "$GITEA_OWNER"; then
log "Gitea owner user: $GITEA_OWNER"
if [ "${GITEA_SKIP_ORG_SETUP:-0}" -eq 0 ]; then
gitea_org_ensure_androidcast "$GITEA_ORG" 2>/dev/null || true
GITEA_OWNER="${GITEA_OWNER:-$GITEA_ORG}"
fi
if gitea_owner_exists "$GITEA_OWNER"; then
log "Gitea repo owner: $GITEA_OWNER"
return 0
fi
warn "Gitea has no user '$GITEA_OWNER' (not Linux/FE login — Gitea accounts are separate)"
warn "Gitea has no owner '$GITEA_OWNER' (user or org — not Linux/FE login)"
log "Gitea users on this instance:"
gitea_list_usernames | while read -r _u; do
[ -n "$_u" ] && log " - $_u"

View File

@@ -17,7 +17,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck source=gitea_submodule_lib.sh
. "$SCRIPT_DIR/gitea_submodule_lib.sh"
GITEA_OWNER="${GITEA_OWNER:-admin}"
GITEA_OWNER="${GITEA_OWNER:-${GITEA_ORG:-AndroidCast}}"
GITEA_REF="${GITEA_REF:-HEAD}"
GITEA_SUBMODULES_CONF="${GITEA_SUBMODULES_CONF:-$SCRIPT_DIR/submodules.defaults.conf}"
@@ -92,7 +92,7 @@ fi
cat <<EOF
If count=1 (only android_cast):
If count=1 (only android_cast under AndroidCast or admin):
• gitea_attach_remote.sh only mirrors the main repo — run submodule step:
sudo ./gitea_migrate_project.sh . --skip-main
or:

View File

@@ -0,0 +1,41 @@
#!/bin/ash
#
# Prepare AndroidCast Gitea org: team owners (admin + foxx), transfer legacy admin/* repos.
# Safe to re-run (idempotent). Run before or with gitea_migrate_project.sh.
#
# Usage (Alpine BE as root):
# sudo ./gitea_migrate_org_setup.sh
# GITEA_ORG=AndroidCast GITEA_ORG_OWNERS="admin foxx" sudo ./gitea_migrate_org_setup.sh
#
set -eu
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck source=gitea_ini.sh
. "$SCRIPT_DIR/gitea_ini.sh"
# shellcheck source=gitea_mirror_lib.sh
. "$SCRIPT_DIR/gitea_mirror_lib.sh"
# shellcheck source=gitea_org_lib.sh
. "$SCRIPT_DIR/gitea_org_lib.sh"
gitea_load_config || exit 1
gitea_ensure_cli_access || exit 1
gitea_org_log "org=$GITEA_ORG owners=$GITEA_ORG_OWNERS transfer_from=$GITEA_TRANSFER_FROM"
gitea_org_log "public URL: ${GITEA_ROOT_URL%/}/$GITEA_ORG"
gitea_org_ensure_androidcast "$GITEA_ORG" || exit 1
gitea_org_log "repos under $GITEA_ORG:"
gitea_list_repos_api "$GITEA_ORG" 2>/dev/null | while read -r _r; do
[ -n "$_r" ] && gitea_org_log " $GITEA_ORG/$_r"
done
cat <<EOF
Org setup done.
• Owners team (full org/repo control): $GITEA_ORG_OWNERS
• Set password or SSH key for foxx: Gitea UI → foxx → Settings
• Mirror all project repos under org:
GITEA_OWNER=$GITEA_ORG sudo ./gitea_migrate_project.sh /path/to/android_cast
EOF

View File

@@ -22,8 +22,10 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
. "$SCRIPT_DIR/gitea_mirror_lib.sh"
# shellcheck source=gitea_submodule_lib.sh
. "$SCRIPT_DIR/gitea_submodule_lib.sh"
# shellcheck source=gitea_org_lib.sh
. "$SCRIPT_DIR/gitea_org_lib.sh"
GITEA_OWNER="${GITEA_OWNER:-admin}"
GITEA_OWNER="${GITEA_OWNER:-${GITEA_ORG:-AndroidCast}}"
GITEA_REPO="${GITEA_REPO:-android_cast}"
GITEA_MIRROR_URL="${GITEA_MIRROR_URL:-git://10.7.0.10/android_cast}"
GITEA_MAIN_MIRROR_INTERVAL="${GITEA_MAIN_MIRROR_INTERVAL:-1m}"
@@ -32,6 +34,7 @@ GITEA_PRIVATE="${GITEA_PRIVATE:-false}"
GITEA_REF="${GITEA_REF:-HEAD}"
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-$$}"
@@ -159,7 +162,7 @@ print_gitea_repo_inventory() {
_n=$((_n + 1))
done
_count="$(echo "$_names" | grep -c . 2>/dev/null || echo 0)"
log "total listed: $_count (expect android_cast + libvpx + opus + speex)"
log "total listed: $_count (expect android_cast + libvpx + opus + speex under $GITEA_ORG)"
}
print_fast_sync_guide() {
@@ -212,6 +215,13 @@ while [ $# -gt 0 ]; do
;;
--skip-main) GITEA_SKIP_MAIN=1; shift ;;
--skip-submodules) GITEA_SKIP_SUBMODULES=1; shift ;;
--skip-org) GITEA_SKIP_ORG_SETUP=1; shift ;;
--org-setup-only)
gitea_load_config || exit 1
gitea_ensure_cli_access || exit 1
gitea_org_ensure_androidcast "$GITEA_ORG" || exit 1
exit 0
;;
--ref)
shift
GITEA_REF="${1:-HEAD}"
@@ -230,10 +240,16 @@ done
gitea_load_config || exit 1
gitea_ensure_cli_access || exit 1
if ! gitea_user_exists "$GITEA_OWNER"; then
if [ "$GITEA_SKIP_ORG_SETUP" -eq 0 ]; then
log "org setup: $GITEA_ORG (owners: $GITEA_ORG_OWNERS)"
gitea_org_ensure_androidcast "$GITEA_ORG" || warn "org setup incomplete — continue with owner=$GITEA_OWNER"
GITEA_OWNER="${GITEA_OWNER:-$GITEA_ORG}"
fi
if ! gitea_owner_exists "$GITEA_OWNER"; then
_fb="$(gitea_pick_owner_username)"
[ -n "$_fb" ] || die "no Gitea user; set GITEA_OWNER=admin"
warn "GITEA_OWNER=$GITEA_OWNER not found; using $_fb"
[ -n "$_fb" ] || die "no Gitea owner; set GITEA_OWNER=$GITEA_ORG or create org in UI"
warn "owner $GITEA_OWNER not found; using $_fb"
GITEA_OWNER="$_fb"
fi

View File

@@ -161,7 +161,13 @@ gitea_list_repos_api() {
_token="${GITEA_ADMIN_TOKEN:-}"
[ -n "$_token" ] || _token="$(gitea_resolve_push_token)" || return 1
_api="$(gitea_api_base)"
curl -sS "$_api/users/$_owner/repos?limit=50" \
_list_url="$_api/users/$_owner/repos?limit=50"
_http="$(curl -sS -o /dev/null -w '%{http_code}' "$_api/orgs/$_owner" \
-H "Authorization: token $_token")"
if [ "$_http" = "200" ]; then
_list_url="$_api/orgs/$_owner/repos?limit=50"
fi
curl -sS "$_list_url" \
-H "Authorization: token $_token" \
| awk -F'"' '/"name":/ { print $4 }'
}

View File

@@ -19,8 +19,10 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
. "$SCRIPT_DIR/gitea_ini.sh"
# shellcheck source=gitea_mirror_lib.sh
. "$SCRIPT_DIR/gitea_mirror_lib.sh"
# shellcheck source=gitea_org_lib.sh
. "$SCRIPT_DIR/gitea_org_lib.sh"
GITEA_OWNER="${GITEA_OWNER:-admin}"
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}"
@@ -148,9 +150,11 @@ if [ $# -ge 1 ] && [ -n "$1" ]; then
esac
fi
if ! gitea_user_exists "$GITEA_OWNER"; then
gitea_org_ensure_androidcast "$GITEA_ORG" 2>/dev/null || true
GITEA_OWNER="${GITEA_OWNER:-$GITEA_ORG}"
if ! gitea_owner_exists "$GITEA_OWNER"; then
_fb="$(gitea_pick_owner_username)"
[ -n "$_fb" ] || die "no Gitea user; set GITEA_OWNER=admin (or create admin in UI)"
[ -n "$_fb" ] || die "no Gitea owner; set GITEA_OWNER=$GITEA_ORG"
warn "GITEA_OWNER=$GITEA_OWNER not found; using $_fb"
GITEA_OWNER="$_fb"
fi

View File

@@ -0,0 +1,206 @@
#!/bin/ash
# Gitea organization, team, and user helpers (AndroidCast team layout).
# shellcheck shell=sh
# Requires: . gitea_ini.sh && gitea_load_config && . gitea_mirror_lib.sh
GITEA_ORG="${GITEA_ORG:-AndroidCast}"
GITEA_ORG_FULL_NAME="${GITEA_ORG_FULL_NAME:-Android Cast}"
GITEA_ORG_VISIBILITY="${GITEA_ORG_VISIBILITY:-public}"
# Space-separated Gitea logins with org Owner (admin) team membership.
GITEA_ORG_OWNERS="${GITEA_ORG_OWNERS:-admin foxx}"
# Transfer mirrors from a personal account when re-homing under the org.
GITEA_TRANSFER_FROM="${GITEA_TRANSFER_FROM:-admin}"
gitea_org_log() { printf '[gitea-org] %s\n' "$*"; }
gitea_org_warn() { printf '[gitea-org] WARN: %s\n' "$*" >&2; }
gitea_api_token() {
_token="${GITEA_ADMIN_TOKEN:-}"
[ -n "$_token" ] || _token="$(gitea_resolve_push_token)" || return 1
printf '%s' "$_token"
}
gitea_org_exists() {
_org="$1"
command -v curl >/dev/null 2>&1 || return 1
_token="$(gitea_api_token)" || return 1
_api="$(gitea_api_base)"
_http="$(curl -sS -o /dev/null -w '%{http_code}' \
"$_api/orgs/$_org" \
-H "Authorization: token $_token")"
[ "$_http" = "200" ]
}
gitea_owner_exists() {
_name="$1"
gitea_org_exists "$_name" && return 0
gitea_user_exists "$_name"
}
gitea_org_create_api() {
_org="$1"
_full="${2:-$GITEA_ORG_FULL_NAME}"
command -v curl >/dev/null 2>&1 || return 1
_token="$(gitea_api_token)" || return 1
_api="$(gitea_api_base)"
_payload=$(cat <<EOF
{
"username": "$_org",
"full_name": "$_full",
"description": "Android Cast project mirrors and sources",
"visibility": "$GITEA_ORG_VISIBILITY",
"repo_admin_change_team_access": true
}
EOF
)
_http="$(curl -sS -o /tmp/gitea-org-create-$$.json -w '%{http_code}' \
-X POST "$_api/orgs" \
-H "Authorization: token $_token" \
-H "Content-Type: application/json" \
-d "$_payload")"
case "$_http" in
201|200) return 0 ;;
409|422)
gitea_org_exists "$_org" && return 0
return 1
;;
*) return 1 ;;
esac
}
gitea_user_create_if_missing() {
_user="$1"
_email="${2:-${_user}@local}"
if gitea_user_exists "$_user"; then
gitea_org_log "user exists: $_user"
return 0
fi
gitea_org_log "creating user $_user (password/SSH key: set later in Gitea UI)"
_pw="setme-$(date +%s)-$$"
if gitea_cli "admin" "user" "create" \
"--username" "$_user" \
"--email" "$_email" \
"--password" "$_pw" \
"--must-change-password" 2>/dev/null; then
return 0
fi
if gitea_cli "admin" "user" "create" \
"--username" "$_user" \
"--email" "$_email" \
"--random-password" \
"--must-change-password" 2>/dev/null; then
return 0
fi
gitea_org_warn "could not create user $_user via CLI — create in Gitea UI"
return 1
}
gitea_org_owners_team_id() {
_org="$1"
command -v curl >/dev/null 2>&1 || return 1
_token="$(gitea_api_token)" || return 1
_api="$(gitea_api_base)"
_id="$(curl -sS "$_api/orgs/$_org/teams" \
-H "Authorization: token $_token" \
| awk -F'"' '
/"id":/ { id = $4 }
/"name": "Owners"/ { print id; exit }
/"name":"Owners"/ { print id; exit }
')"
[ -n "$_id" ] || return 1
printf '%s' "$_id"
}
gitea_team_add_member_api() {
_team_id="$1"
_user="$2"
command -v curl >/dev/null 2>&1 || return 1
_token="$(gitea_api_token)" || return 1
_api="$(gitea_api_base)"
_http="$(curl -sS -o /dev/null -w '%{http_code}' \
-X PUT "$_api/teams/$_team_id/members/$_user" \
-H "Authorization: token $_token")"
case "$_http" in
204|200|201) return 0 ;;
422) return 0 ;;
*) return 1 ;;
esac
}
gitea_org_add_owners() {
_org="$1"
_team_id="$(gitea_org_owners_team_id "$_org")" || {
gitea_org_warn "Owners team not found for org $_org"
return 1
}
for _u in $GITEA_ORG_OWNERS; do
[ -n "$_u" ] || continue
gitea_user_create_if_missing "$_u" || true
if gitea_user_exists "$_u"; then
if gitea_team_add_member_api "$_team_id" "$_u"; then
gitea_org_log "Owners team: $_u"
else
gitea_org_warn "could not add $_u to Owners (may already be member)"
fi
fi
done
return 0
}
gitea_transfer_repo_api() {
_from="$1"
_repo="$2"
_to="$3"
command -v curl >/dev/null 2>&1 || return 1
gitea_repo_exists_api "$_from" "$_repo" || return 1
_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}' \
-X POST "$_api/repos/$_from/$_repo/transfer" \
-H "Authorization: token $_token" \
-H "Content-Type: application/json" \
-d "$_payload")"
case "$_http" in
200|201|202) return 0 ;;
409|422)
gitea_repo_exists_api "$_to" "$_repo" && return 0
return 1
;;
*) return 1 ;;
esac
}
# Move known project mirrors from GITEA_TRANSFER_FROM → org (no-op if absent).
gitea_org_transfer_legacy_repos() {
_org="$1"
_from="${2:-$GITEA_TRANSFER_FROM}"
[ "$_from" = "$_org" ] && return 0
for _repo in android_cast libvpx opus speex wireguard-android; do
if gitea_repo_exists_api "$_from" "$_repo"; then
gitea_org_log "transfer $_from/$_repo -> $_org/$_repo"
gitea_transfer_repo_api "$_from" "$_repo" "$_org" \
&& gitea_org_log " transferred" \
|| gitea_org_warn " transfer failed"
fi
done
}
# Org + Owners team + foxx/admin. Idempotent.
gitea_org_ensure_androidcast() {
_org="${1:-$GITEA_ORG}"
if gitea_org_exists "$_org"; then
gitea_org_log "org exists: $_org"
else
gitea_org_log "creating org $_org"
gitea_org_create_api "$_org" || {
gitea_org_warn "org create failed — create $_org in Gitea UI first"
return 1
}
fi
gitea_org_add_owners "$_org"
gitea_org_transfer_legacy_repos "$_org" "$GITEA_TRANSFER_FROM"
return 0
}

View File

@@ -12,7 +12,7 @@
set -eu
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
GITEA_OWNER="${GITEA_OWNER:-admin}"
GITEA_OWNER="${GITEA_OWNER:-AndroidCast}"
GITEA_ROOT_URL="${GITEA_ROOT_URL:-https://apps.f0xx.org/app/androidcast_project/git}"
GITEA_SUBMODULES_CONF="${GITEA_SUBMODULES_CONF:-$SCRIPT_DIR/submodules.defaults.conf}"

View File

@@ -15,7 +15,7 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck source=gitea_mirror_lib.sh
. "$SCRIPT_DIR/gitea_mirror_lib.sh"
GITEA_OWNER="${GITEA_OWNER:-admin}"
GITEA_OWNER="${GITEA_OWNER:-${GITEA_ORG:-AndroidCast}}"
log() { printf '[gitea-sync] %s\n' "$*"; }
warn() { printf '[gitea-sync] WARN: %s\n' "$*" >&2; }