Docs testing framework: static checks, anchor validation, live smoke checks, and CI wiring - #6991
Open
emmanueletienne-blip wants to merge 26 commits into
Open
emmanueletienne-blip wants to merge 26 commits into
emmanueletienne-blip wants to merge 26 commits into
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
emmanueletienne-blip
requested review from
devalog,
jkonrath-postman and
nerminamiller-postman
as code owners
September 17, 2026 15:31
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Contributor
|
🌿 Preview your docs: https://fern-preview-devin-1789659014-docs-check-framework.docs.buildwithfern.com/learn Here are the markdown pages you've updated: |
…n pages, guard --write-baseline --only Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…includes and every snippet includer, tolerate folder/ref versions Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…link user feedback to its canonical URL Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ding Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…b, preview and post-publish verification - broken-anchor check: #fragment links must match a heading, explicit [#id], <Anchor id>, Step/Tab/Accordion title or ParamField path on the target page (snippet anchors included). All 36 findings confirmed against the live site. - slugify: split trailing capitals (APIs -> ap-is), matching the platform; every derived URL now returns 200 on buildwithfern.com. - smoke.py: fetch derived page URLs from a deployed site; fail on non-200, error-page markers and broken <main> images. --changed maps pages and snippets to URLs; navigation YAML edits widen to the whole site. - docs-checks.yml: lychee over changed files on PRs (shared .github/lychee.toml, extracted from check-links.yml); scheduled production smoke run feeds the tracking issue. - preview-docs.yml smoke-tests changed pages on the preview; publish-docs.yml verifies every URL after fern generate. - untrack __pycache__ Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…de them from lychee; trigger on README.md Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…nges Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…e on link-free changes Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…checks Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ing, chain-before-page Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ge sample), weekday job Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…as nightly Fragments are matched to the schema object that declares their keys, elided and templated values are ignored, and the 27 real discrepancies found today are baselined in examples-baseline.txt for triage. Also: console smoke ignores prefetches of other pages (the preview changelog index 500s on every preview) and duplicate resource-load console lines, and the PR external-link job includes .md/.yaml files. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ng in smoke.py Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…atic checker Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ors: accept any explicit id attribute Production publishes the home page at /learn/home (sitemap and navigation slug both say so); /learn is only a redirect. Restores the original /learn/home#get-support link, which targets a raw <div id> the anchor check previously did not recognise. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… not rendered Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…elCase SVG ids) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.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.
Summary
A layered docs testing framework for buildwithfern.com/learn that fails at the earliest stage that can catch a problem:
docs-checks.ymlscripts/docs_checkstatic checks,fern checkdocs-checks.yml.github/lychee.toml, extracted fromcheck-links.yml)preview-docs.ymlscripts/docs_check/smoke.pyagainst the preview for every page the PR touchesmainpublish-docs.ymlsmoke.pyagainst production for every derived URL afterfern generatedocs-checks.ymlStatic checker (
python3 -m scripts.docs_check, PyYAML only) rebuilds every page's published/learn/...URL fromfern/docs.yml+ product navigation (productslug,skip-slug,slug:overrides, frontmatterslugrelative to the product root, CamelCase splittingGitLab→git-lab,APIs→ap-is) and validates the tree against that model. Errors:nav-path-missing,broken-internal-link,broken-anchor,missing-snippet,missing-asset,changelog-filename,changelog-missing-tags. Warnings:redirected-link,relative-page-link,orphan-page,unused-snippet,missing-title,missing-description,stub-page,changelog-h1. Plus a per-product coverage table in the job summary and a JSON artifact.broken-anchor:#fragmenton same-page and/learn/...links must match an id the target page renders. Ids are derived from source in document order with a shared duplicate counter (api,api-1): headings (with optional[#id]),<Step>/<Tab>/<Accordion>titles,<ParamField path>,<Anchor id>, recursing into included snippets. A first version that only modeled headings produced 164 false positives; the shipped version reports 36, every one confirmed missing in the live HTML. A residual gap: some generated components apply their own id transformation (one link,#user-agenton the PHP configuration page, resolves in source but not on the site), documented in the README.smoke.py: fetch derived URLs from a deployed origin; fail on non-200,Page not found/Something went wrongin the body, or an image under<main>that does not load.--changedmaps edited pages to their URL and edited snippets to every including page; an edited navigation YAML widens the run to the whole site. 404/5xx are retried with backoff so a propagating deploy does not fail the run.The one 404 the first run found (
/learn/api-definitions/ferndef/depending-on-other-apis) was a slug-derivation bug, not an unpublished page: the platform splitsAPIsasap-is. Fixed inslugify.Baseline:
scripts/docs_check/baseline.txtsuppresses 194 pre-existing findings (<check> <path> <message>, one occurrence per line) so the job is green today and only new problems fail a PR; the 36 anchor entries are real broken fragments for triage. Content fixes: two broken internal links on main.Verification
python3 -m unittest discover -s scripts/docs_check/tests -t .→ 13 tests OKpython3 -m scripts.docs_check --strict→0 errors, 0 warnings (194 suppressed by baseline)smoke.pyagainst production → 0 failures across 335 pages; against the PR preview with--changed→ 0 failures.github/lychee.tomlover sample changed files → 0 errorsfern check --warningsunchanged; zizmor: no new findings; Vale passesLink to Devin session: https://app.devin.ai/sessions/4b823dd919a841988f58f31b6dc722a2
Open in Devin Desktop: https://app.devin.ai/desktop/session/4b823dd919a841988f58f31b6dc722a2?variant=devin
Requested by: @emmanueletienne-blip