Skip to content

Redesign documentation versioning: one sitewide Stable/Development toggle - #20

Closed
bcastets-robotiq wants to merge 3 commits into
mainfrom
automate-cut-version
Closed

bcastets-robotiq wants to merge 3 commits into
mainfrom
automate-cut-version

Conversation

@bcastets-robotiq

@bcastets-robotiq bcastets-robotiq commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This PR started as an automation follow-up to #14, but grew into a redesign of how documentation versioning works on this site. It replaces the per-tool architecture #14 introduced — 4 independent Docusaurus plugin instances, each with its own Stable/Development/Previous-versions dropdown — with one sitewide Stable/Development (main) toggle covering every Robotiq-maintained tool at once, cut and merged fully automatically.

Why: using the per-tool switcher surfaced that it was solving the wrong problem. Nobody wants a dropdown per tool page or an independently-tracked "Previous versions" archive per tool — the actual ask is simpler: pick Stable or Development once, sitewide, where Stable always means "every submodule at its own latest tag" and Development means "every submodule at its own live main." Collapsing to that model also directly removed the session's actual bug source: per-tool hand-written sidebar files with manual existence guards, now replaced by one shared, generated sidebar.

What changed

  • One shared versioned-tools Docusaurus instance (docusaurus.config.js) instead of 4 separate ones — path: 'versioned-tools', routeBasePath: 'docs/drivers', exactly 2 versions (current, stable). Previous versions is dropped entirely — older releases aren't archived on this site; a reader wanting one goes to that tag on GitHub directly.
  • One sitewide version dropdown, always visible on every page (not just tool pages) — the stock docsVersionDropdown navbar item already does this natively once there's one shared instance; the custom ScopedDocsVersionDropdown wrapper (built only to hide N separate per-tool dropdowns) is deleted.
  • One shared sidebar (sidebars.versioned-tools.js), generated from scripts/site-nav-tree.mjs, generalized to resolve every versioned tool's real content at once instead of one "active tool" per sidebar file.
  • scripts/cut-version.js cuts every tool's Stable together, each at its own submodule's own newest tag, in one shared Docusaurus version — not N independent per-tool cuts. scripts/auto-cut-versions.js and .github/workflows/cut-versions.yml (daily, fully automatic: checks every submodule for a new tag, cuts, validates with a full build+test, opens and merges its own PR) adjusted to match.
  • Per-page tag banners (src/theme/DocVersionBanner) name each page's own submodule's tag directly — "Use Stable (v1.0.0)" on Development, "This page reflects Stable v1.0.0" on Stable — since the dropdown label itself can no longer carry a single tag (different tools can be on different tags under one sitewide toggle).
  • New src/theme/Layout swizzle (wrap) makes the version choice sticky across visits: Docusaurus already remembers a visitor's preferred version in localStorage, but doesn't on its own redirect a page to it — this closes that gap. (Originally tried as a Root swizzle — wrong layer: useDocsPreferredVersion needs <DocsPreferredVersionContextProvider>, which only exists inside Layout's own children tree, not at Root. Crashed every page in dev with a clear error; moved it to Layout instead.)
  • Self-bootstrapping docusaurus.config.js: lastVersion/versions.stable can't reference 'stable' before it exists — a genuine chicken-and-egg hit while cutting the very first version ever from a clean slate. Now conditional on versioned-tools_versions.json actually containing it, so a brand new site bootstraps itself with no one-time manual config edit.
  • Fixed a correctness bug the shared content root surfaced: doxygen2docusaurus's apiFolderPath was shortened to a bare tail (e.g. 'API') on the old assumption that each tool had its own isolated instance root. Multiple tools now sharing one root could silently collide on the same generated doc ids and the same sidebar cache file — fixed to always use the full per-tool-prefixed path.
  • Fixed a real client-side routing bug, found via manual testing after the first version of this PR was pushed: the shared versioned-tools instance and the default docs instance both had content under /docs/drivers/*. Two plugin instances can't split ownership of one URL prefix — React Router's <Switch> commits to whichever instance's own top-level route matches first for the entire prefix and never falls through to the other if nothing matches deeper. A hard page load never showed it (the server just returns the right static file, bypassing React Router's matching entirely), only client-side navigation did — e.g. clicking through to a real default-instance page like /docs/drivers/Adaptive grippers/ or /docs/drivers/EPick/ 404'd. Fixed at the root: every product/tool page, versioned or not (Force Torque Sensor, EPick, every product's own ROS pages, product landing pages), now lives under versioned-tools/ and is served by the one shared instance — no URL changes, nothing left for the router to get wrong. scripts/generate-tools-table.js and scripts/site-nav-tree.mjs simplified accordingly (one homogeneous content tree instead of two different "which instance owns this" shapes).
  • Fixed a sidebar regression that same move introduced: docs/intro.mdx deliberately stayed on the default instance (so /docs/intro doesn't change), but a doc can only display a sidebar belonging to its own plugin instance — landing there (e.g. by clicking "Overview" from the tools sidebar) collapsed to a tiny sidebar and lost the whole tree. Fixed with a new buildOverviewSidebar() that mirrors the full tree as plain links for that one page. docs/api-stability.mdx is now reachable only contextually (the Development banner, intro's own text) instead of appearing in any sidebar.
  • Fixed two more bugs the driver-content move surfaced in scripts/cut-version.js: its pruneLegacyFolder call now runs over the whole shared versioned-tools/ tree, which started wrongly deleting Force Torque Sensor's one hand-authored non-.mdx exception (Libraries/C/_readme.md, no sync job of its own) as stale content. Generalized the backup/restore mechanism from "every .mdx" to "every git-tracked file" (via git ls-files), and added a restore-if-still-missing pass before docs:version: captures the cut's snapshot — restoring only at the end of the cut was too late.

Adding a tool now

Registering a new versioned tool is now: one external-jobs.js sync job entry, one scripts/versioned-tools.js registry entry, one leaf in site-nav-tree.mjs's SITE_TREE, one entry in sidebars.versioned-tools.js's active-items map. No new Docusaurus plugin instance, no new sidebar file, no new navbar item — see the updated checklist in docs/contribute/versioning.mdx.

Test plan

  • Fresh node scripts/cut-version.js stable cutting all 3 submodules together from a clean slate (no prior versioned-tools_versions.json) — exercised the self-bootstrapping lastVersion fix directly, and the tracked-file backup/restore fix (Force Torque Sensor's _readme.md survives the cut, live and frozen).
  • Full clean build (rm -rf .doxygen2docusaurus-staging build .docusaurus scripts/generated node_modules/.cache && npm run build) — clean, only a pre-existing unrelated upstream anchor warning.
  • npm run test:unit — 43/43 passing (site-nav-tree and cut-version test suites rewritten for the new shapes).
  • npm test smoke check passing.
  • Verified in the built output that only one top-level /docs/drivers route exists (.docusaurus/routes.js) — confirming the routing collision is actually gone, not just no-longer-triggered.
  • Verified the built /docs/intro/index.html's sidebar <aside> contains the full Software Tools tree and no longer contains "API stability policy".
  • npm start (dev mode) — the page that previously crashed with "Hook useDocsPreferredVersionContext is called outside the " now loads cleanly, on the reported page and every product/tool page.
  • Manual verification: version dropdown renders on /docs/intro (non-tool page) and /docs/drivers/EPick/ (product with no submodule at all), not just tool pages; each tool's banner shows its own correct tag on both Development and Stable.

bcastets-robotiq and others added 3 commits September 28, 2026 10:52
Replaces the by-hand checkout/sync/version/restore procedure documented
in docs/contribute/versioning.mdx with a single command per cut
(`node scripts/cut-version.js <plugin-id> stable|previous-versions`),
per explicit direction that the site's job is to render docs with no
manual intervention. Covers every step the manual procedure required —
tag discovery, submodule checkout/restore, stale-content and
stale-sidebar-cache pruning, dangling sub-page link pruning, main->tag
link rewriting, the Development-only admonition strip, the
Previous-versions signpost, and the Stable label (now read from
versioned-tools-stable.json instead of hand-typed in
docusaurus.config.js) — with best-effort cleanup so a failure partway
through never leaves Development's own live content broken.

Also fixes a latent bug this surfaced: sidebars.adaptive-grippers-cpp.js's
"Introduction guides" category linked unconditionally to a docs/index doc
id, even for a version (a previous-versions signpost, or a tag predating
the guide folder) that has no docs/ content at all — frozen into that
version's sidebar snapshot, only caught by Docusaurus's build-time
checkSidebarsDocIds, not by the cut itself. Guarded the same way the
neighboring doxygenApiCategory already was.

Validated by re-cutting all three versioned tools' stable and
previous-versions end to end and confirming a clean npm run build, with
only pre-existing, unrelated diffs (a stray leftover _readme.md under
each tool's previous-versions snapshot, plus a capitalization/line-wrap
fix in the signpost text).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Closes the remaining manual step from scripts/cut-version.js: someone
still had to remember to run it after a release. cut-versions.yml runs
daily, and scripts/auto-cut-versions.js checks every tool already
tracking a Stable tag for a newer one upstream — if there is one, it's
itself the signal to cut (every tool here only ever tags real releases,
so no beta/pre-release filtering is needed yet; that's a deliberate,
easy-to-add-later follow-up once it is). Cuts run through the same
scripts/cut-version.js as a manual cut, get validated with a full build
+ test before anything is pushed, and land as a PR (opened, or updated
in place on a later run) rather than merging unattended.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
"A human still merges" was still a manual step against the "no manual
intervention" goal — the workflow's own build+test already validates
the exact commit being merged, so there's nothing left for a human
approval to add. Still goes through a PR (for the commit/PR history
record), but the workflow opens and merges it in the same run now.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@bcastets-robotiq

Copy link
Copy Markdown
Collaborator Author

The way to handle the current and stable version is going ot be change. This PR is not outdated.

@bcastets-robotiq bcastets-robotiq changed the title Automate cutting Stable/Previous versions with scripts/cut-version.js Redesign documentation versioning: one sitewide Stable/Development toggle Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant