mirror of
https://github.com/harvard-edge/cs249r_book.git
synced 2026-07-21 17:57:24 -05:00
Live deploy mounts _build/ under /tinytorch/, so the meta tag's hardcoded /tinytorch/release-manifest.json resolves correctly. Visual-smoke serves _build/ at the root, so it needs the file at _build/tinytorch/release-manifest.json to match the same path. Mirror the manifest there after emit so smoke's HTTP server finds it.
273 lines
10 KiB
YAML
273 lines
10 KiB
YAML
name: '🔥 TinyTorch · 👁️ Preview (Dev)'
|
|
|
|
# =============================================================================
|
|
# TinyTorch — Dev Preview Deploy (Quarto)
|
|
# =============================================================================
|
|
#
|
|
# Builds the TinyTorch Quarto site with PDFs and slide decks, then
|
|
# deploys to the dev preview site via SSH. Gated on Validate (Dev) passing.
|
|
#
|
|
# Flow:
|
|
# 1. BUILD_PDFS — Compile guide + paper PDFs (reusable workflow)
|
|
# 2. BUILD_SITE — Quarto render + inject PDFs + download slides
|
|
# 3. DEPLOY — Push to dev preview repo via SSH
|
|
#
|
|
# Triggers:
|
|
# - workflow_run: after Validate (Dev) succeeds on dev branch
|
|
# - workflow_dispatch: manual
|
|
#
|
|
# Deploys to: harvard-edge.github.io/{DEV_REPO}/{DEV_TINYTORCH_PATH}/
|
|
# Secrets: SSH_DEPLOY_KEY
|
|
# Vars: TINYTORCH_SITE, BOOK_TOOLS, DEV_REPO, DEV_REPO_URL, DEV_TINYTORCH_PATH
|
|
#
|
|
# Related:
|
|
# - tinytorch-validate-dev.yml — Gates this workflow (must pass first)
|
|
# - tinytorch-publish-live.yml — Production deploy to mlsysbook.ai/tinytorch/
|
|
# - tinytorch-build-pdfs.yml — Reusable PDF build
|
|
#
|
|
# =============================================================================
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
workflow_run:
|
|
workflows: ["🔥 TinyTorch · ✅ Validate (Dev)"]
|
|
types: [completed]
|
|
branches: [dev]
|
|
|
|
permissions:
|
|
contents: read
|
|
actions: read
|
|
|
|
concurrency:
|
|
group: tinytorch-dev-deploy
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
# Build PDFs (only if Validate passed or manual trigger)
|
|
build-pdfs:
|
|
name: '📚 Build PDFs'
|
|
if: (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'dev') || github.event_name == 'workflow_dispatch'
|
|
uses: ./.github/workflows/tinytorch-build-pdfs.yml
|
|
|
|
# Build the site (after PDFs complete — site builds even if PDFs fail).
|
|
# Split out from deploy so the artifact gates the visual-smoke job before
|
|
# any dev preview goes live; deploy only runs if smoke is green.
|
|
build-site:
|
|
name: '🔥 Build TinyTorch Dev Site'
|
|
runs-on: ubuntu-latest
|
|
needs: [build-pdfs]
|
|
if: |
|
|
always() &&
|
|
((github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'dev') || github.event_name == 'workflow_dispatch')
|
|
permissions:
|
|
contents: read
|
|
actions: read
|
|
|
|
steps:
|
|
- name: 📥 Checkout
|
|
uses: actions/checkout@v6
|
|
|
|
- name: 🔧 Setup Quarto
|
|
uses: quarto-dev/quarto-actions/setup@v2
|
|
|
|
# Community dashboard is in-tree at tinytorch/quarto/community/
|
|
# and published via Quarto's `resources: community/**` entry; no
|
|
# pre-render copy step is needed here.
|
|
- name: 🔨 Build Quarto Site
|
|
working-directory: ${{ vars.TINYTORCH_SITE }}
|
|
run: |
|
|
quarto render
|
|
touch _build/.nojekyll
|
|
|
|
- name: 📦 Emit dev release manifest
|
|
# The footer release-pill.js fetches /tinytorch/release-manifest.json
|
|
# at runtime. Preview-dev builds still need this file to exist or
|
|
# visual-smoke catches the 404 as a console error on every page.
|
|
# We stamp a dev manifest derived from the commit SHA so the pill
|
|
# renders without erroring; the publish-live workflow stamps the
|
|
# real release manifest on its own.
|
|
run: |
|
|
set -euo pipefail
|
|
SHORT_SHA=$(git rev-parse --short HEAD)
|
|
RELEASE_ID="0.0.0-dev+${SHORT_SHA}"
|
|
|
|
RELEASE_HASH=$(python3 scripts/version/release.py compute-hash \
|
|
--paths tinytorch/modules tinytorch/quarto \
|
|
tinytorch/pyproject.toml tinytorch/MANIFEST.in \
|
|
--exclude '_build' '__pycache__' '*.pyc' '.DS_Store' \
|
|
'.ipynb_checkpoints' '*.egg-info')
|
|
|
|
python3 scripts/version/release.py emit-manifest \
|
|
--output ${{ vars.TINYTORCH_SITE }}/_build/release-manifest.json \
|
|
--project tinytorch \
|
|
--tier A \
|
|
--release-id "$RELEASE_ID" \
|
|
--release-hash "$RELEASE_HASH"
|
|
|
|
# Mirror at /tinytorch/release-manifest.json so visual-smoke, which
|
|
# serves _build/ at the root, can resolve the absolute path baked
|
|
# into the page meta tag. Live deploy mounts _build/ under
|
|
# /tinytorch/, so the file ends up in the right place either way.
|
|
mkdir -p ${{ vars.TINYTORCH_SITE }}/_build/tinytorch
|
|
cp ${{ vars.TINYTORCH_SITE }}/_build/release-manifest.json \
|
|
${{ vars.TINYTORCH_SITE }}/_build/tinytorch/release-manifest.json
|
|
|
|
echo "✅ Dev manifest written"
|
|
cat ${{ vars.TINYTORCH_SITE }}/_build/release-manifest.json
|
|
|
|
- name: 📥 Download PDF Guide
|
|
uses: actions/download-artifact@v8
|
|
continue-on-error: true
|
|
with:
|
|
name: TinyTorch-Guide
|
|
path: ./pdf-artifacts/guide
|
|
|
|
- name: 📥 Download PDF Paper
|
|
uses: actions/download-artifact@v8
|
|
continue-on-error: true
|
|
with:
|
|
name: TinyTorch-Paper
|
|
path: ./pdf-artifacts/paper
|
|
|
|
- name: 📁 Inject PDFs into site
|
|
run: |
|
|
echo "📁 Injecting PDFs into built site..."
|
|
mkdir -p ${{ vars.TINYTORCH_SITE }}/_build/assets/downloads
|
|
|
|
if [ -f ./pdf-artifacts/guide/TinyTorch-Guide.pdf ]; then
|
|
cp ./pdf-artifacts/guide/TinyTorch-Guide.pdf ${{ vars.TINYTORCH_SITE }}/_build/assets/downloads/TinyTorch-Guide.pdf
|
|
echo "✅ Injected TinyTorch-Guide.pdf"
|
|
else
|
|
echo "⚠️ Guide PDF not found"
|
|
fi
|
|
|
|
if [ -f ./pdf-artifacts/paper/paper.pdf ]; then
|
|
cp ./pdf-artifacts/paper/paper.pdf ${{ vars.TINYTORCH_SITE }}/_build/assets/downloads/TinyTorch-Paper.pdf
|
|
echo "✅ Injected TinyTorch-Paper.pdf"
|
|
else
|
|
echo "⚠️ Paper PDF not found"
|
|
fi
|
|
|
|
echo ""
|
|
echo "📦 Downloads folder contents:"
|
|
ls -la ${{ vars.TINYTORCH_SITE }}/_build/assets/downloads/ || echo "No downloads folder"
|
|
|
|
- name: 📊 Download slide decks from release
|
|
continue-on-error: true
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: |
|
|
echo "📊 Downloading slide decks from GitHub release..."
|
|
mkdir -p ${{ vars.TINYTORCH_SITE }}/_build/assets/slides
|
|
|
|
# Download all PDFs from the slides release
|
|
gh release download tinytorch-slides-v0.1.0 \
|
|
--repo harvard-edge/cs249r_book \
|
|
--pattern "*.pdf" \
|
|
--dir ${{ vars.TINYTORCH_SITE }}/_build/assets/slides || echo "⚠️ No slides release found"
|
|
|
|
echo ""
|
|
echo "📦 Slides folder contents:"
|
|
ls -la ${{ vars.TINYTORCH_SITE }}/_build/assets/slides/ || echo "No slides folder"
|
|
echo "✅ Downloaded $(ls ${{ vars.TINYTORCH_SITE }}/_build/assets/slides/*.pdf 2>/dev/null | wc -l) slide decks"
|
|
|
|
- name: 🔗 Rewrite URLs for dev site
|
|
run: bash .github/scripts/rewrite-dev-urls.sh tinytorch ${{ vars.TINYTORCH_SITE }}/_build
|
|
|
|
- name: 🔧 Modify announcement for dev preview
|
|
run: |
|
|
COMMIT_SHORT="${{ github.sha }}"
|
|
COMMIT_SHORT="${COMMIT_SHORT:0:8}"
|
|
|
|
python3 ${{ vars.BOOK_TOOLS }}/scripts/publish/modify_dev_announcement.py \
|
|
${{ vars.TINYTORCH_SITE }}/_build \
|
|
--verbose \
|
|
--commit-hash "${{ github.sha }}" \
|
|
--commit-short "$COMMIT_SHORT"
|
|
|
|
- name: 📤 Upload built site as artifact
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: tinytorch-dev-build
|
|
path: ${{ vars.TINYTORCH_SITE }}/_build
|
|
retention-days: 1
|
|
include-hidden-files: true
|
|
|
|
# Visual smoke gate — fails before deploy if Bootstrap/CSS regressed,
|
|
# the navbar collapse breakpoint shifted, or pages render blank. Runs
|
|
# the shared .github/scripts/visual_smoke.py against the artifact above.
|
|
smoke:
|
|
name: '👁️ Visual Smoke'
|
|
needs: [build-site]
|
|
if: needs.build-site.result == 'success'
|
|
uses: ./.github/workflows/infra-visual-smoke.yml
|
|
with:
|
|
site: tinytorch
|
|
artifact: tinytorch-dev-build
|
|
pages: '/index.html /preface.html'
|
|
|
|
# Deploy is gated on smoke passing. Re-fetches the artifact rather than
|
|
# the raw repo so we deploy the exact bytes that smoke validated.
|
|
deploy:
|
|
name: '🚀 Deploy TinyTorch Dev'
|
|
runs-on: ubuntu-latest
|
|
needs: [smoke]
|
|
if: needs.smoke.result == 'success'
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- name: 📦 Download built site
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: tinytorch-dev-build
|
|
path: _build
|
|
|
|
- name: 🚀 Deploy to Dev Site via SSH
|
|
env:
|
|
SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }}
|
|
run: |
|
|
echo "🔐 Starting ssh-agent..."
|
|
eval "$(ssh-agent -s)"
|
|
echo "$SSH_DEPLOY_KEY" | tr -d '\r' | ssh-add - > /dev/null
|
|
|
|
mkdir -p ~/.ssh
|
|
ssh-keyscan github.com >> ~/.ssh/known_hosts
|
|
|
|
git config --global user.email "actions@github.com"
|
|
git config --global user.name "GitHub Actions"
|
|
|
|
echo "🔄 Cloning dev preview repository (${{ vars.DEV_REPO }})..."
|
|
git clone --depth=1 ${{ vars.DEV_REPO_URL }} target-repo
|
|
|
|
cd target-repo
|
|
|
|
echo "🧹 Cleaning ${{ vars.DEV_TINYTORCH_PATH }} directory..."
|
|
rm -rf ${{ vars.DEV_TINYTORCH_PATH }}
|
|
mkdir -p ${{ vars.DEV_TINYTORCH_PATH }}
|
|
|
|
echo "🚚 Copying TinyTorch site content..."
|
|
cp -r "${{ github.workspace }}/_build/." ${{ vars.DEV_TINYTORCH_PATH }}/
|
|
|
|
echo "🔍 Validating deployment content..."
|
|
if [ ! -f "${{ vars.DEV_TINYTORCH_PATH }}/index.html" ]; then
|
|
echo "❌ CRITICAL: ${{ vars.DEV_TINYTORCH_PATH }}/index.html is missing. Aborting deployment."
|
|
exit 1
|
|
fi
|
|
|
|
echo "📦 Contents of ${{ vars.DEV_TINYTORCH_PATH }}/:"
|
|
ls -la ${{ vars.DEV_TINYTORCH_PATH }}/ | head -10
|
|
|
|
git add .
|
|
git commit -m "🔥 Deploy TinyTorch dev (Quarto) to /${{ vars.DEV_TINYTORCH_PATH }}/ from ${{ github.sha }}" --allow-empty || echo "🟡 Nothing to commit"
|
|
|
|
for i in 1 2 3; do
|
|
if git push origin main 2>/dev/null; then
|
|
echo "✅ Push succeeded on attempt $i"
|
|
break
|
|
fi
|
|
echo "⚠️ Push failed (attempt $i/3), pulling with rebase..."
|
|
git pull --rebase origin main || true
|
|
done
|
|
|
|
echo "✅ TinyTorch deployed to: https://harvard-edge.github.io/${{ vars.DEV_REPO }}/${{ vars.DEV_TINYTORCH_PATH }}/"
|