Skip to content

fix(ci): don't fail triage cleanup when there is nothing to clean - #7688

Merged
wenshao merged 1 commit into
QwenLM:mainfrom
wenshao:fix/triage-clean-pipefail
Jul 24, 2026
Merged

fix(ci): don't fail triage cleanup when there is nothing to clean#7688
wenshao merged 1 commit into
QwenLM:mainfrom
wenshao:fix/triage-clean-pipefail

Conversation

@wenshao

@wenshao wenshao commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Problem

The triage job on run 30095456731 (PR #7672) failed in Clean stale agent state with exit 1 and no output, before checkout ever ran. The failure has nothing to do with the PR being triaged.

The step sanitizes the persistent workspace's local git config through:

git config --local --name-only --list 2>/dev/null \
  | grep -ivE '<allowlist>' \
  | while IFS= read -r key; do git config --local --unset-all "$key" ...; done

When the config holds only allowlisted keys, grep matches nothing and exits 1. The step runs under the Actions default bash -e shell, and the script's own set -o pipefail propagates grep's status through the pipeline — so the step dies silently.

That empty-match state is not an edge case; it is the steady state on a reused runner: a previous run of this very step already stripped everything non-allowlisted, and actions/checkout's post step removes its auth extraheader at job end, leaving only allowlisted plumbing keys (core.*, remote.*, branch.*). In other words, the step fails exactly when there is nothing to clean. Downstream, "Check triage response" then reports the misleading "global CLI install" error, and a re-run landing on the same runner fails the same way.

Reproduction (fresh repo, config = allowlisted keys only):

$ bash -e step.sh   # before: exit 1, no output
$ bash -e step.sh   # after:  exit 0, "stale agent state cleaned"

Fix

Guard the grep with || true so an empty match feeds an empty loop instead of failing the job.

Verified that sanitization is unchanged: with core.pager, include.path, and a !-command alias planted, the fixed step still strips all three and exits 0.

Regression test

The workflow test harness (qwen-triage-workflow.test.mjs) missed this because its allowlist test re-assembles the pipeline without the step's shell flags and always plants non-allowlisted keys first. Added a steady-state test that runs the step's actual script under bash -e against a config holding only allowlisted keys, plus a negative control that strips the guard and demands the step die — red on the unfixed workflow (26/28), green with the fix (28/28).

中文说明

问题

run 30095456731(PR #7672)的 triage job 在 Clean stale agent state 步骤以 exit 1 失败,无任何输出,checkout 尚未执行。失败与被 triage 的 PR 本身无关。

该步骤通过如下管道清理持久 workspace 的本地 git config:

git config --local --name-only --list 2>/dev/null \
  | grep -ivE '<allowlist>' \
  | while IFS= read -r key; do git config --local --unset-all "$key" ...; done

当 config 中只剩 allowlist 内的键时,grep 匹配不到任何行,退出码为 1。该步骤运行在 Actions 默认的 bash -e shell 下,脚本自身的 set -o pipefail 又把 grep 的退出码传播到整条管道——于是步骤静默死亡。

这个"空匹配"并非罕见边界,而是复用 runner 上的稳态:上一次运行的同一步骤已把非 allowlist 键清理干净,actions/checkout 的 post 步骤也会在 job 结束时移除 auth extraheader,只剩下 allowlist 内的键(core.*remote.*branch.*)。也就是说,恰恰在没有东西可清理时步骤反而失败。下游 "Check triage response" 随后报出误导性的 "global CLI install" 错误;re-run 若调度到同一台处于稳态的 runner 会以同样方式再次失败。

复现(全新仓库,config 仅含 allowlist 键):

$ bash -e step.sh   # 修复前: exit 1,无输出
$ bash -e step.sh   # 修复后: exit 0,输出 "stale agent state cleaned"

修复

给 grep 加 || true 兜底,空匹配时向 while 循环输入空内容,而不是让整个 job 失败。

已验证清理行为不变:植入 core.pagerinclude.path! 命令 alias 后,修复后的步骤仍会全部清除并以 exit 0 结束。

回归测试

workflow 测试 harness(qwen-triage-workflow.test.mjs)之前没抓到这个 bug:其 allowlist 测试自行重组管道(不带步骤的 shell 标志),且总是先植入非 allowlist 键。本 PR 新增稳态回归测试:在只含 allowlist 键的 config 上以 bash -e 运行步骤的真实脚本,并附带一个去掉兜底后必须失败的负向对照——未修复的 workflow 下 26/28 红,修复后 28/28 绿。

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Qwen Triage finishedview run. See the stage comments above for the result.

Qwen Triage 已完成 —— 查看运行。结果见上方各阶段评论。

The 'Clean stale agent state' step strips non-allowlisted keys from the
persistent workspace's local git config through a
`git config --list | grep -ivE <allowlist> | while ...` pipeline. When
the config holds only allowlisted keys — the steady state on a reused
runner this step already sanitized, since actions/checkout's post step
removes its auth extraheader at job end — grep matches nothing and
exits 1. Under the default `bash -e` shell combined with the script's
`set -o pipefail`, that kills the step exactly when there is nothing
to clean, before any output, and every downstream triage step is
skipped (seen on run 30095456731, runner ecs-qwen-runner-sg-4).

Guard the grep with `|| true` so an empty match feeds an empty loop
instead of failing the job. Sanitization behavior is unchanged:
non-allowlisted keys (core.pager, include.path, `!`-aliases) are
still stripped.

The workflow test harness missed this because its allowlist test
re-assembles the pipeline without the step's shell flags and always
plants non-allowlisted keys first. Add a steady-state regression test
that runs the step's actual script under `bash -e` against a config
holding only allowlisted keys, plus a negative control that strips the
guard and demands the step die — red on the old workflow, green now.
@wenshao
wenshao force-pushed the fix/triage-clean-pipefail branch from 2f1a5ac to f4f3b68 Compare July 24, 2026 16:57
@github-actions

Copy link
Copy Markdown
Contributor

Please do not rebase or force-push to an active PR as it invalidates existing review comments. Note for future reference, the bots always squash all changes into a single commit automatically as part of the integration.

中文

请勿对活跃的 PR 执行 rebase 或 force-push,因为这会使已有的评审评论失效。另外,供日后参考:作为集成流程的一部分,机器人始终会自动将所有改动压缩(squash)为单个提交。

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template: the body uses ## Problem / ## Fix instead of the repo template headings, but the substance is all there — problem description, root cause, reproduction, and a Chinese translation. Not going to block on heading names for a CI-only fix.

Problem: observed bug with solid evidence. The linked CI run (30095456731) shows the "Clean stale agent state" step dying with exit 1 and no output. The root cause is well-explained: grep exits 1 on zero matches, pipefail propagates it, and bash -e kills the step — exactly when there's nothing to clean, which is the steady state on a reused runner. Reproduction steps are included.

Direction: straightforward CI infrastructure fix, clearly in scope.

Size: not applicable — the changed file (.github/workflows/qwen-triage.yml) is not a core module path.

Approach: the scope is exactly right. { grep ... || true; } is the idiomatic fix for suppressing grep's exit-1-on-no-match without affecting the pipeline's data flow. The comment explaining why is accurate and helpful. The force-push added a regression test — good addition, reviewed in Stage 2. Nothing to cut, nothing extraneous.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板:PR 正文使用了 ## Problem / ## Fix 而非仓库模板的标题,但实质内容齐全——问题描述、根因分析、复现步骤、中文翻译。对于纯 CI 修复,不因标题格式而阻塞。

问题:已观测到的 bug,证据充分。关联的 CI run(30095456731)显示 "Clean stale agent state" 步骤以 exit 1 静默失败。根因解释清晰:grep 零匹配时退出码为 1,pipefail 传播该退出码,bash -e 终止步骤——恰恰在没有东西可清理时(复用 runner 的稳态)失败。附有复现步骤。

方向:直接的 CI 基础设施修复,明确在范围内。

规模:不适用——变更文件(.github/workflows/qwen-triage.yml)不是核心模块路径。

方案:范围恰好。{ grep ... || true; } 是抑制 grep 零匹配退出码 1 的惯用写法,不影响管道数据流。解释原因的注释准确且有帮助。force-push 新增了回归测试——好的补充,详见 Stage 2。无需删减,无多余改动。

进入代码审查 🔍

Qwen Code · qwen3.8-max-preview

Reviewed at f4f3b681cc73bd9d9617a885ade2189002807762 · re-run with @qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Code review — independent proposal first: given grep-exits-1-on-no-match killing a pipefail + bash -e pipeline, I'd wrap the grep with || true so an empty match feeds an empty loop instead of failing the step. That's exactly what this PR does.

The diff has two parts:

1. Workflow fix (.github/workflows/qwen-triage.yml) — one logical change:

  • | grep -ivE '...'| { grep -ivE '...' || true; } — the brace group scopes || true to grep alone, so the pipeline's data flow is untouched. When grep matches, it outputs normally (exit 0, || true is a no-op). When grep matches nothing, it exits 1 with no output; || true makes that exit 0, and the while loop receives empty input and does nothing. Sanitization behavior is unchanged.
  • A 4-line comment explaining the why — accurate, and earns its place since the interaction of bash -e, pipefail, and grep's exit semantics is non-obvious.

2. Regression test (.github/scripts/qwen-triage-workflow.test.mjs) — a new steady state: nothing to clean suite:

  • Runs the actual step script (cleanStep.run) under bash -e (matching the Actions default shell) against a fresh git init repo where every key is already allowlisted.
  • Asserts exit 0 and "stale agent state cleaned" output.
  • Negative control: strips the || true guard and asserts the step fails — proves the test actually catches the bug.
  • The hermetic wrapper neutralizes the rm -f /tmp/stage-* line so the test never touches files outside its scratch dir, with an assertion that the replacement actually matched.
  • All imports (spawnSync, mkdtempSync, rmSync, join, tmpdir, before, after) are already present in the existing test file. Follows the file's conventions exactly.

No correctness issues, no security concerns, no convention violations. Nothing to flag.

CI test evidence (from the PR's own checks at f4f3b68):

Check Conclusion
precheck-pr / precheck ✅ success
authorize ✅ success
Classify PR ✅ success
label ✅ success
Test (ubuntu-latest, Node 22.x) 🔄 in_progress at review time
Test (macos-latest, Node 22.x) ⏭️ skipped
Test (windows-latest, Node 22.x) ⏭️ skipped
Integration Tests (CLI, No Sandbox) ⏭️ skipped

Unit tests don't directly exercise a workflow YAML change, but the new regression test covers the fix. No failures observed; ubuntu test still running.

Real-scenario testing: N/A — CI workflow change, nothing user-visible to drive in tmux.

中文说明

代码审查——先独立提出方案:鉴于 grep 零匹配时退出码 1 会在 pipefail + bash -e 下终止管道,我会用 || true 包裹 grep,使空匹配向循环输入空内容而非让步骤失败。这正是本 PR 的做法。

diff 包含两部分:

1. Workflow 修复.github/workflows/qwen-triage.yml)——一个逻辑变更:

  • | grep -ivE '...'| { grep -ivE '...' || true; }——花括号组将 || true 限定于 grep 本身,不影响管道数据流。grep 匹配时正常输出(退出码 0,|| true 无效);零匹配时退出码 1 无输出,|| true 使其变为 0,while 循环接收空输入、不执行任何操作。清理行为不变。
  • 4 行注释解释原因——准确,且值得保留,因为 bash -epipefail 和 grep 退出语义的交互并不直观。

2. 回归测试.github/scripts/qwen-triage-workflow.test.mjs)——新增 steady state: nothing to clean 测试套件:

  • bash -e(匹配 Actions 默认 shell)下运行实际步骤脚本(cleanStep.run),针对一个所有键均已在 allowlist 中的全新 git init 仓库。
  • 断言退出码 0 且输出 "stale agent state cleaned"。
  • 反向对照:移除 || true 守卫后断言步骤失败——证明测试确实能捕获该 bug。
  • hermetic 包装器中和了 rm -f /tmp/stage-* 行,使测试不会触碰临时目录外的文件,并附有断言确认替换确实匹配。
  • 所有导入均已存在于现有测试文件中。完全遵循文件惯例。

无正确性问题、无安全隐患、无规范违反。无需指出任何问题。

CI 测试证据(来自 PR 自身在 f4f3b68 的检查):precheck 通过,ubuntu 测试在审查时仍在运行,macOS/Windows/集成测试已跳过。单元测试不直接验证 workflow YAML 变更,但新增的回归测试覆盖了该修复。

真实场景测试:N/A——CI workflow 变更,无用户可见行为可在 tmux 中驱动。

Qwen Code · qwen3.8-max-preview

Reviewed at f4f3b681cc73bd9d9617a885ade2189002807762 · re-run with @qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Confidence: 5/5 — clean across every stage; would merge without hesitation.

This is a textbook small fix: real observed failure, clear root cause, minimal idiomatic change, accurate comment — and now a regression test that runs the actual step script under bash -e and includes a negative control proving the test catches the bug. The { grep ... || true; } pattern is exactly what I'd write independently. The sanitization logic is provably unchanged — || true only fires on the zero-match path that previously killed the step. Every line in the diff serves the stated goal; nothing to cut.

The PR body doesn't follow the template headings, but for a CI fix with reproduction, before/after verification, and a regression test, the substance is all there. Not worth a round-trip.

中文说明

置信度:5/5——各阶段均无问题,毫不犹豫地合并。

这是一个教科书式的小修复:真实观测到的故障、清晰的根因、最小化的惯用修改、准确的注释——现在还有一个回归测试,在 bash -e 下运行实际步骤脚本,并包含反向对照证明测试能捕获该 bug。{ grep ... || true; } 正是我独立会写的方案。清理逻辑可证明不变——|| true 仅在零匹配路径(此前会终止步骤的路径)生效。diff 中每一行都服务于既定目标,无需删减。

PR 正文未使用模板标题,但对于附带复现、before/after 验证和回归测试的 CI 修复,实质内容齐全,不值得为此多一轮往返。

Qwen Code · qwen3.8-max-preview

Reviewed at f4f3b681cc73bd9d9617a885ade2189002807762 · re-run with @qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, looks ready to ship. ✅

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Downgraded from Approve to Comment: CI still running. Reviewed.

中文说明

⚠️ 已从批准降级为评论:CI still running。 已审查。

— qwen3.7-max via Qwen Code /review

@doudouOUC doudouOUC left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Downgraded from Approve to Comment: CI still running. Reviewed.

— qwen3.7-max via Qwen Code /review

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve

Classic bash -e + pipefail trap — grep exits 1 when there's nothing to match, killing the whole step exactly when there's nothing to clean. The { grep ... || true; } guard is the minimal correct fix.

Tests are well-structured: positive case (steady state succeeds) + negative control (without the guard, same state fails). The negative control is especially valuable — it proves the guard is load-bearing, not dead code.

@wenshao
wenshao added this pull request to the merge queue Jul 24, 2026
Merged via the queue into QwenLM:main with commit 2da4209 Jul 24, 2026
77 checks passed
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.1.

@yiliang114

yiliang114 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

PR #7688 已合并(7月24日),CI bot 的评论只是通知该修复已随 v0.21.1 发布。无需代码变更,无需回复。确认收到。


✅ completed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants