ci: add pinned source-link checker#122
Conversation
Adds scripts/check-source-links.mjs, wired as `npm run check:links`. It greps docs/ for pinned github.com/<owner>/<repo>/blob/<hash>/<path> links and checks each resolves via the GitHub contents API with ref=<hash>, using GITHUB_TOKEN/GH_TOKEN when present so private repos resolve. It exits non-zero listing any that 404 (or cannot be verified) and 0 when all resolve. Existence check only, no line-range/content-drift matching. Refs #120 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
VERDICT: approve
Rules + review sweep for the pinned source-link checker. No blocking issues.
Checked and clean:
- PR title and commit
ci: add pinned source-link checkersatisfy the semantic-PR title check (pr-title.ymlis present). - Body has
Closes #120, so the tracking issue auto-closes on merge. - No
.github/workflows/files touched; the CI job is proposed as a patch in the body for a maintainer. - Reviewer @rubenhensen is requested.
apiPathdecode-then-reencode handles+and encoded parens in blob paths correctly, and non-200/non-404 responses exit non-zero so a run that could not confirm never shows green.
One non-blocking note (nit): LINK_RE stops the path group at ), so a link whose path has a literal unencoded parenthesis (e.g. a SvelteKit route group /routes/(app)/+page.svelte) would be truncated and could 404 as a false positive. No current docs link hits this — the encoded %28app%29 form resolves fine and all 45 links pass — so it is a latent edge, not something to fix now. Widening the group to allow ) is risky because markdown wraps URLs in [text](url), so the trailing ) must stay excluded. Leaving as a comment.
Verified: npm run check:links finds 45 unique links, all resolve (exit 0); injecting a bad path/repo yields 404s with exit 1.
| // Decode each segment, then re-encode for the API path so characters like | ||
| // "+" survive as %2B rather than being read as a space. | ||
| function apiPath(rawPath) { | ||
| return rawPath |
There was a problem hiding this comment.
Nit (non-blocking): the path group stops at ), so a literal unencoded parenthesis in a path (e.g. a SvelteKit route group /routes/(app)/+page.svelte) would be truncated and could 404 as a false positive. All 45 current links use the encoded %28app%29 form and pass, so this is a latent edge only. Widening to allow ) is risky since markdown wraps URLs in [text](url).
Adds a checker for the pinned GitHub source links in
docs/, per #120.What it does
scripts/check-source-links.mjsgrepsdocs/for pinned links of the formhttps://github.com/<owner>/<repo>/blob/<hash>/<path>, then checks each one resolves via the GitHub contents API withref=<hash>. It readsGITHUB_TOKEN/GH_TOKENfrom the environment when present, so private repos resolve and the unauthenticated rate limit (60 req/hour) is lifted. It exits non-zero and lists any link that 404s, and exits 0 when all resolve.Wired in as
npm run check:links.This is an HTTP existence check only. It does not compare line ranges or snippet content against the file, matching the scope in #120 (that deeper check is explicitly out of scope).
Verified locally
npm run check:linksfinds 45 unique pinned links and reports all resolve (matches the count in the issue).Non-200, non-404 responses (rate limit, auth, network, 5xx) are reported separately as "could not verify" and also exit non-zero, so a run that could not confirm the links never shows green.
CI wiring (needs a maintainer)
The Dobby App cannot push to
.github/workflows/, so this PR does not touch CI. All repos currently linked fromdocs/are public, so the built-inGITHUB_TOKENresolves them and lifts the rate limit. Suggested addition to.github/workflows/ci.yml:Closes #120