Skip to content

mesh-admin: surface in-flight handler execution (Rust + Python) (#4127) #14469

mesh-admin: surface in-flight handler execution (Rust + Python) (#4127)

mesh-admin: surface in-flight handler execution (Rust + Python) (#4127) #14469

Workflow file for this run

name: Docs
on:
push:
branches:
- 'docs/**'
pull_request:
# uncomment this to turn on scheduled deploys of main docs.
# for now, to secure the gh-pages branch, we require PRs to be accepted to
# make changes. So scheduled builds will have too much overhead of requiring accepts.
# schedule:
# - cron: '17 8 * * *' # Daily at ~8:17 AM UTC (main branch docs)
workflow_dispatch:
inputs:
version:
description: "Docs version to build and deploy (e.g. v0.4.0, main). If empty, builds dev docs without deploying."
required: false
default: ""
concurrency:
group: docs-${{ github.workflow }}-${{ github.ref == 'refs/heads/main' && github.run_number || github.ref }}
cancel-in-progress: true
jobs:
build:
name: Build Documentation
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
with:
timeout: 120
# Building docs needs the CUDA toolkit but not host-GPU access; matching
# pytorch core's pattern of CPU-only ephemeral runners for build-style
# jobs avoids the nvidia-container-cli host-driver-vs-CUDA version
# check (no g4dn-fleet AMI yet carries an NVIDIA driver that satisfies
# cuda>=13.2). Docs build at cu132 to match the wheels we ship; PR GPU
# CI runs at cu130 — see set-matrix.yaml.
runner: linux.c7i.2xlarge
docker-image: "pytorch/manylinux2_28-builder:cuda13.2"
gpu-arch-type: cpu
gpu-arch-version: ""
submodules: recursive
upload-artifact: docs
script: |
# Detect docs version from workflow input, branch name, or event type
if [[ -n "${{ inputs.version }}" ]]; then
export DOCS_VERSION="${{ inputs.version }}"
elif [[ "$GITHUB_REF" == refs/heads/docs/* ]]; then
export DOCS_VERSION="${GITHUB_REF#refs/heads/docs/}"
elif [[ "${{ github.event_name }}" == "schedule" ]]; then
export DOCS_VERSION="main"
else
export DOCS_VERSION="dev"
fi
echo "Building docs for version: $DOCS_VERSION"
# Source common setup functions
source scripts/common-setup.sh
# Setup build environment (conda + system deps + rust + build deps)
# docs build will use 3.13
setup_build_environment 3.13
# Install PyTorch with CUDA support (matching build-cuda.yml)
pip install --pre torch --extra-index-url https://download.pytorch.org/whl/nightly/cu132
# Setup Tensor Engine
setup_tensor_engine
# Setup Python dependencies
python -m pip install --upgrade pip
pip install -r build-requirements.txt
pip install -r docs/requirements.txt
# Set environment variables for CUDA build
export USE_CUDA=1
export USE_TENSOR_ENGINE=1
export RUSTFLAGS="-Zthreads=16 ${RUSTFLAGS:-}"
export _GLIBCXX_USE_CXX11_ABI=1
# Build Monarch completely for documentation - use dedicated script
./scripts/build_monarch_for_docs.sh
# Generate documentation for all workspace crates
cargo doc --workspace --no-deps
# Prepare documentation structure for Sphinx and final output
mkdir -p docs/source/target
cp -r target/doc docs/source/target/
# Build Sphinx documentation with error detection
echo "Building Sphinx documentation..."
cd docs
make clean
make html SPHINXOPTS="-v --keep-going"
cd ..
# Copy Rust API docs to final location
mkdir -p docs/build/html/rust-api
cp -r target/doc/* docs/build/html/rust-api/
# Copy documentation to artifact directory
mkdir -p ${RUNNER_ARTIFACT_DIR}
cp -r docs/build/html ${RUNNER_ARTIFACT_DIR}/docs-html
deploy:
needs: build
if: inputs.version != '' || github.event_name == 'schedule' || startsWith(github.ref, 'refs/heads/docs/')
permissions:
contents: write
runs-on: ubuntu-latest
# Add an environment for permissions checks to push.
environment: github-pages
steps:
- name: Checkout gh-pages branch
uses: actions/checkout@v4
with:
ref: gh-pages
fetch-depth: 1
continue-on-error: true
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: docs
path: artifact
- name: Determine version
id: version
run: |
if [[ -n "${{ inputs.version }}" ]]; then
VERSION="${{ inputs.version }}"
elif [[ "${{ github.event_name }}" == "schedule" ]]; then
VERSION="main"
else
VERSION="${GITHUB_REF#refs/heads/docs/}"
fi
# Skip deploy for pre-release versions (e.g. v0.4.0rc1, v1.0.0beta2)
if [[ "$VERSION" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+[a-zA-Z] ]]; then
echo "::notice::Skipping deploy for pre-release version: $VERSION"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Deploy versioned docs and update metadata
if: steps.version.outputs.skip != 'true'
run: |
export VERSION="${{ steps.version.outputs.version }}"
export SITE_URL="https://meta-pytorch.org/monarch"
# Update versions.json and handle stable directory management.
# For the latest stable release, docs are served from "stable/" instead
# of the version key. Since GitHub Pages doesn't support symlinks, we
# physically rename directories when the stable version changes.
python3 - <<'PYEOF'
import json
import os
import re
import shutil
version = os.environ["VERSION"]
site_url = os.environ["SITE_URL"]
versions_path = "versions.json"
stable_version_path = "stable-version.txt"
# Load existing versions or start fresh
if os.path.exists(versions_path):
with open(versions_path) as f:
versions = json.load(f)
else:
versions = []
# Remove existing entry for this version
versions = [v for v in versions if v["version"] != version]
# Add new entry (URL will be set below based on whether it's the latest stable)
versions.append({
"name": version,
"version": version,
"url": "", # placeholder, set below
})
# Sort by semver descending (versions like v0.4.0)
def sort_key(v):
m = re.match(r"v?(\d+)\.(\d+)\.(\d+)(.*)", v["version"])
if m:
major, minor, patch = int(m.group(1)), int(m.group(2)), int(m.group(3))
# Stable releases (no suffix) sort above pre-releases
is_stable = 1 if m.group(4) == "" else 0
return (1, major, minor, patch, is_stable)
return (0, 0, 0, 0, 0)
versions.sort(key=sort_key, reverse=True)
def is_stable_release(v):
return bool(re.match(r"v?\d+\.\d+\.\d+$", v["version"]))
# Find the latest stable release (pre-releases are never "stable")
latest_stable_version = next(
(v["version"] for v in versions if is_stable_release(v)),
None,
)
# Read which version currently occupies the "stable" directory
prev_stable_version = None
if os.path.exists(stable_version_path):
prev_stable_version = open(stable_version_path).read().strip() or None
is_new_version_latest_stable = (version == latest_stable_version)
# --- Directory management ---
if is_new_version_latest_stable:
# If a different version currently owns "stable/", rename it back
# to its version key so it remains accessible.
if prev_stable_version and prev_stable_version != version:
stable_dir = "stable"
old_version_dir = f"{prev_stable_version}"
if os.path.isdir(stable_dir) and not os.path.exists(old_version_dir):
shutil.move(stable_dir, old_version_dir)
# Deploy new docs into "stable/"
dest = "stable"
if os.path.isdir(dest):
shutil.rmtree(dest)
shutil.copytree("artifact/docs-html", dest)
# Record which version now owns "stable/"
with open(stable_version_path, "w") as f:
f.write(version + "\n")
else:
# Non-latest-stable version: deploy to its own directory
dest = f"{version}"
if os.path.isdir(dest):
shutil.rmtree(dest)
shutil.copytree("artifact/docs-html", dest)
# --- Set URLs and labels ---
for v in versions:
if v["version"] == latest_stable_version:
v["name"] = f"{v['version']} (stable)"
v["url"] = f"{site_url}/stable/"
v["preferred"] = True
elif v["version"] == "main":
v["name"] = "main"
v["url"] = f"{site_url}/main/"
v.pop("preferred", None)
else:
v["name"] = v["version"]
v["url"] = f"{site_url}/{v['version']}/"
v.pop("preferred", None)
with open(versions_path, "w") as f:
json.dump(versions, f, indent=2)
f.write("\n")
PYEOF
# Generate root index.html redirect to stable
cat > index.html <<HTMLEOF
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Redirecting to Monarch docs</title>
<meta http-equiv="refresh" content="0; url=stable/">
<link rel="canonical" href="${SITE_URL}/stable/">
</head>
<body>
<p>Redirecting to <a href="stable/">Monarch stable documentation</a>...</p>
</body>
</html>
HTMLEOF
# Add .nojekyll to prevent Jekyll processing
touch .nojekyll
- name: Push to gh-pages
if: steps.version.outputs.skip != 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -A
git diff --cached --quiet && echo "No changes to deploy" && exit 0
git commit -m "Deploy docs for ${{ steps.version.outputs.version }}"
git push origin gh-pages