Skip to content

Add versioned documentation (litellm 1.79.0 → 1.87.1)#305

Open
yuneng-berri wants to merge 14 commits into
mainfrom
claude/sweet-einstein-khan4
Open

Add versioned documentation (litellm 1.79.0 → 1.87.1)#305
yuneng-berri wants to merge 14 commits into
mainfrom
claude/sweet-einstein-khan4

Conversation

@yuneng-berri

Copy link
Copy Markdown
Contributor

Why

Today the docs have no versioning, so a user on, say, litellm==1.82.0 can't tell what's changed between their version and the latest — a frequent source of confusion. This adds per-pip-release Docusaurus versioning, backfilled from the git history preserved through the docs migration.

What's included

  • 73 version snapshots — every final X.Y.Z pip release from 1.79.0 (2025-10-26) → 1.87.1, each reconstructed from the docs as they existed at that release's commit. (.dev/rc/post builds excluded — not prod install targets.)
  • versioning/ tooling (reproducible, idempotent): build_manifest.py (maps each release → docs commit by PyPI publish date), generate_versions.sh, plus helpers for image/sidebar consistency.
  • Version dropdown + /versions page, an "unreleased" banner on main and "unmaintained" banner on old versions, and noindex + canonical-to-latest on archived versions so they don't dilute SEO/search.

Build architecture (the important part)

Docusaurus re-renders every version on every build, but the snapshots are frozen. Rebuilding 73 versions on each PR blew past Vercel's 45-min limit (and OOM'd at 8 GB). So the build is split — the merge-gating build never touches the snapshots:

Build Renders Where Time
Vercel (every PR + prod) current docs only docs.litellm.ai ~5 min here / ~10–12 min on Vercel
CI (.github/workflows/build-docs-archive.yml) all 73 versions GitHub Pages off the merge path, no 45-min cap; runs only when versions change

Controlled by DOCS_VERSIONS_BUILD_LIMIT (current default · all · <N>). Memory was solved by enabling the rspack bundler; a graceful-fs preload bounds file-descriptor concurrency for the many-version archive build.

Repo size: the 73 snapshots add ~856 MB to the working tree but ~0 to the git pack — their blobs are identical to existing history, so git dedups them.

⚙️ Setup required to go live (one-time)

  1. Enable GitHub Pages (Settings → Pages → Source: GitHub Actions) so build-docs-archive.yml can publish the archive.
  2. On Vercel, set DOCS_ARCHIVE_URL to the archive base (e.g. https://berriai.github.io/litellm-docs) so the dropdown//versions links resolve. The Vercel build stays current-only automatically — nothing else to change.
  3. (Optional) Add a Vercel rewrite to serve old versions under docs.litellm.ai/docs/<version>/ instead of cross-origin.

Full details, the version→commit mapping caveat, and how to add future versions are in versioning/README.md.

Validation

  • Current-only build (Vercel path): exit 0, ~5 min, 0 version dirs. ✅
  • Full 73-version archive build (rspack + 12 GB heap, CI path): validated end-to-end (see latest commit/notes).
  • All 73 snapshots load without sidebar/module/EMFILE errors.

Not included (deliberately deferred)

  • Auto-cutting a doc version on each future pip release (manual runbook documented for now).
  • release_notes/ and blog/ remain global (unversioned), as intended.

https://claude.ai/code/session_01WS4DCjMGq4TdxuecNEc9Jc


Generated by Claude Code

claude added 9 commits June 5, 2026 02:58
…sions)

Implements Docusaurus versioning for litellm-docs:
- versioning/build_manifest.py: maps each final pip release (>=1.79.0) to the
  docs-repo commit current at its PyPI publish time (deterministic, reproducible)
- versioning/generate_versions.sh: idempotent backfill that snapshots historical
  docs/ + sidebars.js per release via 'docusaurus docs:version'
- docusaurus.config.js: lastVersion=newest release at /docs/, current tree as
  'main' at /docs/main/, version dropdown + 'All versions' link; degrades
  gracefully when no versions are generated
- plugins/versioned-seo: post-build noindex + canonical-to-latest on all
  non-latest pages (avoids duplicate-content dilution, scopes search to latest)
- src/pages/versions.js: /versions listing with live version data + release dates
- versioning/README.md: methodology, date-mapping caveat, regen instructions

Generated versioned_docs/ snapshots are committed separately.
Historical docs reference repo-root images relatively (../../img/foo.png), which
break inside versioned_docs/version-X/ (one level deeper than docs/). Expose
versioned_docs/img as a symlink to ../img so all still-present images resolve
across every version, and add fill_missing_images.py to restore images removed
from img/ since (referenced by old snapshots). Restores enterprise_vs_oss.png.
Generated via versioning/generate_versions.sh: one Docusaurus version per final
pip release from 1.79.0 (2025-10-26) through 1.87.1, each snapshotting docs/ +
sidebars.js from the release's mapped source commit.

- versioned_docs/version-*/  : 73 doc snapshots
- versioned_sidebars/         : per-version sidebars
- versions.json               : version list (newest first), drives lastVersion
- versioned_docs/{img,src,static}: symlinks to repo-root siblings so escaping
  relative refs resolve across all versions
- versioning/link_escaping_siblings.py: data-driven symlink generator

Git stores these blobs once (identical to existing history), so pack size is
effectively unchanged despite ~856MB of working-tree markdown.
Loading 73 doc versions concurrently exhausts the file-descriptor ulimit
(EMFILE) on hosts with low limits. Preload graceful-fs + a fs.promises semaphore
via NODE_OPTIONS in the build script so concurrent file ops stay well under the
limit regardless of host ulimit. Adds graceful-fs as an explicit dependency.
- graceful-fs-preload: also wrap graceful-fs's own exports (fs-extra uses
  require('graceful-fs') directly, bypassing core fs), with a concurrency
  semaphore on read/stat/readdir across callback + promises APIs. This bounds
  open FDs during parallel multi-version loading, fixing EMFILE.
- sanitize_sidebars.py: remove versioned-sidebar references to doc ids absent
  from a snapshot (transient historical states where sidebars.js was ahead of
  docs/), which Docusaurus otherwise rejects. Wired into generate_versions.sh.
Building all 73 versions needs >8GB heap and 30+ min, exceeding a default Vercel
builder. Default to building the latest 20 released versions (+ main) via
onlyIncludeVersions so deploys stay fast/light on standard hosting; all 73
snapshots remain committed. Set DOCS_VERSIONS_BUILD_LIMIT=all (or a number) on a
larger builder to publish more. The /versions page notes when older releases are
archived rather than built.
Webpack OOMs (>8GB heap) bundling many doc versions, even ~20. Switch to the
Rust-based rspack bundler (via @docusaurus/faster experimental_faster) which uses
a fraction of the memory, making the versioned build feasible on standard hosts.
fs-extra probes fs.realpath.native; the semaphore wrapper dropped it, triggering
a 'is fs being monkey-patched?' warning. Copy original own-properties onto the
wrapper.
Docusaurus re-renders every frozen version on every build, blowing Vercel's
45-min merge gate. Decouple:
- Default build (Vercel, every PR + prod) now renders CURRENT docs only — fast.
- DOCS_VERSIONS_BUILD_LIMIT=all builds the full archive; new GitHub Actions
  workflow build-docs-archive.yml does this off the merge path (no 45-min cap)
  and deploys to GitHub Pages, rebuilding only when versions change.
- Custom manifest-driven version dropdown + /versions page link frozen versions
  to the archive via DOCS_ARCHIVE_URL.
- url/baseUrl overridable; archive build sets noIndex + canonical to the live
  site so it doesn't compete in search.
See versioning/README.md for setup.
@vercel

vercel Bot commented Jun 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Jun 5, 2026 9:57pm

Request Review

The 73 version snapshots (48k files, ~12M lines) don't belong in the repo — they
are derived artifacts. Untrack versioned_docs/, versioned_sidebars/, versions.json
and gitignore them; the archive workflow now regenerates them from git history
(fetch-depth: 0 + generate_versions.sh) before the full build. The committed
manifest.json drives the version dropdown / Versions page, so the fast Vercel
build (which has no snapshots on disk) still shows the version picker, linking
frozen versions to the archive. Shrinks the PR diff to the versioning machinery.
claude added 2 commits June 5, 2026 20:57
Per project decision, version only STABLE releases from 1.83.x up (1.83.x line
uses -stable tags -> 1.83.10-stable labels; 1.84.0+ are semver finals) plus the
latest rc. That's ~23 versions, small enough to build directly on Vercel — so
the GitHub Pages archive + current-only split are removed.

- build_manifest.py: selects the stable set + latest rc, maps each to a commit.
- prepare-snapshots.sh: npm prebuild hook regenerates snapshots from git history
  at build time (deepens history; degrades to current-only if unavailable), so
  the 48k snapshot files are never committed.
- config: latest STABLE is the default at /docs/ (not the rc); rc + main get
  'unreleased' banners; native version dropdown.
- /versions: lists stable + rc sections from the manifest.
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.

2 participants