GitHub Actions Workflows#
This page documents QuantEcon’s GitHub Actions workflow configurations.
Documentation Preview Workflow#
The QuantEcon.manual repository includes an automated CI workflow that provides documentation previews for Pull Requests.
How It Works#
When you create or update a Pull Request, the ci.yml workflow automatically:
Builds the documentation using Jupyter Book with the same environment as production
Deploys a preview to
https://manual.quantecon.org/pr-{number}/Comments on the PR with a direct link to the preview
Updates the preview when you push new commits to the PR
Cleans up the preview directory when the PR is closed or merged
The cleanup process includes:
Automatic Detection: Distinguishes between merged and closed PRs
Robust Removal: Safely removes preview directories with retry logic
Verification: Confirms successful cleanup completion
Error Handling: Gracefully handles cases where directories are already removed
Benefits#
Visual Feedback: See exactly how your changes will look before merging
Review Process: Reviewers can easily access the rendered documentation
Quality Assurance: Catch formatting issues and broken links early
No Manual Setup: Everything is automated - just create a PR
Preview URLs#
Previews are accessible at:
Primary:
https://manual.quantecon.org/pr-{number}/Fallback:
https://quantecon.github.io/QuantEcon.manual/pr-{number}/
Where {number} is your PR number (e.g., pr-45 for Pull Request #45).
Workflow Configuration#
The CI workflow is defined in .github/workflows/ci.yml and includes:
Environment Setup: Uses the same conda environment as production (
environment.yml)Build Process: Runs
jb build manual --path-output ./Safe Deployment: Uses subdirectory deployment to avoid conflicts with the main site
Smart Comments: Creates new preview comments for each build with commit SHA
Robust Cleanup: Removes preview directories when PRs are closed with:
Automatic detection of merged vs. closed PRs
Retry logic for push operations
Verification of successful cleanup
Graceful handling of edge cases
Note
The preview workflow is completely safe and won’t interfere with the main documentation site. It uses subdirectory deployment and preserves all existing content and configuration.
When the main branch publishes to gh-pages, the publish.yml workflow is configured with
keep_files: true to preserve existing PR preview directories, so active previews remain
accessible even after main branch deployments.
The cleanup mechanism has been enhanced to ensure previews are reliably removed when PRs are closed or merged, preventing accumulation of old preview directories.
GPU-Enabled Workflows#
For lecture repositories that require GPU computation, QuantEcon uses specialized workflows.
Our GPU based workflows are now built using RunsOn
Build Images#
There are two types of workflows:
Using our own custom ami that is preloaded with CUDA, CUDANN, and LaTeX
Using the ami provided by Runs On that includes Docker support. This is used by
collab.ymlworkflows or any containerized workflow.
The benefit of using our own custom AMI is that we can choose CUDA, CUDANN versions and ensure we are able to use the latest versions to support lectures on JAX and GPU computing.
It is best to install only system wide software such as GPU frameworks, tool-kits and drivers.
When setting up a custom AMI we should install the NVIDIA support:
using the latest versions and then LaTeX
sudo apt-get -qq update
sudo apt-get install -y \
texlive-latex-recommended \
texlive-latex-extra \
texlive-fonts-recommended \
texlive-fonts-extra \
texlive-xetex \
latexmk \
xindy \
dvipng \
cm-super
Leave anaconda and local installs to the GitHub actions workflow.
While this incurs a small setup cost in terms of execution time, it provides flexibility in upgrading the python / anaconda software stack.
In addition to anaconda, you should install GPU-enabled Python packages in the GitHub Action as a setup step.
The current standard across the GPU lecture repositories (e.g. lecture-jax, lecture-python-programming) is:
- name: Install JAX and Numpyro
shell: bash -l {0}
run: |
pip install -U "jax[cuda13]"
pip install numpyro
python scripts/test-jax-install.py
Note
The jax[cuda13] selector installs JAX against the CUDA 13 wheels and is matched to the CUDA / driver
version baked into the custom AMI (see below). Bump this selector when the AMI is rebuilt against a newer
CUDA release.
If a lecture also requires PyTorch / Pyro, add them as a separate install step:
- name: Install PyTorch and Pyro
shell: bash -l {0}
run: |
pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu130
pip install pyro-ppl
Warning
PyTorch typically lags JAX in terms of compatibility with NVIDIA drivers. It is best to install the nightly
versions to ensure the best compatibility, and to match the CUDA index URL (cu130, cu13x, …) to the
CUDA version on the AMI.
You can check the latest on the PyTorch site with the installation table
Standard Lecture Workflows#
A typical QuantEcon lecture repository (e.g. lecture-python.myst)
ships the following workflows in .github/workflows/:
Workflow |
Trigger |
Purpose |
|---|---|---|
|
Pull requests |
Build the lecture and generate a preview for review |
|
Push to |
Execute the full project and save the |
|
Push of a |
Build and deploy the live site (see Publishing Lectures) |
|
Schedule / manual |
Validate internal and external links |
|
Manual / containerized |
Build inside a Docker container on a RunsOn runner (used for |
PR and publish builds restore the _build artifact produced by cache.yml, so unchanged lectures are
not re-executed. See Setup Cache for GitHub Actions for the configuration detail.
QuantEcon Actions — Reusable Build & Publish Library#
Note
This is the target architecture for QuantEcon lecture CI/CD. New repositories should adopt it and existing repositories are being migrated over time. See the lecture deployment table for the current per-repo status.
The QuantEcon/actions repository provides a set of reusable composite
GitHub Actions that standardise and speed up lecture builds. Rather than each repository carrying a long,
hand-maintained publish.yml, the build is composed from small, independently versioned actions (current
release v0.6.0). lecture-dp is the reference implementation.
The design rests on three pillars:
Containerised environment — a pre-built Docker image
ghcr.io/quantecon/quantecon-build:latest(Ubuntu 24.04 + TexLive + Miniconda + Anaconda 2025.12 base + Jupyter Book tooling), rebuilt weekly and published to the GitHub Container Registry. This removes the 2–3 minute LaTeX install from every run. The container is built from thecontainers/definitions in the same repo.Modular actions — small composable steps with clear responsibilities (see table below).
Two-layer caching — the container image (environment) plus the Jupyter
_buildcache (execution), so only changed lectures are re-executed.
Available actions#
Action |
Role |
|---|---|
|
Flexible environment setup (optional Conda / LaTeX / ML libs); container-aware |
|
Build Jupyter Book (HTML, PDF, notebooks) with unified error handling and asset assembly |
|
Weekly execution-cache generation on |
|
Read-only cache restore for PR builds (never writes, so PRs can’t corrupt the cache) |
|
Deploy to GitHub Pages using native artifact deployment (no |
|
Deploy PR previews to Netlify with smart PR comments |
|
Deploy PR previews to Cloudflare Pages ( |
Important
publish-gh-pages deploys via the native GitHub Pages artifact pipeline (actions/deploy-pages), so
repositories on this path do not have a gh-pages branch. The local ghp-import fallback documented in
Building Locally and Push to GitHub Pages does not apply to them.
Minimal publish workflow#
A migrated publish.yml reduces to roughly:
jobs:
build:
runs-on: ubuntu-latest
container:
image: ghcr.io/quantecon/quantecon-build:latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- uses: quantecon/actions/restore-jupyter-cache@v0.6.0
- uses: quantecon/actions/build-lectures@v0.6.0
id: build
with:
builder: 'html'
deploy:
needs: build
runs-on: ubuntu-latest
permissions: { contents: write, pages: write, id-token: write }
steps:
- uses: quantecon/actions/publish-gh-pages@v0.6.0
with:
build-dir: _build/html
github-token: ${{ secrets.GITHUB_TOKEN }}
See also
The migration guide and
architecture overview in the
quantecon/actions repository document the full set of inputs and the step-by-step process for converting
a repository.
Repository Backup Workflow#
QuantEcon uses an automated backup system to protect repositories against data loss. The backup workflow is managed from the workflow-backups repository.
Overview#
The backup workflow:
Runs weekly (Sunday at 2 AM UTC) via GitHub Actions
Creates mirror backups of selected repositories (all branches, tags, and history)
Stores backups securely in AWS S3
Generates reports on backup status and storage usage
Repository Selection#
Repositories are selected for backup using pattern-based matching in config.yml:
backup:
enabled: true
organization: "QuantEcon"
# Exact repository names
repositories:
- "QuantEcon.py"
- "QuantEcon.jl"
# Regex patterns for matching multiple repos
patterns:
- "lecture-.*" # All lecture repositories
- "quantecon-.*" # All quantecon packages
s3:
bucket: "your-backup-bucket"
prefix: "backups/"
Authentication Setup#
The backup workflow requires two types of authentication:
AWS Authentication (OIDC)#
AWS access uses OIDC authentication (no long-lived credentials):
An IAM Identity Provider is configured for GitHub Actions
An IAM Role with S3 permissions is created
The role ARN is stored as a repository secret:
AWS_ROLE_ARN
GitHub Token for Private Repositories#
Important
Fine-Grained Personal Access Token (PAT) Setup
For backing up private repositories, a Fine-Grained PAT must be created with READ-ONLY permissions:
Go to GitHub Settings → Developer settings → Personal access tokens → Fine-grained tokens
Click “Generate new token”
Set the following:
Token name:
quantecon-backup-readonly(or similar descriptive name)Expiration: Set an appropriate expiration (recommend 90 days or custom)
Resource owner: Select the QuantEcon organization
Repository access: Select “All repositories” or specific repositories to backup
Permissions: Set Repository permissions to:
Contents: Read-only
Metadata: Read-only (automatically selected)
All other permissions should remain at “No access”
Generate the token and store it as the
REPO_BACKUP_TOKENsecret in the workflow-backups repository
Security Note: The token should have minimal READ-ONLY permissions. Never grant write access for backup operations.
For public repositories only, the default GITHUB_TOKEN works automatically with no additional setup.
Backup Storage Structure#
Backups are stored in S3 with the following structure:
s3://bucket-name/
├── lecture-python/
│ ├── lecture-python-20251127.tar.gz
│ ├── lecture-python-20251120.tar.gz
│ └── lecture-python-20251113.tar.gz
└── QuantEcon.py/
└── QuantEcon.py-20251127.tar.gz
Each backup is a complete git mirror including all branches, tags, and full commit history.
Restoring from Backup#
To restore a repository from backup:
# 1. Download the backup from S3
aws s3 cp s3://bucket-name/repo-name/repo-name-20251127.tar.gz .
# 2. Extract the archive (contains a bare git mirror)
tar -xzf repo-name-20251127.tar.gz
# 3. Clone from the bare repo to create a working repository
git clone repo-name restored-repo
# 4. Verify the restoration
cd restored-repo
git branch -a # View all branches
git tag # View all tags
Manual Trigger#
The backup workflow can be triggered manually via GitHub Actions:
Go to the workflow-backups Actions page
Select the “Repository Backup” workflow
Click “Run workflow”
More Information#
For detailed setup instructions and configuration options, see the workflow-backups README.