已合并
【fix】: 修复precommit的oat检查抢资源问题 #1052
zhangfands创建于 6月26日
【fix】: 修复precommit的oat检查抢资源问题 #1052
已合并
共 3 个文件变更+179-33
| @@ -1,9 +1,14 @@ | |||
| 1 | repos: | 1 | repos: |
| 2 | - - repo: https://github.com/pre-commit/mirrors-clang-format | 2 | + - repo: https://gitcode.com/pre-commit-clang/mirrors-clang-format |
| 3 | - rev: v16.0.0 | 3 | + rev: v18.1.8 |
| 4 | hooks: | 4 | hooks: |
| 5 | - id: clang-format | 5 | - id: clang-format |
| 6 | - types_or: [c++, c] | 6 | + files: \.(c|h|cpp|hpp|cc|hh|cxx|hxx)$ |
| 7 | + args: | ||
| 8 | + - "--style={BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 120, BreakBeforeBraces: Allman}" | ||
| 9 | + - "--verbose" | ||
| 10 | + - "-i" | ||
| 11 | + exclude: ^build/|tests/third_party/ | ||
| 7 | 12 | ||
| 8 | # OAT compliance check (Open Source Audit Tool) | 13 | # OAT compliance check (Open Source Audit Tool) |
| 9 | - repo: local | 14 | - repo: local |
| @@ -1,10 +1,10 @@ | |||
| 1 | 1 | ||
| 2 | <!-- Copyright (c) 2025 Huawei Technologies Co., Ltd. | 2 | <!-- Copyright (c) 2025 Huawei Technologies Co., Ltd. |
| 3 | - This program is free software, you can redistribute it and/or modify it under the terms and conditions of | 3 | + This program is free software, you can redistribute it and/or modify it under the terms and conditions of |
| 4 | CANN Open Software License Agreement Version 2.0 (the "License"). | 4 | CANN Open Software License Agreement Version 2.0 (the "License"). |
| 5 | Please refer to the License for details. You may not use this file except in compliance with the License. | 5 | Please refer to the License for details. You may not use this file except in compliance with the License. |
| 6 | - THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | 6 | + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, |
| 7 | - INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | 7 | + INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. |
| 8 | See LICENSE in the root of the software repository for the full text of the License. | 8 | See LICENSE in the root of the software repository for the full text of the License. |
| 9 | --> | 9 | --> |
| 10 | 10 | ||
| @@ -28,6 +28,9 @@ | |||
| 28 | <!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/--> | 28 | <!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/--> |
| 29 | <!--filteritem type="filepath" name="abcdefg/.*.uvwxyz" desc="Describe the reason for filtering scan results"/--> | 29 | <!--filteritem type="filepath" name="abcdefg/.*.uvwxyz" desc="Describe the reason for filtering scan results"/--> |
| 30 | <!--filteritem type="filepath" name="projectroot/[a-zA-Z0-9]{20,}.sh" desc="Temp files"/--> | 30 | <!--filteritem type="filepath" name="projectroot/[a-zA-Z0-9]{20,}.sh" desc="Temp files"/--> |
| 31 | + <!-- 排除 YAML 配置文件 --> | ||
| 32 | + <filteritem type="filename" name="*.yaml" desc="YAML config files"/> | ||
| 33 | + <filteritem type="filename" name="*.yml" desc="YAML config files"/> | ||
| 31 | </filefilter> | 34 | </filefilter> |
| 32 | <filefilter name="copyrightPolicyFilter" desc="Filters for copyright header policies"> | 35 | <filefilter name="copyrightPolicyFilter" desc="Filters for copyright header policies"> |
| 33 | <!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/--> | 36 | <!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/--> |
| @@ -59,11 +62,11 @@ | |||
| 59 | <licensematcherlist> | 62 | <licensematcherlist> |
| 60 | <licensematcher name="cann License" desc="If the scanning result is InvalidLicense, you can define matching rules here. Note that quotation marks must be escaped."> | 63 | <licensematcher name="cann License" desc="If the scanning result is InvalidLicense, you can define matching rules here. Note that quotation marks must be escaped."> |
| 61 | <licensetext name=" | 64 | <licensetext name=" |
| 62 | - This program is free software, you can redistribute it and/or modify it under the terms and conditions of | 65 | + This program is free software, you can redistribute it and/or modify it under the terms and conditions of |
| 63 | CANN Open Software License Agreement Version 2.0 (the "License"). | 66 | CANN Open Software License Agreement Version 2.0 (the "License"). |
| 64 | Please refer to the License for details. You may not use this file except in compliance with the License. | 67 | Please refer to the License for details. You may not use this file except in compliance with the License. |
| 65 | - THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | 68 | + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, |
| 66 | - INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | 69 | + INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. |
| 67 | See LICENSE in the root of the software repository for the full text of the License. | 70 | See LICENSE in the root of the software repository for the full text of the License. |
| 68 | " desc=""/> | 71 | " desc=""/> |
| 69 | </licensematcher> | 72 | </licensematcher> |
| @@ -48,12 +48,25 @@ if [ -z "$_PYTHON" ]; then | |||
| 48 | fi | 48 | fi |
| 49 | 49 | ||
| 50 | # --------------------------------------------------------------------------- | 50 | # --------------------------------------------------------------------------- |
| 51 | -# 1. Ensure oat-py is installed | 51 | +# 1. Ensure oat-py is installed (serialized via flock to prevent parallel pip conflicts) |
| 52 | # --------------------------------------------------------------------------- | 52 | # --------------------------------------------------------------------------- |
| 53 | _OAT_OK=$("$_PYTHON" -c "import importlib.util; print('ok' if importlib.util.find_spec('oat') else 'missing')" 2>/dev/null || echo "missing") | 53 | _OAT_OK=$("$_PYTHON" -c "import importlib.util; print('ok' if importlib.util.find_spec('oat') else 'missing')" 2>/dev/null || echo "missing") |
| 54 | if [ "$_OAT_OK" != "ok" ]; then | 54 | if [ "$_OAT_OK" != "ok" ]; then |
| 55 | echo "[OAT] oat-py not found. Installing oat-py>=1.0.1 ..." | 55 | echo "[OAT] oat-py not found. Installing oat-py>=1.0.1 ..." |
| 56 | - "$_PYTHON" -m pip install --quiet "oat-py>=1.0.1" | 56 | + _LOCK_FILE="/tmp/oat_pip_install.lock" |
| 57 | + # flock ensures only one concurrent invocation runs pip install at a time; | ||
| 58 | + # re-check inside the lock so processes that waited skip redundant installs | ||
| 59 | + if command -v flock >/dev/null 2>&1; then | ||
🔴 High | 问题代码块:
根因:脚本不 触发条件:前一个 instance 真的卡死 > 2 分钟(罕见但可能——比如 oat 子进程 hang 在大仓库上,或者前一个 instance 等外部锁 / 慢 IO)。 修复:
![]() ![]() | |||
| 60 | + ( | ||
| 61 | + flock -w 120 9 | ||
| 62 | + _RECHECK=$("$_PYTHON" -c "import importlib.util; print('ok' if importlib.util.find_spec('oat') else 'missing')" 2>/dev/null || echo "missing") | ||
| 63 | + if [ "$_RECHECK" != "ok" ]; then | ||
| 64 | + "$_PYTHON" -m pip install --quiet "oat-py>=1.0.1" | ||
| 65 | + fi | ||
| 66 | + ) 9>"$_LOCK_FILE" | ||
| 67 | + else | ||
| 68 | + "$_PYTHON" -m pip install --quiet "oat-py>=1.0.1" | ||
| 69 | + fi | ||
| 57 | _OAT_OK=$("$_PYTHON" -c "import importlib.util; print('ok' if importlib.util.find_spec('oat') else 'missing')" 2>/dev/null || echo "missing") | 70 | _OAT_OK=$("$_PYTHON" -c "import importlib.util; print('ok' if importlib.util.find_spec('oat') else 'missing')" 2>/dev/null || echo "missing") |
| 58 | if [ "$_OAT_OK" != "ok" ]; then | 71 | if [ "$_OAT_OK" != "ok" ]; then |
| 59 | echo "[OAT] [WARNING] Failed to install oat-py. Please run: pip install oat-py>=1.0.1" | 72 | echo "[OAT] [WARNING] Failed to install oat-py. Please run: pip install oat-py>=1.0.1" |
| @@ -68,10 +81,99 @@ fi | |||
| 68 | # --------------------------------------------------------------------------- | 81 | # --------------------------------------------------------------------------- |
| 69 | REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd) | 82 | REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd) |
| 70 | REPO_NAME=$(basename "$REPO_ROOT") | 83 | REPO_NAME=$(basename "$REPO_ROOT") |
| 71 | -OAT_REPORT_DIR="$REPO_ROOT/oat_reports" | 84 | +OAT_REPORT_DIR="${TMPDIR:-/tmp}/oat_reports_$$" |
| 85 | +OAT_RESULT_DIR="$REPO_ROOT/oat_reports" | ||
🟡 Medium | 事实:
影响(用户/工具链可能踩的坑):
修法二选一:
为什么不阻塞但要发:
![]() ![]() | |||
| 72 | 86 | ||
| 73 | -echo "[OAT] Running OAT scan (Python Edition) — INCREMENTAL MODE" | 87 | +# --------------------------------------------------------------------------- |
| 88 | +# 2a. PR-range deduplication (pure git, no CI env vars required) | ||
| 89 | +# | ||
| 90 | +# Strategy: | ||
| 91 | +# 1. Find the merge-base between HEAD and the upstream branch (origin/master | ||
| 92 | +# or similar). If found, this is a feature-branch context ??collect ALL | ||
| 93 | +# files changed since the branch diverged (full PR diff). | ||
| 94 | +# 2. Key a done-marker on the HEAD SHA. The first invocation runs the scan; | ||
| 95 | +# every subsequent invocation for the same HEAD exits 0 immediately. | ||
| 96 | +# This eliminates redundant scans when CI calls the hook once per commit. | ||
| 97 | +# 3. If no merge-base is found (e.g. committing directly on master) fall back | ||
| 98 | +# to scanning only the currently staged files, with no done-marker. | ||
| 99 | +# --------------------------------------------------------------------------- | ||
| 100 | +_PR_MERGE_BASE="" | ||
| 101 | +_DONE_MARKER="" | ||
| 102 | +_HEAD_SHA=$(git rev-parse HEAD 2>/dev/null | cut -c1-12 || true) | ||
| 103 | + | ||
| 104 | +if [ -n "$_HEAD_SHA" ]; then | ||
| 105 | + # Try to find merge-base with a known upstream branch | ||
| 106 | + if [ -n "${PRE_COMMIT_FROM_REF:-}" ]; then | ||
| 107 | + # pre-commit --from-ref/--to-ref: use the provided base directly | ||
| 108 | + _PR_MERGE_BASE=$(git merge-base "$PRE_COMMIT_FROM_REF" HEAD 2>/dev/null || true) | ||
| 109 | + fi | ||
| 110 | + if [ -z "$_PR_MERGE_BASE" ]; then | ||
| 111 | + # Search all remotes (origin, upstream, etc.) for common trunk branch names. | ||
| 112 | + # This handles fork setups where origin=fork and upstream=main-repo. | ||
| 113 | + _CANDIDATE_BASE="" | ||
| 114 | + _CANDIDATE_DIST=0 | ||
| 115 | + for _b in $(git for-each-ref --format='%(refname:short)' \ | ||
| 116 | + 'refs/remotes/*/master' 'refs/remotes/*/main' \ | ||
| 117 | + 'refs/remotes/*/develop' 'refs/remotes/*/dev' 2>/dev/null); do | ||
| 118 | + _mb=$(git merge-base HEAD "$_b" 2>/dev/null || true) | ||
| 119 | + [ -z "$_mb" ] && continue | ||
| 120 | + # Skip if merge-base is HEAD itself (branch is ahead of or equal to HEAD) | ||
| 121 | + [ "$_mb" = "$(git rev-parse HEAD 2>/dev/null)" ] && continue | ||
| 122 | + # Pick the candidate whose merge-base is furthest from HEAD | ||
| 123 | + # (most commits since divergence = most likely true PR base) | ||
| 124 | + _dist=$(git rev-list --count "$_mb"..HEAD 2>/dev/null || echo 0) | ||
| 125 | + if [ -z "$_CANDIDATE_BASE" ] || [ "$_dist" -gt "$_CANDIDATE_DIST" ]; then | ||
| 126 | + _CANDIDATE_BASE="$_mb" | ||
| 127 | + _CANDIDATE_DIST="$_dist" | ||
| 128 | + fi | ||
| 129 | + done | ||
| 130 | + _PR_MERGE_BASE="$_CANDIDATE_BASE" | ||
| 131 | + fi | ||
| 132 | + | ||
| 133 | + # Only use PR-range mode when HEAD has diverged from the upstream base | ||
| 134 | + if [ -n "$_PR_MERGE_BASE" ] && [ "$_PR_MERGE_BASE" != "$(git rev-parse HEAD 2>/dev/null)" ]; then | ||
| 135 | + mkdir -p "$OAT_RESULT_DIR" | ||
| 136 | + _DONE_MARKER="$OAT_RESULT_DIR/.done_${_HEAD_SHA}" | ||
| 137 | + if [ -f "$_DONE_MARKER" ]; then | ||
| 138 | + echo "[OAT] [SKIP] Already scanned HEAD=${_HEAD_SHA}. Skipping duplicate invocation." | ||
| 139 | + exit 0 | ||
| 140 | + fi | ||
| 141 | + else | ||
| 142 | + # HEAD == merge-base: on the upstream branch itself, no PR range | ||
| 143 | + _PR_MERGE_BASE="" | ||
| 144 | + fi | ||
| 145 | +fi | ||
| 146 | + | ||
| 147 | +# --------------------------------------------------------------------------- | ||
| 148 | +# 2b. Deduplicate parallel invocations within the same pre-commit run. | ||
| 149 | +# Only the first instance that acquires the lock actually runs the scan; | ||
| 150 | +# all others wait then exit 0. | ||
| 151 | +# --------------------------------------------------------------------------- | ||
| 152 | +if command -v flock >/dev/null 2>&1; then | ||
| 153 | + _OAT_SCAN_LOCK="${TMPDIR:-/tmp}/oat_scan_$(echo "$REPO_ROOT" | tr '/\\: ' '____').lock" | ||
| 154 | + exec 9>"$_OAT_SCAN_LOCK" | ||
| 155 | + if ! flock -n 9; then | ||
| 156 | + echo "[OAT] Another OAT scan instance is running. Waiting..." | ||
| 157 | + flock -w 120 9 | ||
| 158 | + # Re-check done marker: if the scanning instance completed normally, skip. | ||
| 159 | + # If it exited abnormally (no marker), fall through and run the scan ourselves. | ||
| 160 | + if [ -n "$_DONE_MARKER" ] && [ -f "$_DONE_MARKER" ]; then | ||
| 161 | + echo "[OAT] Scan already completed by another instance. Skipping." | ||
| 162 | + exit 0 | ||
| 163 | + fi | ||
| 164 | + echo "[OAT] Previous instance did not complete. Proceeding with scan..." | ||
| 165 | + # Fall through to run the scan below | ||
| 166 | + fi | ||
| 167 | + # This instance now owns the lock and will run the scan. | ||
| 168 | +fi | ||
| 169 | + | ||
| 170 | +echo "[OAT] Running OAT scan (Python Edition) ??INCREMENTAL MODE" | ||
| 74 | echo "[OAT] Project: $REPO_NAME" | 171 | echo "[OAT] Project: $REPO_NAME" |
| 172 | +if [ -n "$_PR_MERGE_BASE" ]; then | ||
| 173 | + echo "[OAT] Mode: PR range ??scanning all files changed since merge-base" | ||
| 174 | +else | ||
| 175 | + echo "[OAT] Mode: staged files ??scanning only currently staged files" | ||
| 176 | +fi | ||
| 75 | 177 | ||
| 76 | # --------------------------------------------------------------------------- | 178 | # --------------------------------------------------------------------------- |
| 77 | # 3. Collect staged files | 179 | # 3. Collect staged files |
| @@ -93,7 +195,31 @@ if [ $# -gt 0 ]; then | |||
| 93 | FILE_LIST="$FILE_LIST,$_abs" | 195 | FILE_LIST="$FILE_LIST,$_abs" |
| 94 | fi | 196 | fi |
| 95 | done | 197 | done |
| 198 | +elif [ -n "$_PR_MERGE_BASE" ]; then | ||
| 199 | + # PR range mode: collect ALL files changed since the branch diverged | ||
| 200 | + _STAGED=$(git diff --name-only --diff-filter=ACM "$_PR_MERGE_BASE" HEAD \ | ||
| 201 | + 2>/dev/null || true) | ||
| 202 | + if [ -z "$_STAGED" ]; then | ||
| 203 | + echo "[OAT] No files changed in PR range. Skipping." | ||
| 204 | + [ -n "$_DONE_MARKER" ] && touch "$_DONE_MARKER" 2>/dev/null || true | ||
| 205 | + exit 0 | ||
| 206 | + fi | ||
| 207 | + FILE_COUNT=$(echo "$_STAGED" | wc -l | tr -d ' ') | ||
| 208 | + FILE_LIST="" | ||
| 209 | + for _f in $_STAGED; do | ||
| 210 | + case "$_f" in | ||
| 211 | + /*) _abs="$_f" ;; | ||
| 212 | + *) _abs="$REPO_ROOT/$_f" ;; | ||
| 213 | + esac | ||
| 214 | + [ -f "$_abs" ] || continue | ||
| 215 | + if [ -z "$FILE_LIST" ]; then | ||
| 216 | + FILE_LIST="$_abs" | ||
| 217 | + else | ||
| 218 | + FILE_LIST="$FILE_LIST,$_abs" | ||
| 219 | + fi | ||
| 220 | + done | ||
| 96 | else | 221 | else |
| 222 | + # Staged files mode: on upstream branch directly, scan only staged files | ||
| 97 | _STAGED=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null || true) | 223 | _STAGED=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null || true) |
| 98 | if [ -z "$_STAGED" ]; then | 224 | if [ -z "$_STAGED" ]; then |
| 99 | echo "[OAT] No staged files to check. Skipping." | 225 | echo "[OAT] No staged files to check. Skipping." |
| @@ -123,19 +249,13 @@ fi | |||
| 123 | echo "[OAT] Checking $FILE_COUNT staged file(s)..." | 249 | echo "[OAT] Checking $FILE_COUNT staged file(s)..." |
| 124 | 250 | ||
| 125 | # --------------------------------------------------------------------------- | 251 | # --------------------------------------------------------------------------- |
| 126 | -# 4. Ensure oat_reports/ exists | 252 | +# 4. Ensure report directories exist |
| 127 | # --------------------------------------------------------------------------- | 253 | # --------------------------------------------------------------------------- |
| 128 | mkdir -p "$OAT_REPORT_DIR" | 254 | mkdir -p "$OAT_REPORT_DIR" |
| 129 | - | 255 | +mkdir -p "$OAT_RESULT_DIR" |
| 130 | -_GITIGNORE="$REPO_ROOT/.gitignore" | ||
| 131 | -for _entry in "oat_reports" "log"; do | ||
| 132 | - if ! grep -qE "^${_entry}/?$" "$_GITIGNORE" 2>/dev/null; then | ||
| 133 | - echo "[OAT] [WARNING] '${_entry}/' is not in .gitignore. Consider adding it to avoid committing scan artifacts." | ||
| 134 | - fi | ||
| 135 | -done | ||
| 136 | 256 | ||
| 137 | # --------------------------------------------------------------------------- | 257 | # --------------------------------------------------------------------------- |
| 138 | -# 5. Build oat command — use OAT.xml if present in repo root | 258 | +# 5. Build oat command ??use OAT.xml if present in repo root |
| 139 | # --------------------------------------------------------------------------- | 259 | # --------------------------------------------------------------------------- |
| 140 | _OAT_CMD="$_PYTHON -m oat -mode s -s $REPO_ROOT -r $OAT_REPORT_DIR -n $REPO_NAME -w 1 -f $FILE_LIST" | 260 | _OAT_CMD="$_PYTHON -m oat -mode s -s $REPO_ROOT -r $OAT_REPORT_DIR -n $REPO_NAME -w 1 -f $FILE_LIST" |
| 141 | 261 | ||
| @@ -169,7 +289,7 @@ fi | |||
| 169 | # Only: Invalid File Type + License Header Invalid (no copyright) | 289 | # Only: Invalid File Type + License Header Invalid (no copyright) |
| 170 | # --------------------------------------------------------------------------- | 290 | # --------------------------------------------------------------------------- |
| 171 | REPORT_FILE="$OAT_REPORT_DIR/PlainReport_${REPO_NAME}.txt" | 291 | REPORT_FILE="$OAT_REPORT_DIR/PlainReport_${REPO_NAME}.txt" |
| 172 | -RESULT_FILE="$OAT_REPORT_DIR/result.txt" | 292 | +RESULT_FILE="$OAT_RESULT_DIR/result.txt" |
| 173 | 293 | ||
| 174 | # Section headers used as stop-boundaries when extracting sections | 294 | # Section headers used as stop-boundaries when extracting sections |
| 175 | _ALL_HEADERS="Invalid File Type Total Count:|License Not Compatible Total Count:|License Header Invalid Total Count:|Copyright Header Invalid Total Count:|No License File Total Count:|No Readme.OpenSource Total Count:|No Readme Total Count:|Import Invalid Total Count:|Redundant License File Total Count:|Third Party Software Info Total Count:" | 295 | _ALL_HEADERS="Invalid File Type Total Count:|License Not Compatible Total Count:|License Header Invalid Total Count:|Copyright Header Invalid Total Count:|No License File Total Count:|No Readme.OpenSource Total Count:|No Readme Total Count:|Import Invalid Total Count:|Redundant License File Total Count:|Third Party Software Info Total Count:" |
| @@ -200,17 +320,29 @@ _extract_section() { | |||
| 200 | 320 | ||
| 201 | if [ ! -f "$REPORT_FILE" ]; then | 321 | if [ ! -f "$REPORT_FILE" ]; then |
| 202 | if [ "$_OAT_RC" -eq 0 ]; then | 322 | if [ "$_OAT_RC" -eq 0 ]; then |
| 323 | + # oat exited cleanly with no report: all staged files were filtered out | ||
| 203 | echo "[OAT] [OK] All checks passed ($FILE_COUNT file(s) checked)." | 324 | echo "[OAT] [OK] All checks passed ($FILE_COUNT file(s) checked)." |
| 325 | + [ -n "$_DONE_MARKER" ] && touch "$_DONE_MARKER" 2>/dev/null || true | ||
| 326 | + rm -rf "$OAT_REPORT_DIR" | ||
| 204 | exit 0 | 327 | exit 0 |
| 205 | else | 328 | else |
| 206 | - echo "[OAT] [WARNING] Report not found: $REPORT_FILE" | 329 | + # oat returned exit code 1 but produced no report — possible disk issue |
| 330 | + # or oat internal error. Do not silently pass; block the commit. | ||
| 331 | + echo "" | ||
| 332 | + echo "[OAT] [ERROR] oat exited with code $_OAT_RC but no report was generated." | ||
| 333 | + echo "[OAT] This may indicate a disk error or an oat internal bug." | ||
| 334 | + echo "[OAT] To investigate, run manually:" | ||
| 335 | + echo " $_OAT_CMD" | ||
| 336 | + echo "[OAT] Blocking commit to prevent silent compliance bypass." | ||
| 337 | + echo "" | ||
| 338 | + rm -rf "$OAT_REPORT_DIR" | ||
| 207 | exit 1 | 339 | exit 1 |
| 208 | fi | 340 | fi |
| 209 | fi | 341 | fi |
| 210 | 342 | ||
| 211 | -# Parse counts | 343 | +# Parse counts ??use || true to prevent set -e from triggering if grep finds no match |
| 212 | -_INVALID_TYPE=$(grep "^Invalid File Type Total Count:" "$REPORT_FILE" | grep -oE '[0-9]+' | head -1) | 344 | +_INVALID_TYPE=$(grep "^Invalid File Type Total Count:" "$REPORT_FILE" | grep -oE '[0-9]+' | head -1 || true) |
| 213 | -_LICENSE_INVALID=$(grep "^License Header Invalid Total Count:" "$REPORT_FILE" | grep -oE '[0-9]+' | head -1) | 345 | +_LICENSE_INVALID=$(grep "^License Header Invalid Total Count:" "$REPORT_FILE" | grep -oE '[0-9]+' | head -1 || true) |
| 214 | _INVALID_TYPE=${_INVALID_TYPE:-0} | 346 | _INVALID_TYPE=${_INVALID_TYPE:-0} |
| 215 | _LICENSE_INVALID=${_LICENSE_INVALID:-0} | 347 | _LICENSE_INVALID=${_LICENSE_INVALID:-0} |
| 216 | 348 | ||
| @@ -239,11 +371,8 @@ _SECTION_LIC=$(_extract_section "$REPORT_FILE" "License Header Invalid Total Cou | |||
| 239 | echo "===================================" | 371 | echo "===================================" |
| 240 | } > "$RESULT_FILE" | 372 | } > "$RESULT_FILE" |
| 241 | 373 | ||
| 242 | -# Clean up full plain report (keep only result.txt) | ||
| 243 | -rm -f "$REPORT_FILE" | ||
| 244 | - | ||
| 245 | # --------------------------------------------------------------------------- | 374 | # --------------------------------------------------------------------------- |
| 246 | -# 8. Block commit if issues found | 375 | +# 8. Block commit if issues found; always clean up temp dir |
| 247 | # --------------------------------------------------------------------------- | 376 | # --------------------------------------------------------------------------- |
| 248 | TOTAL_ISSUES=$(( _INVALID_TYPE + _LICENSE_INVALID )) | 377 | TOTAL_ISSUES=$(( _INVALID_TYPE + _LICENSE_INVALID )) |
| 249 | 378 | ||
| @@ -257,12 +386,15 @@ if [ "$TOTAL_ISSUES" -gt 0 ]; then | |||
| 257 | echo " - Invalid File Type: $_INVALID_TYPE" | 386 | echo " - Invalid File Type: $_INVALID_TYPE" |
| 258 | echo " - License Header Invalid: $_LICENSE_INVALID" | 387 | echo " - License Header Invalid: $_LICENSE_INVALID" |
| 259 | echo "" | 388 | echo "" |
| 260 | - echo "[OAT] Details:" | 389 | + echo "[OAT] Details (also saved to: $RESULT_FILE):" |
| 261 | - echo " cat $RESULT_FILE" | 390 | + echo "---" |
| 391 | + cat "$RESULT_FILE" | ||
| 392 | + echo "---" | ||
| 262 | echo "" | 393 | echo "" |
| 263 | echo "Fix the issues and recommit, or skip with:" | 394 | echo "Fix the issues and recommit, or skip with:" |
| 264 | echo " git commit --no-verify" | 395 | echo " git commit --no-verify" |
| 265 | echo "" | 396 | echo "" |
| 397 | + rm -rf "$OAT_REPORT_DIR" | ||
| 266 | exit 1 | 398 | exit 1 |
| 267 | fi | 399 | fi |
| 268 | 400 | ||
| @@ -270,4 +402,10 @@ echo "" | |||
| 270 | echo "[OAT] [OK] All checks passed ($FILE_COUNT file(s) checked)." | 402 | echo "[OAT] [OK] All checks passed ($FILE_COUNT file(s) checked)." |
| 271 | echo "[OAT] Summary: cat $RESULT_FILE" | 403 | echo "[OAT] Summary: cat $RESULT_FILE" |
| 272 | echo "" | 404 | echo "" |
| 405 | +# Mark scan as done for CI range mode (prevents redundant re-runs on same PR head) | ||
| 406 | +if [ -n "$_DONE_MARKER" ]; then | ||
| 407 | + touch "$_DONE_MARKER" 2>/dev/null || true | ||
| 408 | + echo "[OAT] Done-marker created: $_DONE_MARKER" | ||
| 409 | +fi | ||
| 410 | +rm -rf "$OAT_REPORT_DIR" | ||
| 273 | exit 0 | 411 | exit 0 |


🔴 High |
--style={...}不是 clang-format 合法语法事实:本行写了
args: ["--style={BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 120, BreakBeforeBraces: Allman}"...]。clang-format
--style只接受:LLVM/Google/Chromium/Mozilla/WebKit)file(默认,使用最近 .clang-format){...}带花括号的写法不在支持列表中。clang-format 找不到有效样式后会:.clang-format定义的BasedOnStyle: Google, AccessModifierOffset: -4, SortIncludes: false, BreakBeforeBraces: Custom全部脱钩clang-format跑同文件会格式结果不一致修复:删掉这行
args里的--style=...,让 clang-format 默认走file模式:hooks: - id: clang-format files: \.(c|h|cpp|hpp|cc|hh|cxx|hxx)$ exclude: ^build/|tests/third_party/项目根
.clang-format会被自动拾取,pre-commit 和本地clang-format结果一致。