From 3c83a59c2011972dd0e8672bb92e69574fc70599 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 05:23:24 +0000 Subject: [PATCH 1/2] =?UTF-8?q?ci(docs):=20=E6=8A=8A=20check-doc-links=20?= =?UTF-8?q?=E6=8E=A5=E8=BF=9B=20CI,=E5=B9=B6=E4=BF=AE=E5=A5=BD=E5=AE=83?= =?UTF-8?q?=E4=B8=80=E7=9B=B4=E5=9C=A8=E6=8A=A5=E7=9A=84=E9=82=A3=E6=9D=A1?= =?UTF-8?q?=E5=9D=8F=E9=93=BE=20(#3213,=20#3292)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit scripts/check-doc-links.mjs 早就存在且能用,但 .github/ 下零调用 —— 它在未 改动的 origin/main 上就 exit 1,报 content/docs/core/enhanced-actions.mdx -> /docs/components/form 断链,却从来没有工作流跑过它。 两处改动: 1. 坏链改指 /docs/components/form/form(retarget,不补 index 页)。 content/docs/components/ 下 9 个分类目录全部没有 index 页,补一个会是 components 树里唯一的例外;components/index.md 自己也是用代表页链到分类 (如 /docs/components/form/button),从不链裸分类路由;form/meta.json 显式 列出 pages 且不含 index。而该句 "- [Form](...) - Form submission actions" 指向的正是 form/form.mdx(title: Form,description: Form container with validation and submission handling),不是 button。 2. ci.yml 的 docs job 加一步 Check docs links,放在 Setup Node.js 之后、 install 与站点构建之前 —— 脚本零依赖零网络,坏链几秒内失败,不必等一次 完整的 Next.js 构建。 已知缺口(不在本次裁决范围,已记为 #3448):ci.yml 的 paths-ignore 含 content/**,GitHub 又没有 per-job path filter,所以纯 docs PR 根本不会启动这个 workflow。control-bytes.yml 撞过同一堵墙并靠独立 workflow 解决,文件头写明了 理由。本步骤覆盖 docs+代码混合 PR 与 push to main。 check-links.yml(Lychee)按裁决维持 workflow_dispatch;有意未加 cron —— 它扫的 是 docs/**(15 个内部文件)而非 content/docs/**(183 个站点文档),范围修正前 加 cron 只会按时产出一份不覆盖站点文档的绿报告(已记为 #3449)。 验证:改前 node scripts/check-doc-links.mjs -> exit 1(1 broken link); 改后 -> exit 0 "Docs links are valid." --- .github/workflows/ci.yml | 25 +++++++++++++++++++++++++ content/docs/core/enhanced-actions.mdx | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 67a622d744..6e7c69fba9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -320,6 +320,31 @@ jobs: node-version: '22.x' cache: 'pnpm' + # `scripts/check-doc-links.mjs` existed and worked, but nothing under + # `.github/` ever called it, so it had never run in CI — it exited 1 on an + # untouched `main` for a broken link that had been sitting there (#3213, + # #3292). It resolves every `/docs/...` markdown link against + # `content/docs/` on the filesystem: no install and no network, so it runs + # here — after Node is set up, before the expensive install + site build — + # and a bad link fails in seconds instead of after a full Next.js build. + # + # KNOWN GAP — read before assuming docs links are fully gated: `ci.yml` + # lists `content/**` and `'**/*.md'` under `paths-ignore`, and GitHub has + # no per-job path filter, so a docs-ONLY pull request never starts this + # workflow and is never link-checked. This step therefore covers pull + # requests that touch docs alongside code, plus pushes to `main` — not the + # pure-docs pull request, which is the likeliest way to break a link. + # + # `control-bytes.yml` hit this same wall and answered it by being its own + # workflow with no path filters, for a gate that likewise needs no install + # and no network; its header explains the reasoning, and + # `scripts/__tests__/check-control-bytes.test.ts` pins it. Moving this + # check to that shape is the known fix, but it changes CI triggering + # policy, so it is left to the maintainer — tracked in #3448. + - name: Check docs links + if: steps.docs-changes.outputs.should_run == 'true' + run: node scripts/check-doc-links.mjs + - name: Turbo Cache if: steps.docs-changes.outputs.should_run == 'true' uses: actions/cache@v6 diff --git a/content/docs/core/enhanced-actions.mdx b/content/docs/core/enhanced-actions.mdx index a498543b37..f202ff945a 100644 --- a/content/docs/core/enhanced-actions.mdx +++ b/content/docs/core/enhanced-actions.mdx @@ -483,5 +483,5 @@ Enhanced Actions are ideal for: ## Related - [Building a CRUD App](/docs/guide/building-crud-app) - CRUD operations with actions -- [Form](/docs/components/form) - Form submission actions +- [Form](/docs/components/form/form) - Form submission actions - [Data Source](/docs/guide/data-source) - API integration From c88ab6b68efa1cef267d61fdb5629ca82d281b25 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 05:28:58 +0000 Subject: [PATCH 2/2] =?UTF-8?q?docs(ci):=20=E6=8A=8A=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=9A=84=E9=93=BE=E6=8E=A5=E9=97=A8=E7=A6=81=E5=86=99=E8=BF=9B?= =?UTF-8?q?=20ci-cd-pipeline.md,=E5=B9=B6=E8=AF=B4=E6=98=8E=E4=B8=A4?= =?UTF-8?q?=E4=B8=AA=E6=A3=80=E6=9F=A5=E5=99=A8=E7=9A=84=E5=88=86=E5=B7=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commandment #2(docs-driven):ci.yml 的 docs job 多了一步 Check docs links, 该页的 job 表格原文只写了 turbo build,已同步。 另在 Link Checking 一节补一张对照表,写清两个检查器各管什么: check-doc-links.mjs 管站内 /docs/... 路由、不走网络、在 ci.yml 里跑; Lychee 管外链、走网络、只能手动触发。并写明两个已知缺口(#3448 纯 docs PR 不触发 ci.yml;#3449 Lychee 扫的是 docs/ 而非 content/docs/),以免读者从这一页 得出「文档链接已被完全守住」的结论。 未改该页既有的其它内容(如 job 数量与 dev-server 行的既存漂移),另行记录。 验证:pnpm exec vitest run scripts/__tests__/ -> 8 files / 120 tests passed (含 ci-cd-pipeline-doc.test.ts 的 9 条,它正是钉这一页的)。 --- content/docs/guide/ci-cd-pipeline.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/content/docs/guide/ci-cd-pipeline.md b/content/docs/guide/ci-cd-pipeline.md index 3fc994f178..5fc89a6578 100644 --- a/content/docs/guide/ci-cd-pipeline.md +++ b/content/docs/guide/ci-cd-pipeline.md @@ -61,7 +61,7 @@ Seven jobs, all parallel — there are no `needs:` edges between them: | `test` | Test (shard N/4) | `pnpm test --shard=N/4` across a 4-runner matrix with `fail-fast: false`, so every shard reports its own failures. No coverage instrumentation — v8 adds 40–100% overhead. | **Pull requests only** | | `test-coverage` | Test (coverage) | One unsharded `pnpm test:coverage`, uploaded to Codecov. Nothing blocks on it, which is why it is not sharded. | **Push only** | | `e2e` | Build & E2E | Builds the console with `vite build` (`VITE_BASE_PATH=/console/`), verifies the artifact, then `pnpm test:e2e --project=chromium`. Uploads the Playwright report on failure. | Every run | -| `docs` | Build Docs | `turbo run build --filter='@object-ui/site'`. On a PR it first diffs against the base and skips the build when nothing under `apps/site/` or `content/` changed. | Every run (build itself conditional) | +| `docs` | Build Docs | `scripts/check-doc-links.mjs` (resolves every `/docs/...` markdown link against `content/docs/` — no install, no network), then `turbo run build --filter='@object-ui/site'`. On a PR it first diffs against the base and skips both when nothing under `apps/site/` or `content/` changed. | Every run (steps themselves conditional) | | `dev-server` | Dev-server fixture build | `pnpm --filter @object-ui/dev-server build` — guards `apps/dev-server`'s `objectstack.config.ts` against fixture / `@objectstack/spec` drift. | Every run | Uses: Node 22.x, pnpm via `corepack`, `actions/cache` over `.turbo/cache`. @@ -217,6 +217,22 @@ Backend pins live in `e2e/live/ci/backend.env` and must match the `@objectstack/ **Trigger:** Manual workflow dispatch (`workflow_dispatch`). +There are **two** link checkers, and they cover different things (objectui#3213): + +| | Covers | Network | Runs | +|---|---|---|---| +| `scripts/check-doc-links.mjs` | **Internal** `/docs/...` routes, resolved against `content/docs/` | No | In `ci.yml`'s `docs` job — see the job table above | +| Lychee (this workflow) | **External** URLs in `docs/` and `README.md` | Yes | Manual dispatch only | + +Note the asymmetry in what Lychee scans: `docs/` holds internal material (ADRs, audits, +architecture notes), while the published site is built from `content/docs/`. Lychee therefore does +not currently see the site's own pages. + +Two known gaps are tracked rather than silently lived with: `ci.yml` lists `content/**` under +`paths-ignore` and GitHub has no per-job path filter, so a **docs-only** PR does not start `ci.yml` +and is not link-checked (objectui#3448); and Lychee's scan scope predates the move to +`content/docs/` (objectui#3449). + Uses [Lychee](https://github.com/lycheeverse/lychee) with configuration from `lychee.toml`: - Scans markdown files in `docs/` and `README.md` - Max concurrency: 10, timeout: 20s, retries: 3