ci(docs): check-doc-links 提升为无路径过滤的独立 workflow,纯 docs PR 也拦得住断链 (#3448) - #3458
Merged
Conversation
`check-doc-links.mjs` 由 PR #3450 接进 CI 时,落点是 `ci.yml` 的 `docs` job —— 而 `ci.yml` 的 `paths-ignore` 列着 `'**/*.md'`、`content/**`、`docs/**`、 `apps/site/**`。GitHub 的 `paths-ignore` 语义是「改动文件全部命中即整个 workflow 不启动」,且没有 per-job path filter;站点文档全在 `content/docs/**`。所以**只改 文档的 PR 根本不会启动 ci.yml**,这道门禁看不见的恰恰是最可能改坏内链的那一类 PR。它此前只覆盖「文档+代码」的混合 PR 和 push 到 main —— 坏链能经纯 docs PR 合 进 main,直到下一个无关作者推代码时才把 main 弄红,归因还错人。 `control-bytes.yml` 撞过同一堵墙,头注写着结论:看不见 markdown-only PR 的门禁 "rebuilds the hole it exists to close";`changeset-guard.yml` 是同一形状的第二例。 本次是第三例。 改动: • 新增 `.github/workflows/docs-links.yml`,镜像 control-bytes.yml 的形状: push/PR to main+develop + workflow_dispatch,**无 paths / 无 paths-ignore**, checkout + setup-node + 一行 `node scripts/check-doc-links.mjs`,无 install 无网络。头注写清为什么不能加路径过滤。 • **从 ci.yml 的 docs job 删掉重复步骤**(最小重复原则):新 workflow 的触发集 是该 job 的严格超集,留着只会为同一条坏链多出一个红勾和一处会忘记同步的副本。 原地留注释说明它去哪了、为什么别加回来。 • 新增 `scripts/__tests__/docs-links-workflow.test.ts` 钉住形状:workflow 必须 存在、必须门禁 PR、必须既无 `paths` 也无 `paths-ignore`、必须是**唯一**跑该 脚本的 workflow;并以不变式表述「跑这个脚本的 workflow 必须是纯 docs PR 能 启动的」,即使将来改名搬家也成立。扫描前先剥掉整行注释 —— ci.yml 的说明注释 里仍然提到脚本名,不剥会误判成重复门禁。 • `content/docs/guide/ci-cd-pipeline.md`:这一条不是顺手改文档,是 `scripts/__tests__/ci-cd-pipeline-doc.test.ts` 的机械要求 —— 只加 workflow 不加章节,该测试立刻红,报「docs-links.yml 无对应标题」。补:清单表一行、新章节 (含为什么无路径过滤)、ci.yml 任务表里 docs 行的更正(它不再跑链接检查)、 以及 Link Checking 章节里 #3448 那个「已知缺口」的收口。 反向验证(方向先判后跑):把删掉的步骤加回 ci.yml —— 新测试如期两处红: "is the only workflow that runs the link checker"(ci.yml + docs-links.yml)与 "every workflow that runs it is one a docs-only PR can start"(ci.yml 有 paths-ignore)。给 docs-links.yml 加 `paths: content/**` —— "carries NO path filter" 如期红。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
yinlianghui
marked this pull request as ready for review
August 6, 2026 06:45
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Aug 6, 2026
#3456 (docs(ci): 删掉 ci.yml 任务表里的幽灵 dev-server 行) 与本分支 (#3448) 都改了 content/docs/guide/ci-cd-pipeline.md,冲突落在 ci.yml 任务表的最后两行。 按并集解: • 取 main 的 #3456 全部改动 —— 删掉 `dev-server` 行、「Seven jobs」改为不写死 数字、清单表 ci.yml 行改为「every job but test-coverage (push only)」、 「What is *not* in ci.yml」补记 dev-server 的完整来龙去脉。 • 叠加本分支 #3448 的四处改动 —— 清单表新增 `docs-links.yml` 行、新增 「Internal Docs Links (docs-links.yml)」章节、任务表 `docs` 行改写为不再跑 链接检查、Link Checking 章节里 #3448 那个「已知缺口」收口(#3449 的保留)。 冲突区实际只有 `docs`/`dev-server` 两行:`docs` 行取本分支的新措辞,`dev-server` 行按 main 删除。ci.yml 与两份测试文件无冲突,自动合并。 验证: • pnpm exec vitest run scripts/ → 10 files / 144 tests 全绿。其中 #3456 新加的 4 条任务表双向 pin 与本分支 docs-links-workflow 的 7 条断言同时对并集文档 通过(任务表首列 = ci.yml 的 6 个 job key,`docs` 的「Appears as」= Build Docs)。 • node scripts/check-doc-links.mjs → "Docs links are valid.",exit 0。 • 两个 workflow YAML 经 yaml.safe_load 解析通过。 • node scripts/check-control-bytes.mjs → OK(3663 个文件);并对本次涉及的 5 个文件单独做了 grep -naP 控制字节自查,无命中。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3448
按 PM 裁定采方案 A:把
node scripts/check-doc-links.mjs提升为独立 workflow,无任何路径过滤,镜像control-bytes.yml的形状(触发集、最小 checkout、头注解释为什么不能加过滤)。裁定与「形式上偏离维护者 08-03 对 #3213 的『加进 ci.yml 的 docs 任务』原话」的理由已在单上论证:#3448 (comment) —— 那个裁决作出时结构洞尚未被发现,其意图(内链断裂 = 硬门禁)在字面落法下对纯 docs PR 恰好失效。问题(已在 origin/main 上复核)
ci.yml的paths-ignore两处都列着'**/*.md'、content/**、docs/**、apps/site/**;站点文档全在content/docs/**。GitHub 的语义是「改动文件全部命中即整个 workflow 不启动」,且没有 per-job path filter —— 所以只改文档的 PR 根本不启动 ci.yml,#3450 加的那一步自然也不跑。它此前只覆盖「文档+代码」混合 PR 与 push 到 main。改动
.github/workflows/docs-links.yml:push/pull_requesttomain+develop加workflow_dispatch,既无paths也无paths-ignore;checkout + setup-node + 一行node scripts/check-doc-links.mjs。无 install、无网络、几秒钟。头注写清为什么路径过滤在这里是错的(paths: content/**看着更紧,实则只是脚本扫描面的第二份副本,会各自漂移)。ci.yml的docsjob 删掉重复步骤 —— 这一处按最小重复原则由实现者定,我选删:新 workflow 的触发集是该 job 的严格超集(同样的 main/develop,且无过滤),保留只会为同一条坏链多出一个红勾、多一处会忘记同步的副本。原地留注释说明它去哪了、为什么别加回来;那段已失效的KNOWN GAP注释一并删除(留着就是假话)。scripts/__tests__/docs-links-workflow.test.ts:workflow 必须存在、必须门禁 PR、必须既无paths也无paths-ignore、必须是唯一跑该脚本的 workflow。最后一条钉的是去重决策本身——把副本加回某个带路径过滤的 workflow,正是会重新制造「看着有覆盖、实则纯 docs PR 照样溜过去」的那个具体错误。扫描前先剥掉整行注释:ci.yml的说明注释里仍提到脚本名,不剥会误报重复门禁。content/docs/guide/ci-cd-pipeline.md派单文件面把
content/docs/**列为禁止面。这一条我越了界,因为它不是顺手改文档,而是既有门禁的机械要求:scripts/__tests__/ci-cd-pipeline-doc.test.ts读.github/workflows/目录,任一 workflow 在该页没有点名标题就红。先加 workflow、不改文档,实测:该页自己的「Adding a New Workflow」也写着「Give it a section on this page in the same PR. Not a convention — a test.」。改动限于四处必要更正:清单表一行、新章节、ci.yml 任务表里
docs行的更正(它不再跑链接检查)、Link Checking 章节里 #3448 那个「已知缺口」的收口(#3449 那个仍在)。如维护者认为该越界不可接受,我可以拆出去,但那样本 PR 必然是红的。与在飞 PR #3456 的交叉:#3456(#3451)同样在改这个文件与
ci-cd-pipeline-doc.test.ts。两边不冲突的部分:它改ci.yml行与dev-server幽灵行,我加docs-links.yml行与新章节;可能冲突的一处是任务表里docs行——我改了它的内容,而它紧邻 #3456 删掉的dev-server行。两处修改都是有意的,谁后合谁 rebase 时按此说明取并集即可。#3456 不动ci.yml,故 workflow 侧零交叉。验证
python yaml.safe_load两个 workflow 均解析通过;docs-links.yml的触发集实测为{'pull_request': {'branches': ['main','develop']}, 'push': {'branches': ['main','develop']}, 'workflow_dispatch': None}—— 没有任何 paths 键。node scripts/check-doc-links.mjs→Docs links are valid.(exit 0)pnpm exec vitest run scripts/(仓库根,规范调用)→ 9 files / 127 tests passednode scripts/check-control-bytes.mjs→ OK(3648 文件);另对本 PR 四个文件做了越出门禁的自扫grep -naP,无命中。ci.yml→ 新测试两处红(is the only workflow that runs the link checker实得['ci.yml','docs-links.yml'];every workflow that runs it is one a docs-only PR can start点名 ci.yml 的 paths-ignore)。给docs-links.yml加paths: content/**→carries NO path filter of any kind红。诚实的覆盖面说明:本 PR 改的是
.github/**,所以它自己既会启动 ci.yml、也会启动新 workflow —— 绿灯只证明「workflow 能在 PR 上跑通」,证明不了「纯 docs PR 会启动它」,后者只能由将来某个只改 markdown 的 PR 实证。能在此刻担保它的,是配置本身:on.pull_request只有branches,没有paths/paths-ignore两个键中的任何一个(YAML 解析结果如上),而 GitHub 只在存在过滤键时才做路径判断。这一条同时由上面那条测试机械看守。未做的事
scripts/的 type-check 覆盖(单上相邻观察)→ 建议拆单,不顺路。理由不是错误多(实测tsc --noEmit --strict跑scripts/**/*.ts只有 3 个报错,且全是.mjs/.js无声明文件的 TS7016 与一处随之失效的 TS2578),而是落点全在本 PR 之外:(1) 它需要 install(typescript + @types/node + vitest 类型),而新 workflow 的全部设计前提是「无 install、无网络、几秒」,还被我的测试钉住了——把 tsc 塞进去等于让纯 docs PR 去等一次完整安装,与paths-ignore想省的正是同一笔开销;正确的家是ci.yml的type-checkjob(那里已有 install 与 turbo 缓存)。(2) 需要为scripts/决定一个 tsconfig(并入根 include?独立 tsconfig?)并与check-type-check-coverage.mjs(按 包 判定覆盖,而scripts/不是包)对齐。(3) 选定的allowJs/checkJs会机械地改变现有测试里@ts-expect-error的成立与否,从而必须改动既有测试文件——其中ci-cd-pipeline-doc.test.ts正被 docs(ci): 删掉 ci.yml 任务表里的幽灵 dev-server 行,并给任务表加双向 pin (#3451) #3456 占用。三处都在本单文件面之外,硬塞进来就是替维护者做架构决定。查重未能完成:GitHub 搜索/列表 API 对本账号已限流(API rate limit already exceeded),与 ci-cd-pipeline.md 的 ci.yml job 表格漂移:写「Seven jobs」并列了一个不存在的 dev-server job(实际 6 个) #3451 的 dev 撞的是同一堵墙,故按 #4949 纪律不盲目立单,留给 PM 立(该观察已记在 check-doc-links 挂在 ci.yml 的 docs job 上,对「纯 docs PR」永远不会触发(paths-ignore 含 content/**) #3448 评论里,不会丢)。Generated by Claude Code