Optimism 仓库 TODO Checker CI 失败修复指南:scheduled-todo-issues 工作流、todo-checker.sh 与 Issue 重开流程 📅 发布时间:2026/9/17 18:47:25 👁 浏览次数: Optimism 仓库 TODO Checker CI 失败修复指南scheduled-todo-issues 工作流、todo-checker.sh 与 Issue 重开流程【免费下载链接】optimismOptimism is Ethereum, scaled.项目地址: https://gitcode.com/GitHub_Trending/op/optimism本文以 fix-todo 技能文档 为主体讲解 Optimism 仓库github 上为 ethereum-optimism/optimism中定时 TODO 检查 CI 失败的完整修复流程如何定位失败的 CircleCI 流水线、从 job 输出中解析引用了已关闭 issue 的 TODO明细、追查 issue 的实际关闭者以及带着规范署名把 issue 重新打开。读完本文你将能够独立完成一次 TODO checker 失败的端到端处置并理解底层 ops/scripts/todo-checker.sh 的检查逻辑与 .circleci/continue/main.yml 中的调度配置。一、背景TODO checker 是什么为什么会失败仓库通过定时 CircleCI 工作流scheduled-todo-issues每 4 小时一次校验代码库中的 TODO 注释。其规则是TODO 注释可以引用 GitHub issue但被引用的 issue 不允许处于已关闭状态——一旦 issue 被关闭而 TODO 仍在引用它说明剩余工作没有被正确跟踪检查任务即判定失败需要重新打开 issue 来继续跟踪剩余工作。TODO 注释支持三种引用格式冒号与描述部分均可选TODO(#1234)—— 引用默认仓库 ethereum-optimism/optimismTODO(repo#1234)—— 引用 ethereum-optimism/repoTODO(org/repo#1234)—— 完整引用。这些格式与检查脚本 ops/scripts/todo-checker.sh 中的实际解析逻辑一一对应脚本先用正则^[0-9]$/^#([0-9])$匹配纯数字或带 # 的数字并回填默认ORGethereum-optimism、REPOoptimism见 todo-checker.sh 第 18-19 行再依次匹配org/repo#number与repo#number两种带命名空间的格式三者都不匹配则计为格式不合法MISMATCH。前置条件已通过 GitHub 认证ghCLICircleCI API 对该仓库公开可读无需 token文档明确说明此点。二、底层机制todo-checker.sh 如何判定失败在动手修复之前理解检查脚本的判定边界能帮助你正确解读 CI 输出。从 ops/scripts/todo-checker.sh 源码看其执行链路如下参数解析第 44-60 行支持--strict格式不合法即失败并隐含 verbose、--verbose打印每个 TODO 的明细、--check-closed检查 issue 是否已关闭并据此报错。强制依赖 ripgrep第 62-67 行缺少rg时扫描会静默返回空结果、脚本会什么都没查却通过因此脚本选择 fail fast 直接退出。全库扫描第 70 行用 ripgrep 匹配TODO\(([^)])\):?( [^,;]*)?并显式排除ops/scripts/todo-checker.sh自身与packages/contracts-bedrock/lib第三方依赖目录。逐条调用 GitHub API 查状态第 109-139 行对每个解析成功的引用请求https://api.github.com/repos/org/repo/issues/num404 计为 NOT_FOUND仅 verbose 告警非 200 则直接报错退出状态为closed时打印形如Issue #18616 is closed. Please remove the TODO in file:line...的红色错误并累入CLOSED_ISSUES表格。私有仓库可通过环境变量CI_TODO_CHECKER_PAT提供 API token第 11-15 行。near-miss 扫描第 148-159 行用第二条 ripgrep 规则捕捉明显想引用 issue 但格式畸形的写法例如TODO:(#123)、TODO (#123)、TODO[#123]、TODO: #123同时排除已用标准TODO(ref)形式的行完全没有 issue 引用的裸 TODO 不告警。汇总与退出码第 185-219 行--strict下格式不合法或 near-miss 都会exit 1只要存在已关闭 issue脚本打印[Error] N TODOs refer to issues that are closed.和Closed issue details:表格三列Repository Issue、Title、Location后exit 1。这个表格正是修复流程第 3、4 步要解析的对象。CircleCI 侧的调度配置在 .circleci/continue/main.yml 中todo-issuesjob 定义于 第 1578-1594 行它带有check_closed布尔参数默认true以 blobless checkout mise 缓存检出代码后执行./ops/scripts/todo-checker.sh --verbose --strict #parameters.check_closed --check-closed即技能文档所述的实际命令ops/scripts/todo-checker.sh --verbose --strict --check-closed失败时还会触发notify-failures-on-develop。定时触发则由 第 2762-2769 行 的scheduled-todo-issues工作流负责当流水线参数c-run_scheduled_todo_issues为真时运行名为todo-issue-checks的 job并注入slack与circleci-repo-readonly-authenticated-github-token两个 context。三、七步修复流程技能文档核心以下命令与步骤完整继承自 SKILL.md适用于定时 TODO checker CI job 失败这一触发场景典型触发话术Fix the latest TODO checker failure、Reopen issues from TODO checker 等。第 1 步找到最近的定时 TODO checker 流水线LATEST_PIPELINE$(curl -s https://circleci.com/api/v2/project/gh/ethereum-optimism/optimism/pipeline?branchdevelop | \ jq -r .items[] | select(.trigger.type scheduled_pipeline) | {id, number, created_at} | json | head -1) PIPELINE_ID$(echo $LATEST_PIPELINE | jq -r .id) PIPELINE_NUMBER$(echo $LATEST_PIPELINE | jq -r .number)第 2 步获取工作流与 job 详情注意一个关键坑最新的定时流水线可能只包含 setup 工作流不一定含有 TODO 检查。需要沿最近的若干条定时流水线逐个探测找到包含scheduled-todo-issues工作流的那一条# Find a pipeline with the TODO workflow PIPELINE_WITH_TODO$(curl -s https://circleci.com/api/v2/project/gh/ethereum-optimism/optimism/pipeline?branchdevelop | \ jq -r .items[] | select(.trigger.type scheduled_pipeline) | .id | while read pid; do workflows$(curl -s https://circleci.com/api/v2/pipeline/$pid/workflow | jq -r .items[] | .name) if echo $workflows | grep -q scheduled-todo-issues; then echo $pid break fi done) PIPELINE_ID$PIPELINE_WITH_TODO PIPELINE_NUMBER$(curl -s https://circleci.com/api/v2/project/gh/ethereum-optimism/optimism/pipeline?branchdevelop | \ jq -r .items[] | select(.id \$PIPELINE_ID\) | .number) WORKFLOW_DATA$(curl -s https://circleci.com/api/v2/pipeline/$PIPELINE_ID/workflow | \ jq .items[] | select(.name scheduled-todo-issues)) WORKFLOW_ID$(echo $WORKFLOW_DATA | jq -r .id) WORKFLOW_STATUS$(echo $WORKFLOW_DATA | jq -r .status) JOB_NUMBER$(curl -s https://circleci.com/api/v1.1/workflow/$WORKFLOW_ID/job | \ jq -r .items[] | .job_number)随后检查工作流状态若为success或running应告知用户当前没有需要修复的失败或等待运行完成只有failed才继续。第 3 步拉取 job 输出定位已关闭 issue表格OUTPUT_URL$(curl -s https://circleci.com/api/v1.1/project/gh/ethereum-optimism/optimism/$JOB_NUMBER | \ jq -r .steps[] | select(.name | contains(TODO)) | .actions[0].output_url) curl -s $OUTPUT_URL | jq -r .[].message输出末尾会出现[Error] Closed issue details:段落对应脚本中printIssue渲染的三列表格todo-checker.sh 第 161-183 行每行给出Repository Issue例如ethereum-optimism/optimism #18616Issue TitleLocation例如op-acceptance-tests/tests/isthmus/preinterop/interop_readiness_test.go:106。第 4 步解析出待处理信息从 Closed issue details 表格中逐条提取issue 编号如#18616、文件路径与行号如op-acceptance-tests/tests/isthmus/preinterop/interop_readiness_test.go:106、issue 标题。第 5 步查明最近一次是谁关闭了 issueissue 可能经由 PR 关闭也可能被用户直接关闭。正确做法是查 GitHub GraphQL timeline取最近一个ClosedEvent的操作者而不是简单取第一个关闭事件——这样才能正确处理被 PR 关闭 → 又被重开 → 后被某用户直接关闭、或被多个人多次关闭等历史ISSUE_NUMissue_number # Use GraphQL to get the timeline and find the most recent close event CLOSER$(gh api graphql -f query query { repository(owner: \ethereum-optimism\, name: \optimism\) { issue(number: $ISSUE_NUM) { timelineItems(last: 20, itemTypes: [CLOSED_EVENT, REOPENED_EVENT]) { nodes { ... on ClosedEvent { __typename createdAt actor { login } closer { __typename } } ... on ReopenedEvent { __typename createdAt actor { login } } } } } } } --jq .data.repository.issue.timelineItems.nodes | reverse | .[] | select(.__typename ClosedEvent) | .actor.login | head -1) echo Issue closed by: $CLOSER技能文档明确要求始终 最近一次关闭事件对应的人。第 6 步读取代码中真实的 TODO 行按第 4 步得到的file:line位置打开文件读取确切的 TODO 注释原文——重开评论中必须引用真实代码行而不是凭记忆转述。第 7 步以规范署名重新打开 issue按技能文档给出的模板发起重开注意评论需包含 关闭者、简要的已完成什么 / 剩余什么背景、带文件行号的被跳过测试说明、真实 TODO 行代码块、CircleCI job 链接gh issue reopen $ISSUE_NUM --comment ${CLOSER} Reopening because this issue was closed but theres still a TODO/skip referencing it in the codebase. [Brief context about what was completed vs what remains] The [TestName] at \file:line\ is still skipped with: \\\language actual TODO line from code \\\ Discovered by the TODO check in CI: https://app.circleci.com/pipelines/github/ethereum-optimism/optimism/${PIPELINE_NUMBER}/workflows/${WORKFLOW_ID}/jobs/${JOB_NUMBER}四、重开评论的硬性要求与报告格式技能文档把以下条目列为强制要求Requirements必须 关闭该 issue 的人GitHub handle来自 timeline 最近一次关闭事件必须给出 TODO 所在的精确文件位置必须附上 CircleCI job URL以便追溯必须读取并附上代码中的真实 TODO 行若能从 issue 本身判断提供已完成 vs 剩余的背景说明。重开成功后按以下格式向用户报告✓ TODO checker failure resolved Issue: #number - title Status: Reopened Tagged: username Location: file:line View issue: https://github.com/ethereum-optimism/optimism/issues/number CircleCI job: https://app.circleci.com/pipelines/github/ethereum-optimism/optimism/pipeline/workflows/workflow/jobs/job五、边界场景与错误处理技能文档对两类常见边界给出明确处置策略一次失败包含多个已关闭 issue逐条串行处理且每重开一个 issue 前都要向用户请求确认issue 已经被重开过先检查是否已存在关于该 TODO 的评论若没有则补一条带位置的评论而不是重复重开。六、小结检查器、调度与修复动作的对应关系把三个仓库位置串起来整条链路是.circleci/continue/main.yml 的scheduled-todo-issues工作流每 4 小时触发一次todo-issuesjob → job 执行 ops/scripts/todo-checker.sh 的--verbose --strict --check-closed组合扫描全库 TODO 引用并调用 GitHub API 核对 issue 状态发现引用已关闭 issue即打印Closed issue details:表格并以非零码退出 → fix-todo 技能 定义了从 CircleCI API 定位失败 job、解析表格、经 GraphQL timeline 找到最近关闭者、读取真实 TODO 行直到署名重开 issue 的完整操作规范。理解脚本的扫描正则、排除目录与退出条件第二节后CI 输出中的每一条[Error]与[Warning]都能直接映射到对应的代码行和 issue修复工作因此可以完全可追溯地闭环。【免费下载链接】optimismOptimism is Ethereum, scaled.项目地址: https://gitcode.com/GitHub_Trending/op/optimism创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考