执行摘要
- 一句话:修复 PR CI 取消工作流的漏洞,覆盖关闭未合并和工作流不完整
- 推荐动作:对于 CI 维护者值得精读,特别是
maybe_cancel_for_pr 函数的处理逻辑和 gh run list --status 的使用。
功能与动机
PR body 指出原有工作流存在空白,导致已关闭但未合并的 PR 仍有排队运行,且 pr-test-extra 和 ci-coverage-overview 工作流未被取消,/rerun-test 的 workflow_dispatch 运行无法正确关联到 PR。
实现拆解
- 修改
cancel-unfinished-pr-tests.yml:
- 默认工作流列表从
pr-test.yml 扩展为 pr-test.yml pr-test-extra.yml,增加新输入 include_rerun_test 以选择性地包含 rerun-test.yml。
- 重构取消逻辑,提取
maybe_cancel_for_pr 函数,统一处理 PR 状态查询和取消决策。
- 对已关闭 PR(无论是否合并)直接取消运行;对开放 PR 保持原有标签跳过规则。
- 改用
gh run list --status 服务器端过滤查找旧运行,避免 --limit 长时间扫描。
- 修改
cancel-pr-workflow-on-merge.yml:
- 工作流名称从 "Cancel PR Workflows on Merge" 改为 "Cancel PR Workflows on Close",移除
if: github.event.pull_request.merged == true 条件,使 PR 关闭时(无论是否合并)都触发取消。
关键文件:
.github/workflows/cancel-unfinished-pr-tests.yml(模块 CI;类别 infra;类型 infrastructure): 主要重构文件,覆盖了新的工作流范围、添加 rerun-test 选项,并提取统一的取消判断逻辑。
.github/workflows/cancel-pr-workflow-on-merge.yml(模块 CI;类别 infra;类型 infrastructure): 重命名事件触发器,移除合并检查,使关闭 PR 即可触发取消。
关键符号:未识别
关键源码片段
.github/workflows/cancel-unfinished-pr-tests.yml
主要重构文件,覆盖了新的工作流范围、添加 rerun-test 选项,并提取统一的取消判断逻辑。
# 核心逻辑片段:maybe_cancel_for_pr 函数
# 根据 PR 状态决定是否取消运行
maybe_cancel_for_pr() {
local run_id="$1"
local pr_query="$2"
local pr_label="$3"
# 查询 PR 信息,取第一个结果
local pr_info
pr_info=$(gh api -H "Accept: application/vnd.github+json" "$pr_query" \
--jq '.[0] | {number, state, merged_at}' 2>/dev/null || true)
if [ -z "$pr_info" ] || [ "$pr_info" = "null" ]; then
echo " ⚠️ 未找到 PR($pr_label),跳过"
return
fi
local pr_number pr_state
pr_number=$(echo "$pr_info" | jq -r '.number // empty')
pr_state=$(echo "$pr_info" | jq -r '.state // empty')
if [ -z "$pr_number" ]; then
echo " ⚠️ PR 查询返回空编号,跳过"
return
fi
local pr_url="https://github.com/$REPO/pull/$pr_number"
echo " PR: $pr_url ($pr_state)"
# 关键决策:已关闭 PR(合并或未合并)直接取消
if [ "$pr_state" = "closed" ]; then
echo " 🚫 取消(PR 已关闭)..."
gh run cancel "$run_id" --repo "$REPO" || echo " ⚠️ 取消失败"
return
fi
# 开放 PR:根据标签判断是否跳过
local labels
labels=$(gh pr view "$pr_number" --repo "$REPO" --json labels \
| jq -r '.labels[].name' 2>/dev/null || true)
if echo "$labels" | grep -Fxq "bypass-maintenance"; then
echo " ⏭️ 跳过(标签 bypass-maintenance)"
else
echo " 🛑 取消(无跳过标签)..."
gh run cancel "$run_id" --repo "$REPO" || echo " ⚠️ 取消失败"
fi
}
.github/workflows/cancel-pr-workflow-on-merge.yml
重命名事件触发器,移除合并检查,使关闭 PR 即可触发取消。
# 修改说明:工作流名称和触发条件
name: Cancel PR Workflows on Close # 原名 "on Merge",现改为 on Close
on:
pull_request_target:
types: [closed]
permissions:
actions: write
jobs:
cancel:
runs-on: ubuntu-latest
steps:
- name: Cancel Previous Runs
# 不再检查 merged == true,关闭即取消
评论区精华
无 review 讨论。
风险与影响
- 风险:低风险。变更仅限于 CI 工作流脚本,不涉及业务代码。主要风险是取消逻辑错误导致误取消或漏取消,但通过不同状态下的明确分支避免。
- 影响:对用户透明;对 CI 维护者,取消行为更符合预期:已关闭的 PR 会自动取消排队运行,不再遗留在队列中。
- 风险标记:CI 流程变更, 覆盖关闭未合并
关联脉络
参与讨论