From 0530cb04dfa3602a7cfe35bb831e0cefebfca0f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=93=E8=89=AF?= <1204183885@qq.com> Date: Wed, 19 Aug 2026 07:09:49 +0000 Subject: [PATCH] fix(triage): diff the flake-gate file list against the pinned base OID (#9464) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "Record changed test files for the flakiness gate" step runs its `git diff 'HEAD^1' HEAD` inside the env -i scrubbed child. On the persistent pool, resolving the `^1` parent there intermittently fails with "Could not access 'HEAD^1'" — the shallow merge-ref object store is left unreadable by prior `--depth=2` fetches — which takes down the whole verify lane. The "Pin agent inputs" step already captures the base OID to $RUNNER_TEMP/verify-base-oid while .git is still root-owned. Diff against that content-addressed OID instead of re-resolving the parent: it needs no parent walk and is the same value the workflow already trusts for its post-build re-pin. Add a pin asserting the record step reads the recorded OID rather than re-deriving HEAD^1. --- .github/scripts/qwen-triage-workflow.test.mjs | 7 ++++++- .github/workflows/qwen-triage.yml | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/scripts/qwen-triage-workflow.test.mjs b/.github/scripts/qwen-triage-workflow.test.mjs index f21b2c562b..22cb58192d 100644 --- a/.github/scripts/qwen-triage-workflow.test.mjs +++ b/.github/scripts/qwen-triage-workflow.test.mjs @@ -1014,9 +1014,14 @@ describe('qwen-triage: flakiness gate (#9125)', () => { // executes, so it is a changed test file exactly like M. assert.match( recordStep.run, - /^\s*git -c core\.quotePath=false diff -z --name-only --diff-filter=ACMRT 'HEAD\^1' HEAD \\\n\s*> "\$GATE_HOME\/files-all"$/m, + /^\s*git -c core\.quotePath=false diff -z --name-only --diff-filter=ACMRT "\$BASE_OID" HEAD \\\n\s*> "\$GATE_HOME\/files-all"$/m, 'the NUL diff must flow straight into its file — $( ) strips NUL bytes, a pipeline swallows the exit status', ); + assert.match( + recordStep.run, + /^\s*BASE_OID="\$\(cat "\$\{RUNNER_TEMP:\?\}\/verify-base-oid"\)"$/m, + 'the record step must diff against the base OID captured while .git was root-owned, not re-resolve HEAD^1', + ); assert.ok( recordStep.run.includes( "grep -zE '\\.(test|spec)\\.(ts|tsx|js|jsx|mjs|cjs|mts|cts)$'", diff --git a/.github/workflows/qwen-triage.yml b/.github/workflows/qwen-triage.yml index 1236cfbda8..0e9f9493f5 100644 --- a/.github/workflows/qwen-triage.yml +++ b/.github/workflows/qwen-triage.yml @@ -2975,7 +2975,20 @@ jobs: # T (typechange) included: a symlink->regular flip changes what # the runner executes, so it is a changed test file exactly # like M — excluding it silently drops the file from the gate. - git -c core.quotePath=false diff -z --name-only --diff-filter=ACMRT 'HEAD^1' HEAD \ + # Diff against the base OID the "Pin agent inputs" step recorded + # while .git was still root-owned, never `HEAD^1` again: this + # step runs in the env -i scrubbed child, and resolving the `^1` + # parent there intermittently fails with "Could not access + # 'HEAD^1'" on the persistent pool — the shallow merge-ref object + # store is left in a state prior --depth=2 fetches made + # unreadable. The OID is content-addressed and needs no parent + # walk, so the diff works from the already-captured value. + BASE_OID="$(cat "${RUNNER_TEMP:?}/verify-base-oid")" + case "$BASE_OID" in + [0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]*) ;; + *) echo "::error::No trusted base OID recorded; refusing to record the flakiness-gate file list."; exit 1 ;; + esac + git -c core.quotePath=false diff -z --name-only --diff-filter=ACMRT "$BASE_OID" HEAD \ > "$GATE_HOME/files-all" # .mts/.cts included: vitest's default include set collects them. # Only a no-match (status 1) may yield an empty list: a grep