pre-push 2.7 KB

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