Add documentation version switcher (dev vs stable)#497
Add documentation version switcher (dev vs stable)#497raphaelvallat wants to merge 2 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a documentation “dev vs stable” version switcher and updates GitHub Pages deployment so unreleased changes on main are published under /dev/ while release docs are published under /stable/, with the site root redirecting to stable.
Changes:
- Add
docs/switcher.jsonand wire it intopydata_sphinx_theme’s version switcher viadocs/conf.py(including a dev-docs announcement banner). - Rework dev docs deployment to publish under
dev/and deploy a root redirect +switcher.json. - Add a new stable docs deployment workflow intended to run on GitHub Releases and publish under
stable/.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/switcher.json | Adds the version list consumed by the theme’s version switcher. |
| docs/conf.py | Adds DOC_VERSION-driven switcher selection + dev announcement banner; exposes switcher.json in built HTML. |
| docs/index.rst | Updates Binder link to use the main branch. |
| README.rst | Updates Binder link to use the main branch. |
| .github/workflows/deploy_doc.yml | Deploys dev docs to dev/ and also deploys root redirect + switcher.json. |
| .github/workflows/deploy_stable_doc.yml | New workflow to build/deploy stable docs to stable/ and update root redirect + switcher.json. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| release = pingouin.__version__ | ||
|
|
||
| doc_version = os.environ.get("DOC_VERSION") # "dev", "stable", or None (local build) | ||
| version_match = "dev" if doc_version == "dev" else version |
There was a problem hiding this comment.
When DOC_VERSION is unset (local builds and the existing doc.yml CI job), version_match is set to pingouin.__version__. On main this is typically a dev version string that won’t match any entry in switcher.json, so the version switcher will likely highlight the preferred (stable) entry even for dev docs. If the intent is to default to dev in these cases, set version_match to "dev" when DOC_VERSION is missing and the codebase version indicates a dev build (or make CI set DOC_VERSION=dev).
| version_match = "dev" if doc_version == "dev" else version | |
| if doc_version is None: | |
| # When building from a dev version locally/without DOC_VERSION, default to "dev" | |
| version_match = "dev" if "dev" in version else version | |
| elif doc_version == "dev": | |
| version_match = "dev" | |
| else: | |
| version_match = version |
| - name: Update switcher.json with current stable version | ||
| run: | | ||
| python -c " | ||
| import json, pingouin | ||
| stable_version = pingouin.__version__ | ||
| switcher = [ | ||
| { | ||
| 'name': 'dev (main branch)', | ||
| 'version': 'dev', | ||
| 'url': 'https://pingouin-stats.org/dev/' | ||
| }, | ||
| { | ||
| 'name': f'{stable_version} (stable)', | ||
| 'version': stable_version, | ||
| 'url': 'https://pingouin-stats.org/stable/', | ||
| 'preferred': True | ||
| } | ||
| ] | ||
| with open('docs/switcher.json', 'w') as f: | ||
| json.dump(switcher, f, indent=2) | ||
| f.write('\n') | ||
| print(f'Updated switcher.json with stable version {stable_version}') | ||
| " |
There was a problem hiding this comment.
The python -c "..." block embeds leading indentation spaces in the Python code (because of YAML indentation), which will raise IndentationError: unexpected indent at runtime. Use a heredoc (python - <<'PY' ... PY) or make the -c argument a single line without leading spaces so the workflow can actually update docs/switcher.json.
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
| - name: Setup Python | ||
| uses: actions/setup-python@v6 | ||
| with: | ||
| python-version-file: "pyproject.toml" |
There was a problem hiding this comment.
workflow_dispatch runs will check out the selected branch (typically main), so this workflow can end up publishing “stable” docs built from unreleased code and a non-stable pingouin.__version__. To ensure stable docs always match a release, make the checkout use a release tag/commit (e.g., checkout ${{ github.event.release.tag_name }} on release events and require an explicit tag/ref input for manual runs, then checkout that).
| - name: Create root redirect and switcher | ||
| run: | | ||
| mkdir -p /tmp/root-pages | ||
| cp docs/switcher.json /tmp/root-pages/switcher.json | ||
| cat > /tmp/root-pages/index.html << 'EOF' |
There was a problem hiding this comment.
This dev-docs workflow deploys docs/switcher.json to the site root on every push to main. After a release, the stable-docs workflow will deploy an updated switcher with the new stable version, but the next dev deploy will overwrite it with whatever is committed on main (likely stale). Consider having only the stable-docs workflow update root switcher.json, or generate the stable version dynamically in this workflow (e.g., from the latest GitHub Release/PyPI) before deploying it.
Add documentation version switcher (dev vs stable)
Summary
The docs were previously re-deployed on every push to
main, meaning users could read unreleased API changes. This PR adds a version toggle identical to the one used by NumPy, SciPy, and other scientific Python libraries, letting users switch between the development (main branch) and latest stable (PyPI release) documentation.Changes
docs/switcher.json— New JSON file consumed by thepydata_sphinx_themeversion-switcher component. Listsdevand0.6.0 (stable)with their respective URLs. Auto-regenerated with the correct version number on every stable release.docs/conf.py— Reads aDOC_VERSIONenvironment variable ("dev"or"stable") to:version_match)switcher.jsonat the root of the HTML output viahtml_extra_path.github/workflows/deploy_doc.yml— Reworked dev-docs deployment:actions/deploy-pages(whole-site replace) toJamesIves/github-pages-deploy-action(subdirectory-aware)pingouin-stats.org/dev/switcher.jsonto the site root (withclean: falseto preserve other subdirectories).github/workflows/deploy_stable_doc.yml— New workflow triggered on every published GitHub Release (and manually viaworkflow_dispatch):switcher.jsonwith the new stable version numberpingouin-stats.org/stable/switcher.jsonResult
pingouin-stats.org/stable/pingouin-stats.org/stable/pingouin-stats.org/dev/pingouin-stats.org/switcher.jsonRequired one-time setup after merge
Important
"GitHub Actions"to"Deploy from a branch"→gh-pages//(root)workflow_dispatch) to populatestable/for the first timeTest plan
gh-pagesbranchdev/is populated atpingouin-stats.org/dev/with the dev banner visiblestable/is populated and the switcher dropdown shows both versions with the correct one highlightedswitcher.jsonis updated automatically with the new version number