ci/links: Add PR check for broken links - #1858
Open
marcleblanc2 wants to merge 20 commits into
Open
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
check-links PR check
This was referenced Sep 7, 2026
check-links PR check
marcleblanc2
added a commit
that referenced
this pull request
Sep 10, 2026
Linear [FE-499: Fix doc site issues](https://linear.app/sourcegraph/issue/FE-499/fix-doc-site-issues) 25 `#anchor` links whose target heading still exists with the same words, but the slug drifted: - `_` vs `-` - doubled `--` - a stray `"` - punctuation github-slugger strips (`ssl/https` → `sslhttps`, `merge/close` → `mergeclose`, `Sourcegraph's` → `sourcegraphs`, `kustomization.yaml` → `kustomizationyaml`) No page changes, no wording changes. Every new anchor matches a real heading on the target page, so review is a skim: the words on both sides of each `→` are the same. Checker findings (`npm run check-links -- --check-anchors`, from #1858): 280 on main → 255 on this branch. One to note: `#deploy-sourcegraph` → `#deploy-sourcegraph-` in `docs/self-hosted/deploy/machine-images/aws-oneclick.mdx` — the heading is `## Deploy Sourcegraph 🎉` and the slugger turns the emoji into a trailing `-`, so its slug has a trailing `-`. Fixing the heading instead would be cleaner but changes a URL; left as a slug fix here. ## Verification The docs site serves its not-found page with HTTP 200 (fix in progress), so status codes prove nothing. Instead, every changed link was fetched on this PR's Vercel preview and the rendered HTML checked for two `id`s: the target page's own first heading (taken from its MDX source — the 404 page never has it) and the link's `#fragment`. Script: `node dev/verify-links-live.mjs --site <preview-url>`, coming in #1858. Old links point at the current production site so you can see the breakage; new links point at the preview and land on the heading. Checked 25 changed links against https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app: 25 resolve, 0 fail. Page rendered = the target page's first heading id is present (the 404 page never has it); Anchor = the #fragment is an id on the page. Old links point at the current site. <details><summary>All 25 links</summary> | File containing the link | Old link (broken today) | New link (preview) | Page rendered | Anchor found | |------|-------------------------|--------------------|---------------|--------------| | `docs/admin/auth/index.mdx` | [`/admin/config/authorization-and-authentication#bitbucket-server-bitbucket-data-center-authorization`](https://sourcegraph.com/docs/admin/config/authorization-and-authentication#bitbucket-server-bitbucket-data-center-authorization) | [`/admin/config/authorization-and-authentication#bitbucket-server--bitbucket-data-center-authorization`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/admin/config/authorization-and-authentication#bitbucket-server--bitbucket-data-center-authorization) | ✅ | ✅ | | `docs/admin/auth/saml/microsoft-adfs.mdx` | [`/self-hosted/http-https-configuration#nginx-ssl-https-configuration`](https://sourcegraph.com/docs/self-hosted/http-https-configuration#nginx-ssl-https-configuration) | [`/self-hosted/http-https-configuration#nginx-sslhttps-configuration`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/self-hosted/http-https-configuration#nginx-sslhttps-configuration) | ✅ | ✅ | | `docs/admin/code-hosts/non-git.mdx` | [`#next-steps--advanced-configuration`](https://sourcegraph.com/docs/admin/code-hosts/non-git#next-steps--advanced-configuration) | [`#next-steps-advanced-configuration`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/admin/code-hosts/non-git#next-steps-advanced-configuration) | ✅ | ✅ | | `docs/admin/search.mdx` | [`/self-hosted/observability/alerts#zoekt-memory-map-areas-percentage-used`](https://sourcegraph.com/docs/self-hosted/observability/alerts#zoekt-memory-map-areas-percentage-used) | [`/self-hosted/observability/alerts#zoekt-memory_map_areas_percentage_used`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/self-hosted/observability/alerts#zoekt-memory_map_areas_percentage_used) | ✅ | ✅ | | `docs/batch-changes/batch-spec-yaml-reference.mdx` | [`#changesettemplate-branch`](https://sourcegraph.com/docs/batch-changes/batch-spec-yaml-reference#changesettemplate-branch) | [`#changesettemplatebranch`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/batch-changes/batch-spec-yaml-reference#changesettemplatebranch) | ✅ | ✅ | | `docs/batch-changes/batch-spec-yaml-reference.mdx` | [`#steps-run`](https://sourcegraph.com/docs/batch-changes/batch-spec-yaml-reference#steps-run) | [`#stepsrun`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/batch-changes/batch-spec-yaml-reference#stepsrun) | ✅ | ✅ | | `docs/batch-changes/batch-spec-yaml-reference.mdx` | [`#on-repository`](https://sourcegraph.com/docs/batch-changes/batch-spec-yaml-reference#on-repository) | [`#onrepository`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/batch-changes/batch-spec-yaml-reference#onrepository) | ✅ | ✅ | | `docs/batch-changes/batch-spec-yaml-reference.mdx` | [`#changesettemplate-branch`](https://sourcegraph.com/docs/batch-changes/batch-spec-yaml-reference#changesettemplate-branch) | [`#changesettemplatebranch`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/batch-changes/batch-spec-yaml-reference#changesettemplatebranch) | ✅ | ✅ | | `docs/batch-changes/batch-spec-yaml-reference.mdx` | [`#changesettemplate-branch`](https://sourcegraph.com/docs/batch-changes/batch-spec-yaml-reference#changesettemplate-branch) | [`#changesettemplatebranch`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/batch-changes/batch-spec-yaml-reference#changesettemplatebranch) | ✅ | ✅ | | `docs/batch-changes/batch-spec-yaml-reference.mdx` | [`#changesettemplate-title`](https://sourcegraph.com/docs/batch-changes/batch-spec-yaml-reference#changesettemplate-title) | [`#changesettemplatetitle`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/batch-changes/batch-spec-yaml-reference#changesettemplatetitle) | ✅ | ✅ | | `docs/batch-changes/batch-spec-yaml-reference.mdx` | [`#changesettemplate-title`](https://sourcegraph.com/docs/batch-changes/batch-spec-yaml-reference#changesettemplate-title) | [`#changesettemplatetitle`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/batch-changes/batch-spec-yaml-reference#changesettemplatetitle) | ✅ | ✅ | | `docs/batch-changes/batch-spec-yaml-reference.mdx` | [`#workspaces-in`](https://sourcegraph.com/docs/batch-changes/batch-spec-yaml-reference#workspaces-in) | [`#workspacesin`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/batch-changes/batch-spec-yaml-reference#workspacesin) | ✅ | ✅ | | `docs/batch-changes/batch-spec-yaml-reference.mdx` | [`#changesettemplate-branch`](https://sourcegraph.com/docs/batch-changes/batch-spec-yaml-reference#changesettemplate-branch) | [`#changesettemplatebranch`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/batch-changes/batch-spec-yaml-reference#changesettemplatebranch) | ✅ | ✅ | | `docs/batch-changes/batch-spec-yaml-reference.mdx` | [`#steps-outputs`](https://sourcegraph.com/docs/batch-changes/batch-spec-yaml-reference#steps-outputs) | [`#stepsoutputs`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/batch-changes/batch-spec-yaml-reference#stepsoutputs) | ✅ | ✅ | | `docs/batch-changes/site-admin-configuration.mdx` | [`/admin/config/batch-changes#automatically-delete-branches-on-merge-close`](https://sourcegraph.com/docs/admin/config/batch-changes#automatically-delete-branches-on-merge-close) | [`/admin/config/batch-changes#automatically-delete-branches-on-mergeclose`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/admin/config/batch-changes#automatically-delete-branches-on-mergeclose) | ✅ | ✅ | | `docs/code-insights/explanations/current-limitations-of-code-insights.mdx` | [`/admin/permissions/api#Setting-sub-repository-permissions-for-users`](https://sourcegraph.com/docs/admin/permissions/api#Setting-sub-repository-permissions-for-users) | [`/admin/permissions/api#setting-sub-repository-permissions-for-users`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/admin/permissions/api#setting-sub-repository-permissions-for-users) | ✅ | ✅ | | `docs/code-insights/references/requirements.mdx` | [`/admin/permissions/api#Setting-sub-repository-permissions-for-users`](https://sourcegraph.com/docs/admin/permissions/api#Setting-sub-repository-permissions-for-users) | [`/admin/permissions/api#setting-sub-repository-permissions-for-users`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/admin/permissions/api#setting-sub-repository-permissions-for-users) | ✅ | ✅ | | `docs/code-navigation/auto-indexing-configuration.mdx` | [`#index-jobs`](https://sourcegraph.com/docs/code-navigation/auto-indexing-configuration#index-jobs) | [`#index_jobs`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/code-navigation/auto-indexing-configuration#index_jobs) | ✅ | ✅ | | `docs/self-hosted/deploy/kubernetes/troubleshoot.mdx` | [`#symbols-sidebar-and-hovers-are-not-working"`](https://sourcegraph.com/docs/self-hosted/deploy/kubernetes/troubleshoot#symbols-sidebar-and-hovers-are-not-working") | [`#symbols-sidebar-and-hovers-are-not-working`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/self-hosted/deploy/kubernetes/troubleshoot#symbols-sidebar-and-hovers-are-not-working) | ✅ | ✅ | | `docs/self-hosted/deploy/machine-images/aws-oneclick.mdx` | [`#deploy-sourcegraph`](https://sourcegraph.com/docs/self-hosted/deploy/machine-images/aws-oneclick#deploy-sourcegraph) | [`#deploy-sourcegraph-`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/self-hosted/deploy/machine-images/aws-oneclick#deploy-sourcegraph-) | ✅ | ✅ | | `docs/self-hosted/faq.mdx` | [`/self-hosted/observability/dashboards#frontend-provisioning-container-cpu-usage-long-term`](https://sourcegraph.com/docs/self-hosted/observability/dashboards#frontend-provisioning-container-cpu-usage-long-term) | [`/self-hosted/observability/dashboards#frontend-provisioning_container_cpu_usage_long_term`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/self-hosted/observability/dashboards#frontend-provisioning_container_cpu_usage_long_term) | ✅ | ✅ | | `docs/self-hosted/faq.mdx` | [`/self-hosted/observability/alerts#frontend-container-cpu-usage`](https://sourcegraph.com/docs/self-hosted/observability/alerts#frontend-container-cpu-usage) | [`/self-hosted/observability/alerts#frontend-container_cpu_usage`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/self-hosted/observability/alerts#frontend-container_cpu_usage) | ✅ | ✅ | | `docs/self-hosted/faq.mdx` | [`#can-i-consume-sourcegraph-s-metrics-in-my-own-monitoring-system-datadog-new-relic-etc`](https://sourcegraph.com/docs/self-hosted/faq#can-i-consume-sourcegraph-s-metrics-in-my-own-monitoring-system-datadog-new-relic-etc) | [`#can-i-consume-sourcegraphs-metrics-in-my-own-monitoring-system-datadog-new-relic-etc`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/self-hosted/faq#can-i-consume-sourcegraphs-metrics-in-my-own-monitoring-system-datadog-new-relic-etc) | ✅ | ✅ | | `docs/self-hosted/http-https-configuration.mdx` | [`#nginx-ssl-https-configuration`](https://sourcegraph.com/docs/self-hosted/http-https-configuration#nginx-ssl-https-configuration) | [`#nginx-sslhttps-configuration`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/self-hosted/http-https-configuration#nginx-sslhttps-configuration) | ✅ | ✅ | | `docs/self-hosted/http-https-configuration.mdx` | [`#nginx-ssl-https-configuration`](https://sourcegraph.com/docs/self-hosted/http-https-configuration#nginx-ssl-https-configuration) | [`#nginx-sslhttps-configuration`](https://sourcegraph-docs-git-fix-anchor-slug-drift-sourcegraph-f8c71130.vercel.app/self-hosted/http-https-configuration#nginx-sslhttps-configuration) | ✅ | ✅ | </details> Dropped from this PR: 11 same-page anchors in `docs/self-hosted/deploy/kubernetes/kustomize/index.mdx`. That file is shadowed by `kustomize.mdx` at the same route and never renders, so its links cannot be verified (or clicked) on the site. They go with the shadowed-route cleanup instead. Co-authored-by: Amp <amp@ampcode.com>
marcleblanc2
force-pushed
the
check-links-pr-check
branch
from
September 10, 2026 03:21
5baaad5 to
7e827bc
Compare
marcleblanc2
added a commit
that referenced
this pull request
Sep 10, 2026
Linear [FE-499: Fix doc site issues](https://linear.app/sourcegraph/issue/FE-499/fix-doc-site-issues) ## Problem The right-hand TOC (`headings` computed field in `contentlayer.config.ts`) strips fenced code blocks with the non-greedy regex `/```[\s\S]*?```/g`, then treats any remaining `#` line as a heading. Any inline triple-backtick run in prose is taken as a fence opener and flips every later fence pairing. `docs/batch-changes/batch-spec-yaml-reference.mdx` has two (`` `"true``` `` on line 376, `` `"*``` `` on line 709), so from there on the "inside/outside a fence" state is inverted: YAML `# comment` lines leak into the TOC as headings whose anchors don't exist, and real headings are dropped. Live repro: https://sourcegraph.com/docs/batch-changes/batch-spec-yaml-reference has a TOC entry linking to `#do-not-meddle-in-the-affairs-of-wizards-for-they-are-subtle-and-quick-to-anger` (line 572 of the MDX, a YAML comment inside a fence). No element with that id exists. This page alone accounted for 14 of the broken anchors found by lychee in the investigation behind #1858. ## Before / after TOC on `/batch-changes/batch-spec-yaml-reference`, local `next dev`, 1600px viewport. | Before (`main`) | After (this PR) | | --- | --- | | <img src="https://ampcode.com/user-content/artifacts/ee9ba290aa34b608e52fa272b2abfdc0cf6484f93120fa42b2c1c31441aab30f-file.png" width="400"> | <img src="https://ampcode.com/user-content/artifacts/96b96b558b53a28b6f65f786485818bb28dce5812a8c32995a1725242f1ad6dd-file.png" width="400"> | Before: 12 YAML comments (`if: is true, step always executes.`, `Mount a Python script and run the script`, `Do not meddle in the affairs of wizards…`) render as TOC entries with dead anchors, and every `changesetTemplate.*` heading except `.fork` is missing. After: the comments are gone and `steps.mount`, `importChangesets*`, `changesetTemplate*`, `Publishing only specific changesets` are back. ## Fix Walk the body line by line: a fence opens on a line starting with 3+ backticks or tildes and closes on a line of the same character at least as long, matching how the MDX renderer treats fences. Also handles the ```` ```` ```` four-backtick fences in `cody/troubleshooting.mdx` and `code-navigation/writing-an-indexer.mdx` that contain literal ```` ``` ```` text. ## Verification - Compared old vs new heading output across every `.mdx` under `docs/`: only `batch-spec-yaml-reference.mdx` changes — 12 bogus comment entries removed, 13 real headings restored. - `npx contentlayer build`: generated `Post` for that page has 66 headings, 0 bogus, all `changesetTemplate.*` ids present. - `npx tsc --noEmit` clean, `next lint` clean. Follow-up from the link-check work in #1858. Co-authored-by: Amp <amp@ampcode.com>
Add a pull_request workflow that runs dev/check-links.mjs --check-anchors on both the PR head and its merge base, and reports only the findings the PR introduces: outbound links from changed pages, and inbound links from other pages to a page or heading the PR removed or renamed. Pre-existing broken anchors on main are ignored. The job comments on the PR and fails when new breakage is found. dev/check-links.mjs gains --root, --format (text|json|markdown) and --baseline to support that diff, plus case-mismatch detection for routes (links that resolve on macOS but 404 on Linux) and scanning of *.md files. Only *.mdx files count as routes, matching contentlayer's filePathPattern. Amp-Thread-ID: https://ampcode.com/threads/T-01a0753f-0f4f-7478-b36c-87466e7c0261 Co-authored-by: Amp <amp@ampcode.com>
…erted) Amp-Thread-ID: https://ampcode.com/threads/T-01a0753f-0f4f-7478-b36c-87466e7c0261 Co-authored-by: Amp <amp@ampcode.com>
…l be reverted)" This reverts commit 1edcff8.
Generated pages such as admin/telemetry/protocol.mdx define anchors with <a name="..."> rather than headings. Drops 132 false positives on main (431 -> 299 with --check-anchors). Amp-Thread-ID: https://ampcode.com/threads/T-01a0753f-0f4f-7478-b36c-87466e7c0261 Co-authored-by: Amp <amp@ampcode.com>
Replace the fs.existsSync asset checks (case-insensitive on macOS, so they
hid links that 404 on the Linux build) with an enumerated lowercase -> real
path map of files under public/ and docs/, mirroring the route check.
Also register docs/index.mdx as the / route. It was never in the path map
(the /index strip needed a leading slash), and existsSync('public/') was
masking that by accepting any '/' link. Six pre-existing broken /#anchor
links on the homepage are now reported.
Amp-Thread-ID: https://ampcode.com/threads/T-01a07597-43c0-751b-8c49-6e5809e714d2
Co-authored-by: Amp <amp@ampcode.com>
A green run posts nothing. If an earlier run left a report and the PR has since been fixed, delete that comment instead of editing it to a checkmark. Amp-Thread-ID: https://ampcode.com/threads/T-01a07597-43c0-751b-8c49-6e5809e714d2 Co-authored-by: Amp <amp@ampcode.com>
The checkmark comment only ever appears after an earlier run reported breakage, so word it that way instead of "introduces no broken links". Keeps the comment (reverts the delete from the previous commit). Amp-Thread-ID: https://ampcode.com/threads/T-01a07597-43c0-751b-8c49-6e5809e714d2 Co-authored-by: Amp <amp@ampcode.com>
…-page anchors use own headings Amp-Thread-ID: https://ampcode.com/threads/T-01a07623-9d65-7356-96b8-2bebb31ffa5a Co-authored-by: Amp <amp@ampcode.com>
…ployed site Co-authored-by: Amp <amp@ampcode.com> Amp-Thread-ID: https://ampcode.com/threads/T-01a07623-9d65-7356-96b8-2bebb31ffa5a
…k, matching rehype-slug Amp-Thread-ID: https://ampcode.com/threads/T-01a07623-9d65-7356-96b8-2bebb31ffa5a Co-authored-by: Amp <amp@ampcode.com>
The checker resolves links against docs/**/*.mdx routes only and never reads src/data/redirects.ts, so a redirect added alongside a page move still leaves inbound links reported. Say so in the PR comment and in AGENTS.md so contributors update the links instead. Amp-Thread-ID: https://ampcode.com/threads/T-01a085bf-fe07-77a1-a4e2-55bff4679bcc Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-01a088d9-b8fd-76fd-ba93-3a416c5829a3 Co-authored-by: Amp <amp@ampcode.com>
… not count Amp-Thread-ID: https://ampcode.com/threads/T-01a088d9-b8fd-76fd-ba93-3a416c5829a3 Co-authored-by: Amp <amp@ampcode.com>
… PR branch Amp-Thread-ID: https://ampcode.com/threads/T-01a088d9-b8fd-76fd-ba93-3a416c5829a3 Co-authored-by: Amp <amp@ampcode.com>
…the source view Drop glob in favour of fs.readdirSync(recursive) so the PR check needs one package instead of the whole site, and skip the pnpm/setup-node steps. Every finding now links to the file and line on the PR branch, in the ?plain=1 code view where #L anchors work. Amp-Thread-ID: https://ampcode.com/threads/T-01a088d9-b8fd-76fd-ba93-3a416c5829a3 Co-authored-by: Amp <amp@ampcode.com>
Outbound findings are in files the PR changed (it added or edited a bad link); inbound ones are elsewhere (the PR renamed or removed a link target). The workflow passes git diff --name-only against the merge base.
…l superseded runs Amp-Thread-ID: https://ampcode.com/threads/T-01a088d9-b8fd-76fd-ba93-3a416c5829a3 Co-authored-by: Amp <amp@ampcode.com>
… probe external links on added lines Absolute links to this site (https://sourcegraph.com/docs/..., the legacy docs.sourcegraph.com host, http://, //, www.) are findings even when the target exists: they leave preview deployments and local dev, and hide moved pages behind redirects. The finding proposes the relative link, following src/data/redirects.ts when the page moved. Version-pinned links (/@5.1/...) stay external. --diff replaces --changed-files and scopes two new features to added lines: --check-external requests each external link (HEAD, then GET on an error status, following redirects) and reports 404/410 only; --review writes a GitHub review with one suggested change per line, which the workflow posts, skipping suggestions already on the PR. Amp-Thread-ID: https://ampcode.com/threads/T-01a08a01-44c1-775b-84d0-d67ff9501905 Co-authored-by: Amp <amp@ampcode.com>
marcleblanc2
force-pushed
the
check-links-pr-check
branch
from
September 10, 2026 06:57
c6d0c22 to
c17d30e
Compare
This was referenced Sep 10, 2026
…he ones the suggestion leaves Amp-Thread-ID: https://ampcode.com/threads/T-01a08a01-44c1-775b-84d0-d67ff9501905 Co-authored-by: Amp <amp@ampcode.com>
… so next build fails on dead links alone Amp-Thread-ID: https://ampcode.com/threads/T-01a08a01-44c1-775b-84d0-d67ff9501905 Co-authored-by: Amp <amp@ampcode.com>
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.
Linear FE-499: Fix doc site issues
Problem
dev/check-links.mjsfinds broken internal links and anchors, but it isn't run automatically, so PRs can easily break links (renaming a heading, moving or deleting a page) without anyone noticingSolution
Updated the script to also work as a PR check, with additional functions beyond what's run when used as a CI test in Vercel builds
PR check to run the script and report if the PR breaks links
It runs the script (with
--check-anchors) on both the PR head and its merge base, and diffs the findingsThis catches both directions:
Outbound: a changed page links to a page or
#headingthat doesn't existInbound: the PR renames a heading or removes/moves a page that other, unchanged pages link to — those show up as findings in files the PR didn't touch
Pre-existing broken links are ignored by the PR check
The comment is created / updated in place, and once the PR is fixed, the PR check passes and the comment is updated to say so
A PR that never broke anything gets no comment
Verification
PR check comment in test PR: #1895 (comment)
Broken links found
Broken links fixed
Absolute self-links and external links
https://sourcegraph.com/docs/…,http://…,//…,www., the legacyhttps://docs.sourcegraph.com/…) fail the check even when the target exists: they leave the Vercel preview and local dev, and hide moved pages behind redirects. The finding names the relative link, followingsrc/data/redirects.tswhen the page moved. Version-pinned links (/@5.1/…) stay external*.example.com,localhost, templated<host>) are skippedTest PR: #1900 (report comment + one review suggestion; the
#samplinganchor deliberately does not exist, so that link gets no suggestion; a second run posted nothing new)Related
Amp threads