chore: add gitea backup hook
This commit is contained in:
+4
-1
@@ -3,7 +3,7 @@ SHELL := /bin/bash
|
||||
APP_PORT ?= 18080
|
||||
DATA_FILES := ../data/classnotes.txt ../data/学生课时账户.md
|
||||
|
||||
.PHONY: check smoke data-hash build up ps health deploy logs
|
||||
.PHONY: check smoke data-hash build up ps health deploy logs install-gitea-backup
|
||||
|
||||
check:
|
||||
node --check app/static/app.js
|
||||
@@ -38,3 +38,6 @@ deploy: check smoke
|
||||
|
||||
logs:
|
||||
docker compose logs --tail=120 xsk-records-web
|
||||
|
||||
install-gitea-backup:
|
||||
python3 scripts/install_gitea_backup_hook.py
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
PROJECT_DIR = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="安装提交后自动推送到 Gitea 的 Git hook")
|
||||
parser.add_argument("--remote", default="origin", help="Gitea remote 名称,默认 origin")
|
||||
parser.add_argument("--force", action="store_true", help="覆盖已有 post-commit hook")
|
||||
parser.add_argument("--dry-run", action="store_true", help="只打印将要写入的 hook 内容")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def run_git(args: list[str]) -> str:
|
||||
result = subprocess.run(
|
||||
["git", *args],
|
||||
cwd=PROJECT_DIR,
|
||||
text=True,
|
||||
capture_output=True,
|
||||
check=False,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
raise RuntimeError(result.stderr.strip() or result.stdout.strip())
|
||||
return result.stdout.strip()
|
||||
|
||||
|
||||
def hook_text(remote: str) -> str:
|
||||
return f"""#!/bin/sh
|
||||
set -eu
|
||||
|
||||
remote={remote!r}
|
||||
branch=$(git symbolic-ref --quiet --short HEAD || true)
|
||||
|
||||
if [ -z "$branch" ]; then
|
||||
echo "[gitea-backup] detached HEAD,跳过自动推送" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! git remote get-url "$remote" >/dev/null 2>&1; then
|
||||
echo "[gitea-backup] remote '$remote' 不存在,跳过自动推送" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "[gitea-backup] pushing $branch to $remote"
|
||||
if ! git push "$remote" "HEAD:$branch"; then
|
||||
echo "[gitea-backup] push 失败;本地提交已保留,请检查 SSH key 或远端权限" >&2
|
||||
exit 0
|
||||
fi
|
||||
"""
|
||||
|
||||
|
||||
def main() -> int:
|
||||
args = parse_args()
|
||||
git_dir = Path(run_git(["rev-parse", "--git-dir"]))
|
||||
if not git_dir.is_absolute():
|
||||
git_dir = PROJECT_DIR / git_dir
|
||||
hook_path = git_dir / "hooks" / "post-commit"
|
||||
|
||||
try:
|
||||
remote_url = run_git(["remote", "get-url", args.remote])
|
||||
except RuntimeError:
|
||||
remote_url = ""
|
||||
|
||||
content = hook_text(args.remote)
|
||||
if args.dry_run:
|
||||
print(content)
|
||||
if remote_url:
|
||||
print(f"# remote {args.remote}: {remote_url}")
|
||||
else:
|
||||
print(f"# remote {args.remote}: 未配置")
|
||||
return 0
|
||||
|
||||
if hook_path.exists() and not args.force:
|
||||
raise RuntimeError(f"{hook_path} 已存在;如需覆盖,请加 --force")
|
||||
|
||||
hook_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
hook_path.write_text(content, encoding="utf-8")
|
||||
mode = hook_path.stat().st_mode
|
||||
hook_path.chmod(mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
|
||||
print(f"已安装 {hook_path}")
|
||||
if remote_url:
|
||||
print(f"提交后将自动推送到 {args.remote}: {remote_url}")
|
||||
else:
|
||||
print(f"注意:当前尚未配置 remote '{args.remote}',请先设置 Gitea SSH 地址")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
raise SystemExit(main())
|
||||
except Exception as exc:
|
||||
print(f"安装失败: {exc}", file=sys.stderr)
|
||||
raise SystemExit(1)
|
||||
Reference in New Issue
Block a user