Repository navigation
ci: replace hyperlink with lychee for docs link checking - #21246
uncoolclub wants to merge 2 commits into
Conversation
❌ Deploy Preview for docs-eslint failed. Why did it fail? →
|
|
Hi everyone, it looks like we lost track of this pull request. Please review and see what the next steps are. This pull request will auto-close in 7 days without an update. |
|
Hi everyone, it looks like we lost track of this pull request. Please review and see what the next steps are. This pull request will auto-close in 7 days without an update. |
Fixes eslint#21124. `hyperlink` crawls the built site with jsdom and assetgraph, modelling every asset relationship, to answer two questions: does each internal link resolve, and does each fragment exist. It needs a 4GB heap and dominates Docs CI. `lychee` answers both directly, and handles the extensionless pretty URLs this site uses: `fallback_extensions` since 0.16, `index_files` since 0.20. All behaviour now lives in `docs/lychee.toml` instead of a custom script, so `hyperlink`, `@munter/tap-render`, `tap-spot` and `cross-env` all go, along with the heap flag. Two exclusions are workarounds rather than intentional skips, both noted inline. Pretty-URL resolution cannot handle a path segment containing a dot, which covers the `/use/migrate-to-<version>` links; that is lycheeverse/lychee#2274, and the exclusion goes once the fix ships. Protocol-relative URLs are read as local paths in offline mode; the site has two, both external favicons that the old checker skipped as well. One coverage gap this does not work around: `lychee` does not extract `<script src>`, which `hyperlink` checked. No config option restores it.
8eb58bd to
1395770
Compare
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
To your three questions:
|
|
Hi everyone, it looks like we lost track of this pull request. Please review and see what the next steps are. This pull request will auto-close in 7 days without an update. |
|
Hi everyone, it looks like we lost track of this pull request. Please review and see what the next steps are. This pull request will auto-close in 7 days without an update. |
|
Hi everyone, it looks like we lost track of this pull request. Please review and see what the next steps are. This pull request will auto-close in 7 days without an update. |
Prerequisites checklist
AI acknowledgment
What is the purpose of this pull request? (put an "X" next to an item)
[ ] Documentation update
[ ] Bug fix (template)
[ ] New rule (template)
[ ] Changes an existing rule (template)
[ ] Add autofix to a rule
[ ] Add a CLI option
[ ] Add something to the core
[X] Other, please explain: CI change. Replaces the docs link checker to fix #21124.
What changes did you make? (Give an overview)
Fixes #21124.
Draft as suggested, so this can be reviewed while an upstream lychee fix is pending.
This replaces the custom docs link checker with lychee.
hyperlinkcrawls the built site withjsdomandassetgraphand builds a resource graph to answer two questions:lychee answers both directly, and supports the extensionless pretty URLs this site uses through
fallback_extensions(since 0.16) andindex_files(since 0.20).Performance
Measured in CI, before and after:
Validate internal linksVerify Docs FilesjobThe 2s includes downloading the lychee binary. lychee checked 80,268 links with 0 errors.
Memory drops too. Locally, on the same built site, peak RSS goes from 3.98GB (the measurement in #21124, and the reason the old script needed
--max-old-space-size=4096) to 113MB.Changes
All link-checking behaviour moves from
docs/tools/validate-links.jstodocs/lychee.toml. The script and its dependencies are removed:hyperlink,@munter/tap-render,tap-spot,cross-env, and the--max-old-space-size=4096flag it needed.docs/src/maintain/manage-releases.mdtold maintainers to add a pattern toskipPatternsin the deleted script. It now points at theexcludelist indocs/lychee.toml.docs/README.mdgains an install note, becausenpm run lint:linksnow needs alycheebinary that npm does not install. Without the note a contributor getscommand not found.Coverage differences
Two behaviour changes, one in each direction.
<script src>is no longer checked.hyperlinkchecked script sources; lychee does not extract them. The site references 8 local scripts underassets/js/. I could not find a lychee option that restores this, so the limitation is documented indocs/lychee.tomlrather than worked around. This is the one place the new setup checks less than the old one.More HTML pages are checked.
hyperlinkonly crawled pages reachable fromindex.html, leaving 50 orphans unchecked. lychee scans every HTML file in_site, which picks up 36 of them. The remaining 14 arecomponent-library/previews, excluded as link sources because they use placeholder hrefs.Temporary exclusions
Two, both commented inline as workarounds rather than intentional skips.
Dotted extensionless URLs. lychee cannot resolve a path segment containing a dot, so
/use/migrate-to-8.0.0,-9.0.0and-10.0.0are excluded. That is 3 unique URLs but 778 occurrences, since the migration banner appears on every rule page, so while the exclusion stands, deleting a migration page would go uncaught. Tracked upstream as lycheeverse/lychee#2274. The fix, #2276, merged on 2026-09-20, but it is not in a released binary yet: the newest release islychee-v0.24.2(2026-05-01), and the v0.25.0 release PR has been open since late May. I would rather not block this PR on that release. Once one carrying the fix ships, dropping the exclusion and bumpinglycheeVersionis a two-line follow-up.I also tested a
remapworkaround that keeps those URLs checked today. I preferred the exclusion because lychee validates the remapped path: if a remap accidentally points a broken URL at an existing file, the link passes validation. With the upstream fix already approved, the exclusion is the safer failure mode. Happy to switch if you would rather not carry it.Protocol-relative URLs. lychee reads
//host/pathas a local path in offline mode. The site has two, both external favicons, which the previous checker also skipped.Action and binary
The action is pinned to a commit SHA, consistent with the other third-party actions in this repository, so Dependabot keeps it current.
lycheeVersionis pinned separately, since it fixes the binary rather than the action code that installs it.lychee-actiondownloads the binary from GitHub Releases without verifying a checksum. The release does publish.sha256files, but they are controlled by the same upstream release, while hardcoding one here would make every version bump require a second manual edit Dependabot cannot perform.The job has
contents: read, no repository secrets, no cache and no publish step, and link checking is its final step, so I left the action's installation behaviour unchanged.Review questions
<script src>coverage. The new checker does not validate these. Is that reduction a blocker? If so I can look at adding the extractor upstream.docs/is not infiles), anddocs/tooling already downloads binaries at install time throughbin-wrapper(viagifsicle,jpegtran-bin,optipng-bin). Is that acceptable here?Verification
Verified locally against a freshly built
_siteusing lychee 0.24.2. The check completes in ~1s over 80,267 links with 0 errors, and still catches:<img src>references<link rel="stylesheet">references.htmlURLsindex.htmldirectory linksDisclosure: I'm a participant of open source contribution program OSSCA