Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
236 changes: 236 additions & 0 deletions .github/workflows/docs-migration.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

name: Docs Migration

on:
workflow_dispatch:
inputs:
dry_run:
description: "Dry run (build but don't deploy)"
required: false
default: "false"
type: choice
options:
- "false"
- "true"

permissions:
contents: read

jobs:
build-version:
name: Build ${{ matrix.ref }}
runs-on: ubuntu-latest
strategy:
matrix:
ref:
- main
- develop
- release/2.1.0
- release/2.2.0
- release/2.3.0
- v1.0.0
- v1.1.0
- v1.2.0
- v1.3.0
- v1.4.0
- v1.4.1
- v2.0.0
- v2.0.1
- v2.0.2
- v2.1.0
- v2.1.1
- v2.2.0
- v2.2.1
- v2.3.0
- v2.3.1
- v2.3.2
- v3.0.0-beta
fail-fast: false

steps:
- name: Checkout ref
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ matrix.ref }}

- name: Setup python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
architecture: x64

- name: Install dev requirements
working-directory: ./docs
run: pip install -r requirements.txt

- name: Determine slug
id: slug
env:
REF: ${{ matrix.ref }}
run: |
# For branches with slashes, replace / with -
SLUG="${REF//\//-}"
echo "slug=$SLUG" >> "$GITHUB_OUTPUT"
echo "Slug: $SLUG"

- name: Build docs
working-directory: ./docs
env:
# Set the version slug so conf.py (on branches that have it) can
# configure the theme switcher's version_match correctly.
DOCS_VERSION_SLUG: ${{ steps.slug.outputs.slug }}
# No -W flag: old versions may have warnings that are acceptable.
run: |
rm -rf "_build"
sphinx-build -b html . "_build"
Comment on lines +80 to +89

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 DOCS_VERSION_SLUG not passed to migration builds

For branches that already carry the updated conf.py (main, develop, release/2.1.0, release/2.2.0, release/2.3.0), _version_slug will fall back to the semver from the VERSION file (e.g. "3.0.0") instead of the directory slug (e.g. "main"). The pydata-sphinx-theme built-in switcher uses version_match to highlight the current version; a mismatch means no version is highlighted and users lose orientation. The regular docs.yaml sets this variable correctly:

Suggested change
- name: Build docs
working-directory: ./docs
# No -W flag: old versions may have warnings that are acceptable.
run: |
rm -rf "_build"
sphinx-build -b html . "_build"
- name: Build docs
working-directory: ./docs
env:
DOCS_VERSION_SLUG: ${{ steps.slug.outputs.slug }}
# No -W flag: old versions may have warnings that are acceptable.
run: |
rm -rf "_build"
sphinx-build -b html . "_build"


- name: Upload artifact
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: docs-${{ steps.slug.outputs.slug }}
path: ./docs/_build

deploy-all:
name: Deploy All Versions
runs-on: ubuntu-latest
needs: [build-version]
if: ${{ inputs.dry_run == 'false' }}
permissions:
contents: write

steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: |
docs/_static/version-switcher.js
docs/_redirect/index.html

- name: Download all artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: ./artifacts

- name: Assemble site
run: |
mkdir -p site

# Move each artifact into its versioned directory
for dir in artifacts/docs-*; do
SLUG="${dir#artifacts/docs-}"
echo "Assembling: $SLUG"
cp -r "$dir" "site/${SLUG}"
done

# Inject version-switcher.js into every HTML file across all versions
find site/ -name "*.html" -exec sed -i \
's|</body>|<script src="/IsaacLab/version-switcher.js"></script></body>|' {} +

# Verify injection
TOTAL=$(find site/ -name "*.html" | wc -l)
INJECTED=$(grep -rl 'version-switcher.js' site/ --include="*.html" | wc -l)
echo "Injected version-switcher.js into ${INJECTED}/${TOTAL} HTML files"
if [ "$TOTAL" -gt 0 ] && [ "$INJECTED" -eq 0 ]; then
echo "::error::version-switcher.js injection found zero matches in ${TOTAL} HTML files"
exit 1
fi

# Copy static assets to root
cp docs/_static/version-switcher.js site/version-switcher.js
cp docs/_redirect/index.html site/index.html

- name: Create stable alias
run: |
# Find the latest semver tag directory (highest version number)
LATEST_TAG=""
for dir in site/v*; do
[ -d "$dir" ] || continue
TAG="${dir#site/}"
if [ -z "$LATEST_TAG" ] || python3 -c "
import sys, re
def vt(s): return tuple(int(n) for n in re.findall(r'\d+', s))
sys.exit(0 if vt(sys.argv[1]) > vt(sys.argv[2]) else 1)
" "$TAG" "$LATEST_TAG" 2>/dev/null; then
LATEST_TAG="$TAG"
fi
done

if [ -n "$LATEST_TAG" ]; then
echo "Creating /stable/ from ${LATEST_TAG}"
cp -r "site/${LATEST_TAG}" "site/stable"
# Update root redirect to point to /stable/
cat > site/index.html << 'HTMLEOF'
<!DOCTYPE html>
<html>
<head>
<title>Redirecting to the latest Isaac Lab documentation</title>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=./stable/index.html">
<link rel="canonical" href="https://isaac-sim.github.io/IsaacLab/stable/">
</head>
<body>
<p>Redirecting to <a href="./stable/index.html">Isaac Lab documentation</a>...</p>
</body>
</html>
HTMLEOF
else
echo "No tag directories found, skipping /stable/ creation"
fi

- name: Generate versions.json
run: |
python3 << 'PYEOF'
import json, os, re, sys

versions = []
for name in sorted(os.listdir('site')):
path = os.path.join('site', name)
if not os.path.isdir(path):
continue
versions.append({
'name': name,
'version': name,
'url': '/IsaacLab/' + name + '/',
})

if not versions:
print('::error::No version directories found in site/')
sys.exit(1)

# Sort: branches first, then releases, then tags
def _version_tuple(s):
"""Extract numeric parts for semver-aware sorting."""
return tuple(int(n) for n in re.findall(r'\d+', s))

def sort_key(v):
s = v['version']
if s == 'main':
return (0, ())
elif s == 'develop':
return (1, ())
elif s.startswith('release-'):
return (2, _version_tuple(s))
else:
return (3, _version_tuple(s))

versions.sort(key=sort_key)

with open('site/versions.json', 'w') as f:
json.dump(versions, f, indent=2)
f.write('\n')

print(f'Generated versions.json with {len(versions)} entries:')
for v in versions:
print(f' {v["version"]}')
PYEOF

- name: Deploy to gh-pages
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./site
keep_files: false
Loading
Loading