Deploy to Cloudflare Pages #85
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: Deploy to Cloudflare Pages | |
| on: | |
| push: | |
| branches: [main, master] | |
| pull_request: | |
| branches: [main, master] | |
| workflow_dispatch: | |
| inputs: | |
| environment: | |
| description: 'Deployment environment' | |
| required: false | |
| default: 'production' | |
| type: choice | |
| options: | |
| - production | |
| - staging | |
| permissions: | |
| contents: read | |
| deployments: write | |
| pull-requests: write | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| NODE_VERSION: '20' | |
| RUST_VERSION: '1.70.0' | |
| jobs: | |
| build-and-deploy: | |
| name: Build and Deploy to Cloudflare Pages | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: ${{ env.RUST_VERSION }} | |
| components: rustfmt, clippy | |
| - name: Cache Cargo dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/bin/ | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| target/ | |
| key: ${{ runner.os }}-cloudflare-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cloudflare-cargo- | |
| ${{ runner.os }}-stable-cargo- | |
| ${{ runner.os }}-cargo- | |
| - name: Cache Bun dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb', '**/package.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-bun- | |
| - name: Install Node.js and Bun | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Install Bun | |
| uses: oven-sh/setup-bun@v1 | |
| with: | |
| bun-version: latest | |
| - name: Install frontend dependencies | |
| run: bun install | |
| - name: Install Pagefind CLI | |
| run: npm install -g pagefind | |
| - name: Run tests before deployment | |
| run: | | |
| cargo fmt --all -- --check | |
| cargo clippy --all-targets --all-features -- -D warnings | |
| cargo test --lib --bins --all-features | |
| cargo test --test integration --features "tokio,search,syntax-highlighting" | |
| bun test | |
| - name: Build optimized release binary | |
| run: cargo build --release --all-features | |
| - name: Generate static site | |
| run: | | |
| # Clean any previous build | |
| rm -rf dist | |
| # Generate the static site using test_book_mdbook (full feature demo) | |
| ./target/release/md-book -i test_book_mdbook/src -o dist | |
| # Verify the build output | |
| echo "Generated $(find dist -type f | wc -l) files" | |
| ls -la dist/ | |
| # Verify pagefind search index was created | |
| if [ -d "dist/pagefind" ]; then | |
| echo "✓ Pagefind search index created successfully" | |
| ls -la dist/pagefind/ | |
| else | |
| echo "✗ ERROR: Pagefind search index not found!" | |
| exit 1 | |
| fi | |
| - name: Create 404 page | |
| run: | | |
| # Create a custom 404 page | |
| cat > dist/404.html << 'EOF' | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Page Not Found - MD-Book</title> | |
| <link rel="stylesheet" href="/css/variables.css"> | |
| <link rel="stylesheet" href="/css/general.css"> | |
| <link rel="stylesheet" href="/css/chrome.css"> | |
| </head> | |
| <body> | |
| <div id="wrapper" class="page-wrapper"> | |
| <div class="page"> | |
| <main> | |
| <h1>Page Not Found</h1> | |
| <p>The page you're looking for doesn't exist.</p> | |
| <p><a href="/">Return to the homepage</a></p> | |
| </main> | |
| </div> | |
| </div> | |
| </body> | |
| </html> | |
| EOF | |
| - name: Cache npm global packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.npm | |
| key: ${{ runner.os }}-npm-global-${{ hashFiles('**/package.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-npm-global- | |
| - name: Setup Cloudflare CLI | |
| run: npm install -g wrangler | |
| - name: Load secrets from 1Password | |
| uses: 1password/load-secrets-action@v2 | |
| if: vars.USE_1PASSWORD == 'true' || vars.USE_1PASSWORD != 'false' | |
| with: | |
| export-env: true | |
| env: | |
| OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }} | |
| CLOUDFLARE_API_TOKEN: "op://TerraphimPlatform/md-book-cloudflare/api_token" | |
| CLOUDFLARE_ACCOUNT_ID: "op://TerraphimPlatform/md-book-cloudflare/account_id" | |
| - name: Deploy to Cloudflare Pages (Production) | |
| if: (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')) || github.event_name == 'workflow_dispatch' | |
| run: | | |
| wrangler pages deploy dist \ | |
| --project-name=md-book | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ env.CLOUDFLARE_API_TOKEN || secrets.CLOUDFLARE_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ env.CLOUDFLARE_ACCOUNT_ID || secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| - name: Deploy to Cloudflare Pages (Preview) | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| wrangler pages deploy dist \ | |
| --project-name=md-book \ | |
| --branch=preview-${{ github.event.pull_request.number }} | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ env.CLOUDFLARE_API_TOKEN || secrets.CLOUDFLARE_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ env.CLOUDFLARE_ACCOUNT_ID || secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| - name: Comment deployment URL on PR | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const deploymentUrl = `https://preview-${{ github.event.pull_request.number }}.md-book.pages.dev`; | |
| const body = `## 🚀 Deployment Preview\n\nYour changes have been deployed to Cloudflare Pages!\n\n🔗 **Preview URL**: ${deploymentUrl}\n\nThe deployment will be updated automatically when you push new changes to this PR.`; | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: body | |
| }); | |
| - name: Upload build artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: built-site-${{ github.sha }} | |
| path: dist/ | |
| retention-days: 7 | |
| - name: Deployment Summary | |
| if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') | |
| run: | | |
| echo "## 🎉 Deployment Successful!" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Your MD-Book documentation has been deployed to Cloudflare Pages." >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "🔗 **Live URL**: https://md-book.pages.dev" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Build Information" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Rust Version**: ${{ env.RUST_VERSION }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Build Time**: $(date -u)" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Generated Files**: $(find dist -type f | wc -l)" >> $GITHUB_STEP_SUMMARY |