Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m1s
CD Pipeline / build-and-deploy (push) Successful in 4m25s
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 0s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Failing after 29s
CD Pipeline / post-deploy-checks (push) Successful in 1m45s
150 lines
5.0 KiB
Bash
Executable File
150 lines
5.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Verify one Gitea bundle can be restored into a temporary mirror clone.
|
|
# This is a dry-run verifier only. It does not restore into production, mutate
|
|
# Gitea, read credentials, delete repositories, or change repo visibility.
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT="${AIOPS_GITEA_BUNDLE_ROOT:-/home/ollama/backup/110/gitea/git-bundles/latest-private-complete}"
|
|
REPO="${AIOPS_GITEA_BUNDLE_SAMPLE_REPO:-wooo/awoooi}"
|
|
HOST_LABEL="${AIOPS_HOST_LABEL:-188}"
|
|
TEXTFILE_PATH="${AIOPS_GITEA_BUNDLE_RESTORE_TEXTFILE:-/home/ollama/node_exporter_textfiles/gitea_bundle_restore_dry_run.prom}"
|
|
WRITE_TEXTFILE=0
|
|
TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-120}"
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage: scripts/backup/gitea-bundle-sample-restore-dry-run.sh [options]
|
|
|
|
Options:
|
|
--root PATH Bundle root directory.
|
|
--repo OWNER/NAME Repository sample to verify. Default: wooo/awoooi.
|
|
--write-textfile Write node-exporter textfile metric after verification.
|
|
--textfile PATH Textfile metric path.
|
|
-h, --help Show this help.
|
|
|
|
This verifier clones the bundle into a temporary mirror and runs git fsck.
|
|
It never restores to production, never contacts Gitea, and never reads tokens.
|
|
USAGE
|
|
}
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--root)
|
|
shift
|
|
ROOT="${1:?--root requires PATH}"
|
|
;;
|
|
--repo)
|
|
shift
|
|
REPO="${1:?--repo requires OWNER/NAME}"
|
|
;;
|
|
--write-textfile)
|
|
WRITE_TEXTFILE=1
|
|
;;
|
|
--textfile)
|
|
shift
|
|
TEXTFILE_PATH="${1:?--textfile requires PATH}"
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown argument: $1" >&2
|
|
usage >&2
|
|
exit 64
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
slug="${REPO//\//__}"
|
|
repo_name="${REPO##*/}"
|
|
bundle_path=""
|
|
checksum_path=""
|
|
|
|
if [ -f "${ROOT}/${slug}.bundle" ]; then
|
|
bundle_path="${ROOT}/${slug}.bundle"
|
|
elif [ -f "${ROOT}/manifest.remote.tsv" ] || [ -f "${ROOT}/manifest.tsv" ]; then
|
|
manifest="${ROOT}/manifest.remote.tsv"
|
|
[ -f "$manifest" ] || manifest="${ROOT}/manifest.tsv"
|
|
bundle_path="$(awk -F '\t' -v repo="$REPO" 'NR > 1 && $1 == repo {print $4; exit}' "$manifest")"
|
|
if [ -n "$bundle_path" ] && [ ! -f "$bundle_path" ] && [ -f "${ROOT}/$(basename "$bundle_path")" ]; then
|
|
bundle_path="${ROOT}/$(basename "$bundle_path")"
|
|
fi
|
|
fi
|
|
|
|
if [ -z "$bundle_path" ] || [ ! -f "$bundle_path" ]; then
|
|
first_match="$(find "$ROOT" -maxdepth 1 -type f -name "${repo_name}-local-*.bundle" | sort | tail -n 1)"
|
|
bundle_path="$first_match"
|
|
fi
|
|
|
|
ok=0
|
|
ref_count=0
|
|
error_reason=""
|
|
tmp_root=""
|
|
|
|
if [ -z "$bundle_path" ] || [ ! -f "$bundle_path" ]; then
|
|
error_reason="bundle_not_found"
|
|
else
|
|
checksum_path="${bundle_path}.sha256"
|
|
if [ -f "$checksum_path" ]; then
|
|
expected="$(awk 'NR == 1 {print $1}' "$checksum_path")"
|
|
if command -v sha256sum >/dev/null 2>&1; then
|
|
actual="$(sha256sum "$bundle_path" | awk '{print $1}')"
|
|
else
|
|
actual="$(shasum -a 256 "$bundle_path" | awk '{print $1}')"
|
|
fi
|
|
if [ "$expected" != "$actual" ]; then
|
|
error_reason="checksum_mismatch"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if [ -z "$error_reason" ]; then
|
|
tmp_root="$(mktemp -d "${TMPDIR:-/tmp}/gitea-bundle-restore.XXXXXX")"
|
|
trap 'rm -rf "$tmp_root"' EXIT
|
|
if ! timeout "$TIMEOUT_SECONDS" git clone --mirror --quiet "$bundle_path" "${tmp_root}/restore.git"; then
|
|
error_reason="clone_failed"
|
|
elif ! timeout "$TIMEOUT_SECONDS" git -C "${tmp_root}/restore.git" fsck --connectivity-only >/dev/null; then
|
|
error_reason="fsck_failed"
|
|
else
|
|
ref_count="$(git -C "${tmp_root}/restore.git" for-each-ref --format='%(refname)' | wc -l | tr -d ' ')"
|
|
ok=1
|
|
fi
|
|
fi
|
|
|
|
timestamp="$(date +%s)"
|
|
bundle_name="$(basename "${bundle_path:-missing}")"
|
|
root_label="${ROOT//\\/\\\\}"
|
|
root_label="${root_label//\"/\\\"}"
|
|
repo_label="${REPO//\\/\\\\}"
|
|
repo_label="${repo_label//\"/\\\"}"
|
|
bundle_label="${bundle_name//\\/\\\\}"
|
|
bundle_label="${bundle_label//\"/\\\"}"
|
|
error_label="${error_reason//\\/\\\\}"
|
|
error_label="${error_label//\"/\\\"}"
|
|
|
|
if [ "$WRITE_TEXTFILE" -eq 1 ]; then
|
|
mkdir -p "$(dirname "$TEXTFILE_PATH")"
|
|
tmp_textfile="${TEXTFILE_PATH}.$$"
|
|
{
|
|
echo '# HELP awoooi_gitea_bundle_sample_restore_dry_run_ok Whether sample Gitea bundle restore dry-run succeeded.'
|
|
echo '# TYPE awoooi_gitea_bundle_sample_restore_dry_run_ok gauge'
|
|
printf 'awoooi_gitea_bundle_sample_restore_dry_run_ok{host="%s",repo="%s",root="%s",bundle="%s",error="%s"} %s\n' "$HOST_LABEL" "$repo_label" "$root_label" "$bundle_label" "$error_label" "$ok"
|
|
printf 'awoooi_gitea_bundle_sample_restore_dry_run_timestamp{host="%s",repo="%s"} %s\n' "$HOST_LABEL" "$repo_label" "$timestamp"
|
|
printf 'awoooi_gitea_bundle_sample_restore_dry_run_ref_count{host="%s",repo="%s"} %s\n' "$HOST_LABEL" "$repo_label" "$ref_count"
|
|
} > "$tmp_textfile"
|
|
mv "$tmp_textfile" "$TEXTFILE_PATH"
|
|
fi
|
|
|
|
printf 'GITEA_BUNDLE_SAMPLE_RESTORE_DRY_RUN_OK=%s\n' "$ok"
|
|
printf 'REPO=%s\n' "$REPO"
|
|
printf 'BUNDLE=%s\n' "${bundle_path:-missing}"
|
|
printf 'REF_COUNT=%s\n' "$ref_count"
|
|
printf 'TEXTFILE_WRITTEN=%s\n' "$WRITE_TEXTFILE"
|
|
if [ -n "$error_reason" ]; then
|
|
printf 'ERROR=%s\n' "$error_reason"
|
|
exit 1
|
|
fi
|