Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / tests (push) Has been cancelled
144 lines
4.3 KiB
Bash
Executable File
144 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Create emergency Git bundle backups from Gitea over Git HTTP.
|
|
# This is a repository-history fallback only. It does not replace `gitea dump`,
|
|
# does not back up Gitea DB rows, settings, issues, packages, secrets, or LFS.
|
|
|
|
set -euo pipefail
|
|
|
|
GITEA_BASE_URL="${GITEA_BASE_URL:-http://192.168.0.110:3001}"
|
|
OUTPUT_ROOT="${OUTPUT_ROOT:-/home/ollama/backup/110/gitea/git-bundles}"
|
|
TIMEOUT_LS_REMOTE_SECONDS="${TIMEOUT_LS_REMOTE_SECONDS:-60}"
|
|
TIMEOUT_CLONE_SECONDS="${TIMEOUT_CLONE_SECONDS:-180}"
|
|
TIMEOUT_BUNDLE_SECONDS="${TIMEOUT_BUNDLE_SECONDS:-180}"
|
|
TIMEOUT_VERIFY_SECONDS="${TIMEOUT_VERIFY_SECONDS:-60}"
|
|
STAMP="${STAMP:-$(date +%Y%m%d-%H%M%S)}"
|
|
DRY_RUN=0
|
|
REPOS=()
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage: scripts/backup/gitea-repo-bundle-backup.sh [options]
|
|
|
|
Options:
|
|
--repo OWNER/NAME Repository to bundle. May be passed more than once.
|
|
--output-root PATH Bundle root. Default: /home/ollama/backup/110/gitea/git-bundles
|
|
--gitea-base URL Gitea base URL. Default: http://192.168.0.110:3001
|
|
--stamp STAMP Output directory stamp. Default: current local timestamp.
|
|
--dry-run Print target URLs without cloning or writing bundles.
|
|
-h, --help Show this help.
|
|
|
|
This script uses GIT_TERMINAL_PROMPT=0 and never asks for, reads, or prints
|
|
tokens or passwords. Private repositories without an existing credential fail
|
|
closed in the manifest.
|
|
USAGE
|
|
}
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--repo)
|
|
shift
|
|
REPOS+=("${1:?--repo requires OWNER/NAME}")
|
|
;;
|
|
--output-root)
|
|
shift
|
|
OUTPUT_ROOT="${1:?--output-root requires PATH}"
|
|
;;
|
|
--gitea-base)
|
|
shift
|
|
GITEA_BASE_URL="${1:?--gitea-base requires URL}"
|
|
;;
|
|
--stamp)
|
|
shift
|
|
STAMP="${1:?--stamp requires value}"
|
|
;;
|
|
--dry-run)
|
|
DRY_RUN=1
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown argument: $1" >&2
|
|
usage >&2
|
|
exit 64
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ "${#REPOS[@]}" -eq 0 ]; then
|
|
REPOS=(
|
|
"wooo/awoooi"
|
|
"wooo/ewoooc"
|
|
"wooo/2026FIFAWorldCup"
|
|
"wooo/agent-bounty-protocol"
|
|
"wooo/AwoooGo"
|
|
"wooo/stockplatform-v2"
|
|
"wooo/vibework"
|
|
)
|
|
fi
|
|
|
|
if [ "$DRY_RUN" -eq 1 ]; then
|
|
for repo in "${REPOS[@]}"; do
|
|
printf 'DRY_RUN repo=%s url=%s/%s.git\n' "$repo" "$GITEA_BASE_URL" "$repo"
|
|
done
|
|
exit 0
|
|
fi
|
|
|
|
backup_root="${OUTPUT_ROOT%/}/${STAMP}"
|
|
tmp_root="$(mktemp -d "${TMPDIR:-/tmp}/gitea-bundle.XXXXXX")"
|
|
manifest="${backup_root}/manifest.tsv"
|
|
mkdir -p "$backup_root"
|
|
trap 'rm -rf "$tmp_root"' EXIT
|
|
|
|
printf 'repo\tstatus\thead_count\tbundle\tchecksum\n' > "$manifest"
|
|
|
|
for repo in "${REPOS[@]}"; do
|
|
slug="${repo//\//__}"
|
|
url="${GITEA_BASE_URL%/}/${repo}.git"
|
|
refs_file="${backup_root}/${slug}.refs"
|
|
err_file="${backup_root}/${slug}.err"
|
|
bundle_file="${backup_root}/${slug}.bundle"
|
|
checksum_file="${bundle_file}.sha256"
|
|
repo_tmp="${tmp_root}/${slug}.git"
|
|
|
|
if ! GIT_TERMINAL_PROMPT=0 timeout "$TIMEOUT_LS_REMOTE_SECONDS" \
|
|
git ls-remote --heads "$url" >"$refs_file" 2>"$err_file"; then
|
|
printf '%s\tls_remote_failed\t0\t\t\n' "$repo" >> "$manifest"
|
|
continue
|
|
fi
|
|
|
|
head_count="$(wc -l < "$refs_file" | tr -d ' ')"
|
|
rm -rf "$repo_tmp"
|
|
if ! GIT_TERMINAL_PROMPT=0 timeout "$TIMEOUT_CLONE_SECONDS" \
|
|
git clone --mirror --quiet "$url" "$repo_tmp" 2>>"$err_file"; then
|
|
printf '%s\tclone_failed\t%s\t\t\n' "$repo" "$head_count" >> "$manifest"
|
|
continue
|
|
fi
|
|
|
|
if ! timeout "$TIMEOUT_BUNDLE_SECONDS" \
|
|
git -C "$repo_tmp" bundle create "$bundle_file" --all >/dev/null 2>>"$err_file"; then
|
|
printf '%s\tbundle_failed\t%s\t\t\n' "$repo" "$head_count" >> "$manifest"
|
|
continue
|
|
fi
|
|
|
|
if ! timeout "$TIMEOUT_VERIFY_SECONDS" \
|
|
git -C "$repo_tmp" bundle verify "$bundle_file" >/dev/null 2>>"$err_file"; then
|
|
printf '%s\tverify_failed\t%s\t%s\t\n' "$repo" "$head_count" "$bundle_file" >> "$manifest"
|
|
continue
|
|
fi
|
|
|
|
(sha256sum "$bundle_file" 2>/dev/null || shasum -a 256 "$bundle_file") > "$checksum_file"
|
|
rm -rf "$repo_tmp"
|
|
printf '%s\tok\t%s\t%s\t%s\n' "$repo" "$head_count" "$bundle_file" "$checksum_file" >> "$manifest"
|
|
done
|
|
|
|
latest_link="${OUTPUT_ROOT%/}/latest"
|
|
if [ ! -e "$latest_link" ] || [ -L "$latest_link" ]; then
|
|
ln -sfn "$backup_root" "$latest_link"
|
|
else
|
|
echo "WARN latest path exists and is not a symlink: $latest_link" >&2
|
|
fi
|
|
cat "$manifest"
|