fix(docs): link version picker entries to each version's landing doc - #2095
Merged
Conversation
Archived versions are still Docusaurus-built and carry .theme-doc-markdown, not the Astro layer's .docs-content, so the original assertion could never go green once the picker pointed at them. A bare h1 is not a valid simplification: the 404 page a 403 renders has exactly one h1. The helm-chart test asserted only an absence, which a 404 or a blank page would satisfy; it now anchors on the page's own heading first.
Every picker entry pointed at a version root (/docs/apisix/3.15/). Those directories carry no index.html, so ASF httpd answers 403 through Options -Indexes and ErrorDocument renders the 404 page — 8 dead links on each of 249 English pages plus the zh mirror, and 6 more across the sub-projects. Entries now link the target version's landing doc, derived from the first leaf of the project's sidebar. The full landing path is required: linking .../3.15/getting-started/ would hit the .htaccess:160 redirect and land on the latest version instead. helm-chart renders no unreleased entry — Docusaurus does not version-publish it, so /docs/helm-chart/next/ has never existed.
Catches two classes the Astro build structurally cannot: an archived version listed in APISIX_ARCHIVED_VERSIONS but never published, and a landing URL that escapes its project prefix. This step runs after the overlay because that is the only point where both toolchains' output exists.
zh/docs/helm-chart/ is Astro-built and shipped the same dead /zh/docs/helm-chart/next/ link as the English tree, but the assertion checked only English, leaving a Chinese-side regression undetectable. A missing tree now fails loudly too: grep -r on an absent path exits 2, which inside `if` reads as "no match", so the negative assertion would otherwise pass on a build that shipped no helm-chart docs at all.
… deploy toBeVisible() on a locator resolving to several elements is a Playwright strict-mode violation. This spec runs inside the deploy workflow, and the sub-project next/ trees are rebuilt from upstream master on every run, so a doc gaining a second top-level heading would fail the site deploy rather than a test. python-plugin-runner's next/getting-started already ships two. .first() does not weaken the check: a zero-match locator still fails toBeVisible, which is what keeps 404 pages and directory listings red. Also narrows an overstated claim in the deploy gate's comment to what the step uniquely does, so it does not read as disprovable.
LiteSun
approved these changes
Aug 5, 2026
guoqqqi
approved these changes
Aug 6, 2026
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.
Changes:
The docs version picker linked every entry to a version root directory (
/docs/apisix/3.16/). Those directories contain noindex.html, and.htaccesssetsOptions -Indexes, so ASF httpd answers HTTP 403, whichErrorDocument 403 /404.htmlthen renders as the 404 page. The status code is 403 rather than 404, which reads to crawlers as access-denied rather than gone.Measured against the published
asf-sitetree:/docs/apisix/301at.htaccess:158/docs/apisix/3.10/…/docs/apisix/3.16//docs/apisix/next//docs/{ingress-controller,helm-chart,docker,java-,go-,python-plugin-runner}/next/That is 8 dead links on each of the 249 English version-less docs pages, plus the Chinese mirror.
This is the same class of bug
.htaccess:156-160already fixes for/docs/apisix/and/docs/ingress-controller/, under the comment "Bare landing directories have no index page and return 403". The versioned directories were simply missed.The fix
Each entry now links that version's landing doc, derived from the first leaf of the project's sidebar — no new data, and it tracks upstream sidebar changes automatically. URL construction moves out of
DocPage.astrointo two pure functions incontent.ts; the layout receives a preparedversions[]array and only renders it. Splitting that knowledge across the layout and its callers is what allowed the bug.The full landing path is required, not just the version segment:
.htaccess:160redirects/docs/apisix/3.<n>/getting-started/to the latest version, so emitting the shorter form would silently defeat the version switch.versionedLandingHref's doc comment records this so a future simplification is pre-refuted.helm-chartnow renders no "Next (unreleased)" entry at all. Docusaurus does not version-publish it — there is no/docs/helm-chart/next/tree and never has been — so that entry was a 403 by construction. With one version left, the picker collapses to a plain label instead of a one-item dropdown.Two small corrections on lines already being touched: the current-version entry links its landing doc directly (one less redirect hop, one less dependency on
.htaccess), and itsaria-currentbecomes"true"instead of"page"— it marks the current version, so on any page other than the landing doc"page"told screen readers something false.Failure handling
next/src/**degrades rather than throwing, matching this project's split between a degrading render path and hard-failing validators: an unresolvable entry is dropped, an empty sidebar renders no picker. The newdeploy.ymlstep is where failure is loud — after the overlay, it walks every built docs page, collects each.version-pickerhref, and fails the deploy if any has no file behind it. That is the only layer that can catchAPISIX_ARCHIVED_VERSIONS(a hardcoded list) drifting from what is actually published, because the Astro build never sees archived-version content.This gate is deliberately deploy-blocking. If a listed archived version is ever unpublished, the site deploy fails until the list is corrected. That is the point, but it is worth knowing before merging.
Testing
next/tests/e2e/docs-version-picker.spec.mjscollects every picker href and asserts each opens a real docs page.It asserts on page content, never on HTTP status, because the e2e static server (
python3 -m http.server) answers an index-less directory with200plus a directory listing where production returns403— a status assertion would have passed on the exact build the test exists to reject. It accepts both.docs-content h1and.theme-doc-markdown h1, because version-less pages are Astro-built and archived versions are still Docusaurus-built. A bareh1would not work either: the 404 page a 403 renders has exactly oneh1, with the text404.Verified against production before the fix: 5 failures, each on the intended assertion, naming
/docs/apisix/3.16/,/zh/docs/apisix/3.16/,/docs/ingress-controller/next/,/docs/docker/next/, and the helm-chartnextlink.Known limitations, disclosed
/docs/apisix/3.16/) still returns 403. This PR fixes the links that produce those URLs; bookmarks and already-indexed URLs need an.htaccessredirect, which is intentionally out of scope here.EXPECT_DOCUSARUS_ROUTESis unset) and runs fully only in the deploy pipeline against the overlaid tree. It is red against production until the first post-merge deploy. I have not claimed a green run here, because the archived pages it needs exist only in that assembled tree.Screenshots of the change:
No visual change to the docs layout. The one user-visible difference is on
/docs/helm-chart/*, where the version picker becomes a plain label instead of a dropdown whose only entry was broken.