Prod/dev split, dev site on dev relative path, prod on root #11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build Videos and Deploy Site | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - '.github/workflows/**' | |
| - 'Chapter*/**' | |
| - 'scene_utils/**' | |
| - 'imgs/**' | |
| - 'docs/**/*.md' | |
| - 'mkdocs.yml' | |
| - 'manim.cfg' | |
| - 'requirements.txt' | |
| workflow_dispatch: | |
| inputs: | |
| chapters: | |
| description: 'Chapters to rebuild (comma-separated, e.g. "0,3,5" or "all")' | |
| required: false | |
| default: 'all' | |
| prod: | |
| description: 'Use ElevenLabs TTS for production quality narration' | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: read | |
| pages: write | |
| id-token: write | |
| concurrency: | |
| group: pages | |
| cancel-in-progress: false | |
| jobs: | |
| build-and-deploy: | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deployment.outputs.page_url }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 2 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y ffmpeg sox libcairo2-dev libpango1.0-dev \ | |
| texlive texlive-latex-extra texlive-fonts-extra | |
| - name: Install Python dependencies | |
| run: | | |
| pip install 'setuptools<82' | |
| pip install manim manim-voiceover[gtts] invoke python-graphblas \ | |
| networkx matplotlib python-dotenv \ | |
| mkdocs mkdocs-material pymdown-extensions | |
| if [ "${{ inputs.prod }}" = "true" ]; then | |
| pip install 'elevenlabs>=0.2.27,<0.3.0' | |
| fi | |
| - name: Restore dev video cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: .video-cache/dev | |
| key: dev-videos-${{ hashFiles('Chapter**/Scene*.py', 'Chapter**/Thumb.py', 'scene_utils/**/*.py', 'imgs/**', 'manim.cfg') }} | |
| restore-keys: dev-videos- | |
| - name: Restore prod video cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: .video-cache/prod | |
| key: prod-videos-${{ hashFiles('Chapter**/Scene*.py', 'Chapter**/Thumb.py', 'scene_utils/**/*.py', 'imgs/**', 'manim.cfg') }} | |
| restore-keys: prod-videos- | |
| - name: Restore voiceover cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| Chapter0/media/voiceovers | |
| Chapter1/media/voiceovers | |
| Chapter2/media/voiceovers | |
| Chapter3/media/voiceovers | |
| Chapter4/media/voiceovers | |
| Chapter5/media/voiceovers | |
| Chapter6/media/voiceovers | |
| Chapter7/media/voiceovers | |
| Chapter8/media/voiceovers | |
| Chapter9/media/voiceovers | |
| key: voiceovers-${{ hashFiles('Chapter**/Scene*.py') }} | |
| restore-keys: voiceovers- | |
| - name: Determine chapters to build | |
| id: chapters | |
| run: | | |
| mkdir -p .video-cache/dev .video-cache/prod | |
| # Determine build mode | |
| if [ "${{ inputs.prod }}" = "true" ]; then | |
| CACHE_DIR=".video-cache/prod" | |
| else | |
| CACHE_DIR=".video-cache/dev" | |
| fi | |
| # On workflow_dispatch, use the input | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| if [ "${{ inputs.chapters }}" = "all" ]; then | |
| echo "rebuild=0,1,2,3,4,5,6,7,8,9" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "rebuild=${{ inputs.chapters }}" >> "$GITHUB_OUTPUT" | |
| fi | |
| else | |
| # On push, rebuild dev chapters that have cache misses | |
| REBUILD="" | |
| for N in 0 1 2 3 4 5 6 7 8 9; do | |
| CHAPTER="Chapter${N}" | |
| if [ ! -f "${CACHE_DIR}/${CHAPTER}_480p15.mp4" ] || [ ! -f "${CACHE_DIR}/${CHAPTER}.png" ]; then | |
| if [ -d "$CHAPTER" ]; then | |
| REBUILD="${REBUILD:+${REBUILD},}${N}" | |
| fi | |
| fi | |
| done | |
| echo "rebuild=${REBUILD}" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Build chapters | |
| env: | |
| ELEVEN_API_KEY: ${{ secrets.ELEVEN_API_KEY }} | |
| run: | | |
| # Determine target cache directory | |
| if [ "${{ inputs.prod }}" = "true" ]; then | |
| CACHE_DIR=".video-cache/prod" | |
| else | |
| CACHE_DIR=".video-cache/dev" | |
| fi | |
| REBUILD="${{ steps.chapters.outputs.rebuild }}" | |
| echo "Build mode: $([ "${{ inputs.prod }}" = "true" ] && echo "PROD" || echo "DEV")" | |
| echo "Chapters to rebuild: ${REBUILD:-none}" | |
| # Build chapters that need rebuilding | |
| if [ -n "$REBUILD" ]; then | |
| IFS=',' read -ra CHAPTERS <<< "$REBUILD" | |
| for N in "${CHAPTERS[@]}"; do | |
| N=$(echo "$N" | tr -d ' ') | |
| CHAPTER="Chapter${N}" | |
| if [ ! -d "$CHAPTER" ]; then | |
| echo "Skipping ${CHAPTER} (directory not found)" | |
| continue | |
| fi | |
| echo "==========================================" | |
| echo "Building ${CHAPTER}" | |
| echo "==========================================" | |
| # Build and stitch the chapter | |
| if [ "${{ inputs.prod }}" = "true" ]; then | |
| invoke build-chapter --chapter "$CHAPTER" --quality l --pause-time 0 --prod | |
| else | |
| invoke build-chapter --chapter "$CHAPTER" --quality l --pause-time 0 | |
| fi | |
| # Render thumbnail | |
| cd "$CHAPTER" | |
| manim -ql -s Thumb.py Thumb -o "../../../../docs/${CHAPTER}.png" | |
| cd .. | |
| # Cache the results | |
| cp "docs/${CHAPTER}_480p15.mp4" "${CACHE_DIR}/${CHAPTER}_480p15.mp4" | |
| cp "docs/${CHAPTER}.png" "${CACHE_DIR}/${CHAPTER}.png" | |
| echo "${CHAPTER} complete" | |
| done | |
| fi | |
| - name: Assemble and build site | |
| run: | | |
| # Step 1: Build prod site at root (if prod videos exist) | |
| PROD_VIDEOS_EXIST=false | |
| for N in 0 1 2 3 4 5 6 7 8 9; do | |
| CHAPTER="Chapter${N}" | |
| if [ -f ".video-cache/prod/${CHAPTER}_480p15.mp4" ]; then | |
| cp ".video-cache/prod/${CHAPTER}_480p15.mp4" "docs/${CHAPTER}_480p15.mp4" | |
| cp ".video-cache/prod/${CHAPTER}.png" "docs/${CHAPTER}.png" | |
| PROD_VIDEOS_EXIST=true | |
| fi | |
| done | |
| if [ "$PROD_VIDEOS_EXIST" = "true" ]; then | |
| echo "Building prod site at root..." | |
| mkdocs build -d site | |
| else | |
| echo "No prod videos cached yet. Building placeholder prod site..." | |
| mkdocs build -d site | |
| fi | |
| # Step 2: Build dev site at /dev/ | |
| for N in 0 1 2 3 4 5 6 7 8 9; do | |
| CHAPTER="Chapter${N}" | |
| if [ -f ".video-cache/dev/${CHAPTER}_480p15.mp4" ]; then | |
| cp ".video-cache/dev/${CHAPTER}_480p15.mp4" "docs/${CHAPTER}_480p15.mp4" | |
| cp ".video-cache/dev/${CHAPTER}.png" "docs/${CHAPTER}.png" | |
| fi | |
| done | |
| echo "Building dev site at /dev/..." | |
| mkdocs build -d site/dev | |
| - name: Upload Pages artifact | |
| uses: actions/upload-pages-artifact@v3 | |
| with: | |
| path: site | |
| - name: Deploy to GitHub Pages | |
| id: deployment | |
| uses: actions/deploy-pages@v4 |