From b7f4bbe03ca3db6b433d172d239a5659fbcfae76 Mon Sep 17 00:00:00 2001 From: dongzi Date: Tue, 14 Jul 2026 17:30:35 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B5=81=E6=B0=B4=E7=BA=BF=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=EF=BC=8C=E4=BF=AE=E5=A4=8Dcommit=E6=AC=A1=E6=95=B0?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E4=B8=8D=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/cache-schema-check.yaml | 58 ++++++++++++++++++++++-- docs/CI集成说明.md | 3 +- docs/实施方案.md | 7 ++- 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/.gitea/workflows/cache-schema-check.yaml b/.gitea/workflows/cache-schema-check.yaml index 95d76b3..d7fc265 100644 --- a/.gitea/workflows/cache-schema-check.yaml +++ b/.gitea/workflows/cache-schema-check.yaml @@ -82,6 +82,8 @@ jobs: env: # push 前 tip;新分支首次 push 时为全 0。workflow_dispatch 可能为空,下方会回退。 PUSH_BEFORE: ${{ gitea.event.before }} + # push 事件携带的 commits 列表(JSON);用于准确统计 commit 数(不受浅克隆影响) + PUSH_COMMITS_JSON: ${{ toJson(gitea.event.commits) }} run: | if [ -f /tmp/cache-schema-check.skip ]; then echo "总开关已关闭,跳过检测" @@ -113,7 +115,7 @@ jobs: exit 0 fi - # 确保 before 提交对象可读(按 SHA 浅取,无需全量历史) + # 确保提交对象可读 ensure_commit() { local sha="$1" if git cat-file -e "${sha}^{commit}" 2>/dev/null; then @@ -123,7 +125,6 @@ jobs: if git fetch --depth 1 origin "${sha}"; then git cat-file -e "${sha}^{commit}" 2>/dev/null && return 0 fi - # 兜底:逐步 deepen(应对部分服务端不允许直接 fetch SHA) for d in 10 30 50 100; do echo "deepen ${d}…" git fetch --deepen "${d}" || true @@ -134,6 +135,43 @@ jobs: return 1 } + # 加深当前 tip 的历史,直到 before 成为 after 的祖先(否则 rev-list 在浅克隆下会少算) + ensure_range() { + local old="$1" + local new="$2" + local i=0 + while [ "$i" -lt 15 ]; do + if git merge-base --is-ancestor "${old}" "${new}" 2>/dev/null; then + return 0 + fi + echo "区间历史不完整,deepen 20…(第 $((i + 1)) 次)" + git fetch --deepen 20 || true + i=$((i + 1)) + done + # force-push 等非祖先关系:对象在即可做 git show,但 rev-list 不可靠 + if git cat-file -e "${old}^{commit}" 2>/dev/null \ + && git cat-file -e "${new}^{commit}" 2>/dev/null; then + echo "警告: ${old} 不是 ${new} 的祖先(可能 force-push),commit 计数将改用事件 payload" + return 0 + fi + return 1 + } + + # 优先用 Gitea push 事件的 commits 数组长度(准确且不依赖 shallow) + count_from_payload() { + if [ -z "${PUSH_COMMITS_JSON:-}" ] || [ "${PUSH_COMMITS_JSON}" = "null" ] || [ "${PUSH_COMMITS_JSON}" = "[]" ]; then + return 1 + fi + # Gitea/GitHub push payload: [{"id":"<40位sha>", ...}, ...] + local n + n=$(printf '%s' "${PUSH_COMMITS_JSON}" | grep -oE '"id"[[:space:]]*:[[:space:]]*"[0-9a-fA-F]{7,40}"' | wc -l | tr -d ' ') + if [ -n "$n" ] && [ "$n" -gt 0 ] 2>/dev/null; then + echo "$n" + return 0 + fi + return 1 + } + if ! ensure_commit "$OLD_SHA"; then echo "错误: 无法获取 push 前 tip ${OLD_SHA},请检查 shallow/权限" exit 2 @@ -142,10 +180,22 @@ jobs: echo "错误: 无法解析当前 tip ${NEW_SHA}" exit 2 fi + if ! ensure_range "$OLD_SHA" "$NEW_SHA"; then + echo "错误: 无法补齐 ${OLD_SHA}..${NEW_SHA} 历史" + exit 2 + fi echo "对比区间: ${OLD_SHA} → ${NEW_SHA}" - COMMIT_COUNT=$(git rev-list --count "${OLD_SHA}..${NEW_SHA}" 2>/dev/null || echo "?") - echo "本次 push 累计 commit 数(约): ${COMMIT_COUNT}" + + COMMIT_COUNT="" + if COMMIT_COUNT=$(count_from_payload); then + echo "本次 push 累计 commit 数: ${COMMIT_COUNT}(来自事件 payload)" + elif git merge-base --is-ancestor "$OLD_SHA" "$NEW_SHA" 2>/dev/null; then + COMMIT_COUNT=$(git rev-list --count "${OLD_SHA}..${NEW_SHA}" 2>/dev/null || echo "?") + echo "本次 push 累计 commit 数: ${COMMIT_COUNT}(来自 git rev-list)" + else + echo "本次 push 累计 commit 数: ?(非祖先关系且无 payload)" + fi COMMIT_TIME=$(git log -1 --format=%cd --date=format:'%Y-%m-%d %H:%M:%S' "${NEW_SHA}") diff --git a/docs/CI集成说明.md b/docs/CI集成说明.md index b944275..8aeb4ae 100644 --- a/docs/CI集成说明.md +++ b/docs/CI集成说明.md @@ -36,6 +36,7 @@ mode=block 且含任意结构变更 → exit 1(流水线失败) - `before` 全 `0` / 空 → 新分支首次 push,跳过 - `workflow_dispatch` 无 before → 回退 `HEAD~1` - 中间 commit 改坏又被末 commit 改回 → 累计可能无告警(以最终结构为准) +- commit 计数:优先取 `gitea.event.commits` 长度;否则 deepen 到 `before` 为祖先后再 `git rev-list`(浅克隆下直接 `rev-list` 会少算) --- @@ -141,7 +142,7 @@ com/codechecker/cache-schema-checker/1.0.0/ | 下载 jar 失败 | Nexus 地址/版本错误 | 检查 env 变量 | | 未收到企微 | Secret 未配 / notify.enabled=false / webhook_url 空 | 检查配置 | | 大量误报 | 锁/计数器未过滤 | 补充 ignore.key_patterns | -| 漏报(多 commit) | 业务仓仍用旧版 `HEAD~1` 流水线 | 同步本仓库最新 workflow(`before..after`) | +| commit 数显示为 1(实际多个) | 浅克隆下 `rev-list` 看不到中间提交 | 已修复:优先事件 `commits` 长度;并 deepen 到 before 为祖先 | | 漏报(模式/模块) | W0x 未开 / include_modules 过窄 | 确认 W01~W05;检查模块过滤 | | 类型展开不完整 | 类型在依赖 jar 中 | 补充 `manual_mappings.value_type` | diff --git a/docs/实施方案.md b/docs/实施方案.md index 0639550..2786f6f 100644 --- a/docs/实施方案.md +++ b/docs/实施方案.md @@ -245,12 +245,11 @@ java -jar cache-schema-checker-1.0.0.jar \ 2. `--old-sha` = `gitea.event.before`(push 前 tip) 3. `before` 为空或全 `0`(新分支首次 push)→ 跳过检测,`exit 0` 4. `workflow_dispatch` 无 before 时回退 `HEAD~1` -5. 浅克隆当前 tip(`--depth 1`),再按需 `git fetch --depth 1 ` / `deepen`,**无需全量历史** +5. 浅克隆当前 tip(`--depth 1`),再按需 `git fetch --depth 1 `;统计 commit 数时 deepen 至 `before` 为祖先,或直接用事件 `commits` 数组长度(**无需全量历史**) > 一次 push 含多个 commit 时,只做 **一次** 检测,对比区间为整次 push 的累计 diff(`before..after`),不会漏掉中间 commit 留下的结构变更。 -> 不做「每个 commit 各告警一条」;中间引入又被末 commit 改回的净无变更,累计结果可能为「无变更」(符合阻断「最终结构」的目标)。 - -详见 `docs/CI集成说明.md`。 +> 不做「每个 commit 各告警一条」;中间引入又被末 commit 改回的净无变更,累计结果可能为「无变更」(符合阻断「最终结构」的目标)。 +> 日志中的 commit 数:优先 `gitea.event.commits`;勿在未 deepen 时用浅库 `rev-list`(会少算)。 ### 6.3 处理步骤