diff --git a/.githooks/pre-push b/.githooks/pre-push new file mode 100755 index 000000000..1b7cddbe6 --- /dev/null +++ b/.githooks/pre-push @@ -0,0 +1,86 @@ +#!/bin/bash +# ============================================================ +# Pre-push Hook — HIS 项目防误删保护 +# 功能: 推送前检查是否删除了关键文件或大量文件 +# 安装: git config core.hooksPath .githooks +# ============================================================ + +REMOTE="$1" +URL="$2" +ZERO="0000000000000000000000000000000000000000" + +# 受保护路径列表 (严禁删除) +PROTECTED_PATHS=( + "openhis-server-new/pom.xml" + "openhis-server-new/core-admin" + "openhis-server-new/core-framework" + "openhis-server-new/core-system" + "openhis-server-new/core-common" + "openhis-server-new/core-flowable" + "openhis-server-new/core-quartz" + "openhis-server-new/core-generator" + "openhis-server-new/openhis-application" + "openhis-server-new/openhis-domain" + "openhis-server-new/openhis-common" +) + +MAX_DELETE_FILES=100 + +echo "===========================================" +echo " Pre-push: 推送安全检查" +echo "===========================================" + +while read local_ref local_sha remote_ref remote_sha; do + # 跳过删除分支操作 + [ "$local_sha" = "$ZERO" ] && continue + + # 新分支没有 remote_sha,用 origin/develop 做基准 + if [ "$remote_sha" = "$ZERO" ]; then + remote_sha=$(git rev-parse origin/develop 2>/dev/null || echo "") + [ -z "$remote_sha" ] && continue + fi + + # ==== 检查 1: 是否删除了受保护路径 ==== + for path in "${PROTECTED_PATHS[@]}"; do + if git diff --name-status "$remote_sha".."$local_sha" 2>/dev/null | grep -q "^D.*$path"; then + echo "错误: 受保护路径被删除!" + echo " 路径: $path" + echo " 本次推送已拦截。如确有需要,请联系仓库管理员。" + exit 1 + fi + done + + # ==== 检查 2: 是否删除了过多文件 ==== + delete_count=$(git diff --name-status "$remote_sha".."$local_sha" 2>/dev/null | grep -c "^D") + if [ "$delete_count" -gt "$MAX_DELETE_FILES" ]; then + echo "错误: 本次推送删除了 $delete_count 个文件 (阈值: $MAX_DELETE_FILES)" + echo " 请检查是否有误删操作。确认需要推送请执行:" + echo " git push --no-verify origin $local_ref:$remote_ref" + exit 1 + fi + + # ==== 检查 3: 是否删除了 pom.xml (任何位置) ==== + deleted_poms=$(git diff --name-status "$remote_sha".."$local_sha" 2>/dev/null | grep "^D.*pom.xml") + if [ -n "$deleted_poms" ]; then + echo "错误: pom.xml 文件被删除!" + echo "$deleted_poms" + echo " 本次推送已拦截。" + exit 1 + fi + + # ==== 检查 4: 删除/新增比例异常 ==== + add_count=$(git diff --name-status "$remote_sha".."$local_sha" 2>/dev/null | grep -c "^[AMR]") + if [ "$delete_count" -gt 0 ] && [ "$add_count" -gt 0 ]; then + ratio=$((delete_count * 100 / add_count)) + if [ "$ratio" -gt 80 ]; then + echo "警告: 删除文件比例异常 ($ratio% 是删除)" + echo " 删除: $delete_count / 新增: $add_count" + echo " 请人工确认后重新推送。" + exit 1 + fi + fi + + echo "Pre-push 检查通过 ($add_count 新增, $delete_count 删除)" +done + +exit 0 diff --git a/AGENTS.md b/AGENTS.md index eda61f305..0998f143d 100755 --- a/AGENTS.md +++ b/AGENTS.md @@ -185,4 +185,22 @@ npm run preview - 前端端口:81 - API 前缀:`/openhis` - Swagger UI:`/openhis/swagger-ui/index.html` -- Druid 监控:`/openhis/druid/login.html` \ No newline at end of file +- Druid 监控:`/openhis/druid/login.html` +## 🔒 安全铁律 + +### 受保护路径(严禁删除) +以下文件和目录在任何提交中都禁止删除: +- `openhis-server-new/pom.xml` +- `openhis-server-new/core-admin/`、`core-common/`、`core-flowable/`、`core-framework/`、`core-generator/`、`core-quartz/`、`core-system/` +- `openhis-server-new/openhis-application/`、`openhis-domain/`、`openhis-common/` +- 任何 `pom.xml` 文件 + +### 提交规范 +1. **单次提交删除文件数不得超过 100 个** +2. **删除/新增文件比例不得超过 80%** +3. **提交前执行 `git diff --stat` 检查变更范围** +4. **不确定的操作优先用 `git revert` 而不是 `git rm`** + +### 违规后果 +违反上述规则会导致推送被 `pre-push` 钩子拦截,或触发 Gitea 分支保护规则。 +