pre-push 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #!/usr/bin/env bash
  2. #
  3. # githooks/pre-push — 本地编译闸门(OPS-CI-GATE 方案 A)
  4. #
  5. # 作用:git push 前,对"推送到受保护长期分支 且 涉及 cfc-backend 改动"的 ref
  6. # 执行 `mvn -q -DskipTests compile`;编译失败(红构建)则禁止 push。
  7. # 启用:仓库内执行 `git config core.hooksPath githooks`(每位开发者配置一次)。
  8. # 约束:编译闸门仅在 local(开发者本机)与 iwintrue(远端 CI)执行 —— 本 hook 即 local 侧。
  9. # 临时关闭(紧急 bypass):XAF_CI_GATE=0 git push
  10. #
  11. # 读取 stdin:每行 "<local-ref> <local-sha> <remote-ref> <remote-sha>"
  12. #
  13. set -euo pipefail
  14. # 允许通过环境变量临时关闭
  15. if [ "${XAF_CI_GATE:-1}" = "0" ]; then
  16. echo "[pre-push 编译闸门] XAF_CI_GATE=0,已跳过编译检查。" >&2
  17. exit 0
  18. fi
  19. BACKEND_DIR="cfc-backend"
  20. ZERO="0000000000000000000000000000000000000000"
  21. # 判断本次推送的提交范围是否触及 backend 源码
  22. backend_touched() {
  23. local local_sha="$1" remote_sha="$2"
  24. if [ "$remote_sha" = "$ZERO" ]; then
  25. # 新建分支:与本地 HEAD 的 merge-base 比较
  26. git diff --name-only "$(git merge-base HEAD "$local_sha")" "$local_sha" 2>/dev/null
  27. else
  28. git diff --name-only "$remote_sha" "$local_sha" 2>/dev/null
  29. fi | grep -q "^${BACKEND_DIR}/"
  30. }
  31. need_compile=0
  32. while read -r local_ref local_sha remote_ref remote_sha; do
  33. # 仅对受保护长期分支设闸门;其余分支(个人 feature 等)不拦截,交给远端 CI
  34. case "$remote_ref" in
  35. refs/heads/cfclub|refs/heads/main|refs/heads/master|refs/heads/release/*) ;;
  36. *) continue ;;
  37. esac
  38. if backend_touched "$local_sha" "$remote_sha"; then
  39. need_compile=1
  40. fi
  41. done
  42. if [ "$need_compile" -ne 1 ]; then
  43. exit 0
  44. fi
  45. echo "[pre-push 编译闸门] 检测到 cfc-backend 改动,开始编译校验(mvn -q -DskipTests compile)..." >&2
  46. if ! command -v mvn >/dev/null 2>&1; then
  47. echo "[pre-push 编译闸门] ❌ 未找到 mvn,无法校验编译。请安装 Maven 并加入 PATH;或确认用 XAF_CI_GATE=0 临时跳过(不推荐,红构建将不被拦截)。" >&2
  48. exit 1
  49. fi
  50. if [ ! -d "$BACKEND_DIR" ]; then
  51. echo "[pre-push 编译闸门] ⚠️ 未找到 $BACKEND_DIR 目录,跳过(可能非后端仓库)。" >&2
  52. exit 0
  53. fi
  54. set +e
  55. ( cd "$BACKEND_DIR" && mvn -q -DskipTests compile )
  56. rc=$?
  57. set -e
  58. if [ "$rc" -ne 0 ]; then
  59. echo "[pre-push 编译闸门] ❌ 编译失败(exit=$rc),已阻止 push。请修复后再推送;确认需跳过可用 XAF_CI_GATE=0。" >&2
  60. exit 1
  61. fi
  62. echo "[pre-push 编译闸门] ✅ 编译通过,允许 push。" >&2
  63. exit 0