Skip to content

Deploy Pages

Deploy Pages #10098

Workflow file for this run

name: Deploy Pages
on:
push:
branches: [main]
paths:
- 'web/**'
- 'projects/**/paper/pdf/**.pdf'
- '.github/workflows/pages.yml'
workflow_dispatch:
permissions:
contents: write
pages: write
id-token: write
concurrency:
group: pages-deploy
cancel-in-progress: false
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
# docs/ is a static build from web/ — it NEVER needs the projects'
# external submodules. The legacy "Deploy from branch" built-in recursed
# them and died on a broken NESTED submodule in an ingested paper's
# vendored code (PROJ-780 .../tokviz/repos/emptylist has no url in its
# .gitmodules) → every Pages deploy failed, leaving the dashboard stale.
# Artifact deploy (below) + submodules:false avoids that recursion.
submodules: false
- name: Sync web/ -> docs/
run: |
rm -rf docs
cp -R web docs
touch docs/.nojekyll
- name: Mirror paper PDFs into docs/ for same-origin inline rendering
# raw.githubusercontent.com serves PDFs with Content-Disposition:
# attachment + X-Frame-Options: deny so browsers refuse to render
# them inline. GitHub Pages serves PDFs from the same origin with a
# proper Content-Type: application/pdf, so we mirror every paper PDF
# under docs/papers/<project_id>/<filename>.pdf for the paper modal
# to embed.
#
# SIZE CAP: GitHub Pages caps a published site at 1 GB. The full PDF set
# is ~1.7 GB (dominated by a few dozen oversized 20-50 MB PDFs), which put
# the site over the limit (the deploy warned "exceeds 1 GB"). Mirror only
# PDFs <= MAX_MB so docs/ stays comfortably under 1 GB; the paper modal
# (dialog.js _renderArtifactPane) already falls back to a raw download link
# when the same-origin mirror is absent, so oversized papers still open.
run: |
set -euo pipefail
mkdir -p docs/papers
MAX_MB=15
skipped=0
# File paths are entirely under our control here (repo-checked-out
# paths only). No untrusted input is interpolated into the shell.
while IFS= read -r src; do
sz=$(stat -c%s "$src" 2>/dev/null || echo 0)
if [ "$sz" -gt $((MAX_MB * 1024 * 1024)) ]; then
echo "skip oversized ($((sz / 1024 / 1024))MB > ${MAX_MB}MB), modal falls back to download link: $src"
skipped=$((skipped + 1))
continue
fi
proj=$(echo "$src" | awk -F/ '{print $2}')
name=$(basename "$src")
mkdir -p "docs/papers/$proj"
cp "$src" "docs/papers/$proj/$name"
done < <(find projects -path 'projects/*/paper/pdf/*.pdf' -type f)
echo "mirrored PDFs total: $(du -sh docs/papers | cut -f1); skipped oversized: $skipped"
- name: Commit if changed
# The ~14 cron workflows commit to main constantly, so a bare push races
# and is rejected non-fast-forward (the dominant Deploy Pages failure).
# Use the SAME single-source-of-truth commit+push helper every other
# workflow uses (8-attempt rebase-retry with `-X theirs`, clean tree
# guaranteed via `rebase --abort`, push exit checked directly, fails loud
# on total loss). The deploy commit only touches docs/ (regenerated
# wholesale from web/), so the rebase is conflict-free.
run: |
bash scripts/ci/commit-and-push.sh "deploy: sync web/ -> docs/ for GitHub Pages [skip ci]"
# Deploy docs/ via the GitHub Actions artifact path (NOT the legacy
# deploy-from-branch built-in, which re-checks-out the repo recursively and
# dies on the broken nested submodule above). Requires the Pages source to be
# "GitHub Actions" (build_type=workflow) — set once via the repo Pages
# settings / `gh api ... -f build_type=workflow`.
- name: Configure Pages
uses: actions/configure-pages@v5
- name: Upload docs/ as the Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4