-
Notifications
You must be signed in to change notification settings - Fork 3
Centralize tool versions and improve build consistency #36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
1a057a6
1b2cc2c
ac5697b
ce14abe
6074e3b
4b39647
dc0b5be
3025129
38d3733
fb64c63
881d415
33da196
c587f47
f5fdda3
0d6b35e
79b706f
959a88d
09869f6
5ce6442
39cfff9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| # PR Preview System | ||
|
|
||
| This repository uses GitHub Pages for automated PR preview deployments without any third-party dependencies. | ||
|
|
||
| ## How It Works | ||
|
|
||
| ### Architecture | ||
|
|
||
| - **Production**: `gh-pages` branch root → https://stlab.github.io/better-code/ | ||
| - **PR Previews**: `gh-pages` branch under `pr-preview/[NUMBER]/` → https://stlab.github.io/better-code/pr-preview/123/ | ||
| - **Preview Index**: https://stlab.github.io/better-code/pr-preview/ (lists all active previews) | ||
|
|
||
| ### Workflow | ||
|
|
||
| 1. **Open PR** → Builds and deploys to `gh-pages:pr-preview/[PR-NUMBER]/` | ||
| 2. **Push to PR** → Updates the preview deployment | ||
| 3. **Close/Merge PR** → Automatically removes the preview directory | ||
| 4. **Merge to main** → Deploys to production (root of gh-pages) | ||
|
|
||
| ## Features | ||
|
|
||
| ✅ **Automatic deployment** - No manual steps required | ||
| ✅ **PR comments** - Bot posts preview URL on every PR | ||
| ✅ **Automatic cleanup** - Previews removed when PR closes | ||
| ✅ **No third-party services** - Pure GitHub Pages | ||
| ✅ **Fast builds** - Only builds changed content | ||
| ✅ **Isolated environments** - Each PR gets its own subdirectory | ||
|
|
||
| ## File Structure on gh-pages Branch | ||
|
|
||
| ``` | ||
| gh-pages/ | ||
| ├── index.html # Production site | ||
| ├── chapter-1-intro.html | ||
| ├── ... | ||
| └── pr-preview/ | ||
| ├── index.html # List of all PR previews | ||
| ├── 123/ # Preview for PR #123 | ||
| │ ├── index.html | ||
| │ └── ... | ||
| ├── 124/ # Preview for PR #124 | ||
| │ └── ... | ||
| └── ... | ||
| ``` | ||
|
|
||
| ## Configuration | ||
|
|
||
| ### Required Permissions | ||
|
|
||
| The workflow requires these permissions (already configured): | ||
| - `contents: write` - To push to gh-pages branch | ||
| - `pages: write` - To deploy to GitHub Pages | ||
| - `pull-requests: write` - To comment on PRs | ||
|
|
||
| ### GitHub Pages Settings | ||
|
|
||
| Ensure GitHub Pages is configured to deploy from the `gh-pages` branch: | ||
| 1. Go to Settings → Pages | ||
| 2. Source: Deploy from a branch | ||
| 3. Branch: `gh-pages` / `root` | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### Preview not deploying | ||
|
|
||
| Check: | ||
| 1. Workflow ran successfully in Actions tab | ||
| 2. `gh-pages` branch exists and has the preview directory | ||
| 3. GitHub Pages is enabled and set to deploy from `gh-pages` branch | ||
|
|
||
| ### Preview URL 404 | ||
|
|
||
| - Wait 1-2 minutes after deployment for GitHub Pages to update | ||
| - Check if the directory exists in the `gh-pages` branch | ||
| - Verify the PR number in the URL matches the directory name | ||
|
|
||
| ### Old previews not cleaning up | ||
|
|
||
| - Check if the cleanup workflow ran when PR closed | ||
| - Manually remove with: `git checkout gh-pages && git rm -rf pr-preview/[NUMBER] && git commit && git push` | ||
|
|
||
| ## Manual Cleanup | ||
|
|
||
| To manually remove all PR previews: | ||
|
|
||
| ```bash | ||
| git checkout gh-pages | ||
| git rm -rf pr-preview/ | ||
| git commit -m "Clean up all PR previews" | ||
| git push | ||
| ``` | ||
|
|
||
| To remove a specific preview: | ||
|
|
||
| ```bash | ||
| git checkout gh-pages | ||
| git rm -rf pr-preview/123 | ||
| git commit -m "Remove preview for PR #123" | ||
| git push | ||
| ``` | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| name: Cleanup PR Preview | ||
|
|
||
| on: | ||
| pull_request: | ||
| types: [closed] | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| jobs: | ||
| cleanup: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout gh-pages branch | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: gh-pages | ||
|
|
||
| - name: Remove PR preview directory | ||
|
sean-parent marked this conversation as resolved.
Outdated
|
||
| run: | | ||
| if [ -d "pr-preview/${{ github.event.number }}" ]; then | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git rm -rf pr-preview/${{ github.event.number }} | ||
| git commit -m "Remove preview for closed PR #${{ github.event.number }}" | ||
| git push | ||
| echo "Removed preview for PR #${{ github.event.number }}" | ||
| else | ||
| echo "No preview directory found for PR #${{ github.event.number }}" | ||
| fi | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,58 +1,214 @@ | ||
| name: Deploy mdBook to GitHub Pages | ||
| name: Build and Deploy mdBook | ||
|
sean-parent marked this conversation as resolved.
Outdated
|
||
| # Tool versions are managed in versions.toml at the repository root. | ||
| # To update mdbook or plugin versions, edit versions.toml and the CI will automatically use them. | ||
|
|
||
| on: | ||
| # Runs on pushes targeting the default branch | ||
| push: | ||
| branches: ["main"] | ||
|
|
||
| # Runs on pull requests for validation and preview deployment | ||
| pull_request: | ||
| branches: ["main"] | ||
|
|
||
| # Allows you to run this workflow manually from the Actions tab | ||
| workflow_dispatch: | ||
|
|
||
| # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages | ||
| permissions: | ||
| contents: read | ||
| contents: write # Needed for PR preview deployments | ||
| pages: write | ||
| id-token: write | ||
| pull-requests: write # Needed to comment on PRs | ||
|
|
||
| # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. | ||
| # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is it good to delete the comments in this file? |
||
| # Allow only one concurrent deployment per PR or main | ||
| concurrency: | ||
| group: "pages" | ||
| cancel-in-progress: false | ||
| group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.event.number || 'main' }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| # Build job | ||
| # Build job - runs on both PRs and main branch | ||
| build: | ||
| runs-on: ubuntu-latest | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we're going to have powershell scripts in here for running on windows, we need to do the build on Windows too, to test them.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a test. |
||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
| uses: actions/checkout@v6 | ||
|
|
||
| - name: Install mdBook | ||
| run: cargo install mdbook | ||
|
|
||
| - name: Setup Pages | ||
| id: pages | ||
| uses: actions/configure-pages@v5 | ||
|
|
||
| - name: Build with mdBook | ||
| - name: Install mdBook and plugins | ||
| run: | | ||
| cd better-code | ||
| mdbook build | ||
|
|
||
| - name: Upload artifact | ||
| uses: actions/upload-pages-artifact@v3 | ||
| chmod +x scripts/install-tools.sh | ||
| ./scripts/install-tools.sh | ||
|
|
||
| # For PRs: Build with base path for preview subdirectory | ||
| - name: Build with mdBook (PR Preview) | ||
| if: github.event_name == 'pull_request' | ||
| run: | | ||
| # Update book.toml to use PR-specific path | ||
| sed -i 's|site-url = "/better-code/"|site-url = "/better-code/pr-preview/${{ github.event.number }}/"|' better-code/book.toml | ||
| mdbook build ./better-code | ||
|
|
||
| # For main: Build with production path | ||
| - name: Build with mdBook (Production) | ||
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | ||
| run: mdbook build ./better-code | ||
|
cursor[bot] marked this conversation as resolved.
Outdated
|
||
|
|
||
| # Upload build artifact for inspection/debugging | ||
| - name: Upload build artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: book-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.number) || 'production' }} | ||
| path: ./better-code/book | ||
| retention-days: ${{ github.event_name == 'pull_request' && 7 || 30 }} | ||
|
|
||
| # Deployment job | ||
| deploy: | ||
| # PR Preview Deployment - deploys to gh-pages branch under pr-preview/NUMBER/ | ||
| deploy-preview: | ||
| if: github.event_name == 'pull_request' | ||
| needs: build | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout gh-pages branch | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: gh-pages | ||
|
|
||
| - name: Download build artifact | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: book-pr-${{ github.event.number }} | ||
| path: ./pr-preview/${{ github.event.number }} | ||
|
|
||
| - name: Create preview index | ||
| run: | | ||
| # Create an index of all PR previews if it doesn't exist | ||
| if [ ! -f pr-preview/index.html ]; then | ||
| cat > pr-preview/index.html << 'EOF' | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <title>PR Previews - Better Code</title> | ||
| <style> | ||
| body { font-family: system-ui; max-width: 800px; margin: 50px auto; padding: 20px; } | ||
| h1 { color: #333; } | ||
| ul { list-style: none; padding: 0; } | ||
| li { margin: 10px 0; padding: 10px; background: #f5f5f5; border-radius: 5px; } | ||
| a { color: #0066cc; text-decoration: none; } | ||
| a:hover { text-decoration: underline; } | ||
| </style> | ||
| </head> | ||
| <body> | ||
| <h1>Pull Request Previews</h1> | ||
| <p><a href="../">← Back to main documentation</a></p> | ||
| <p>Preview deployments for pull requests:</p> | ||
| <ul id="previews"></ul> | ||
| <script> | ||
| // List all PR preview directories | ||
| fetch('.') | ||
| .then(r => r.text()) | ||
| .then(text => { | ||
| const parser = new DOMParser(); | ||
| const doc = parser.parseFromString(text, 'text/html'); | ||
| const links = Array.from(doc.querySelectorAll('a')) | ||
| .map(a => a.getAttribute('href')) | ||
| .filter(href => href && /^\d+\/$/.test(href)) | ||
| .sort((a, b) => parseInt(b) - parseInt(a)); | ||
|
|
||
| const list = document.getElementById('previews'); | ||
| if (links.length === 0) { | ||
| list.innerHTML = '<li>No active PR previews</li>'; | ||
| } else { | ||
| links.forEach(link => { | ||
| const pr = link.replace('/', ''); | ||
| const li = document.createElement('li'); | ||
| li.innerHTML = `<a href="${link}">PR #${pr} Preview</a>`; | ||
| list.appendChild(li); | ||
| }); | ||
| } | ||
| }); | ||
| </script> | ||
| </body> | ||
| </html> | ||
| EOF | ||
| fi | ||
|
|
||
| - name: Commit and push preview | ||
| run: | | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git add pr-preview/${{ github.event.number }} | ||
| git add pr-preview/index.html | ||
| git commit -m "Deploy preview for PR #${{ github.event.number }}" || echo "No changes to commit" | ||
| git push | ||
|
sean-parent marked this conversation as resolved.
Outdated
|
||
|
|
||
| - name: Comment PR with preview URL | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const prNumber = context.issue.number; | ||
| const previewUrl = `https://stlab.github.io/better-code/pr-preview/${prNumber}/`; | ||
| const comment = `## 📚 Documentation Preview | ||
|
|
||
| Your changes have been deployed to a preview environment: | ||
|
|
||
| 🔗 **Preview URL:** ${previewUrl} | ||
|
|
||
| This preview will be automatically updated with new commits and removed when the PR is closed. | ||
|
|
||
| <sub>Built with commit ${context.sha.substring(0, 7)}</sub>`; | ||
|
|
||
| // Find existing preview comment | ||
| const { data: comments } = await github.rest.issues.listComments({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: prNumber, | ||
| }); | ||
|
|
||
| const botComment = comments.find(comment => | ||
| comment.user.type === 'Bot' && | ||
| comment.body.includes('Documentation Preview') | ||
| ); | ||
|
|
||
| if (botComment) { | ||
| // Update existing comment | ||
| await github.rest.issues.updateComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| comment_id: botComment.id, | ||
| body: comment | ||
| }); | ||
| } else { | ||
| // Create new comment | ||
| await github.rest.issues.createComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: prNumber, | ||
| body: comment | ||
| }); | ||
| } | ||
|
|
||
| # Production Deployment - deploys to root of GitHub Pages | ||
| deploy-production: | ||
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | ||
| needs: build | ||
| environment: | ||
| name: github-pages | ||
| url: ${{ steps.deployment.outputs.page_url }} | ||
| runs-on: ubuntu-latest | ||
| needs: build | ||
| steps: | ||
| - name: Download build artifact | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: book-production | ||
| path: ./book | ||
|
|
||
| - name: Setup Pages | ||
| id: pages | ||
| uses: actions/configure-pages@v5 | ||
|
|
||
| - name: Upload Pages artifact | ||
| uses: actions/upload-pages-artifact@v4 | ||
| with: | ||
| path: ./book | ||
|
|
||
| - name: Deploy to GitHub Pages | ||
| id: deployment | ||
| uses: actions/deploy-pages@v4 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # Tool versions for asdf version manager | ||
| # See: https://asdf-vm.com/ | ||
| # | ||
| # Note: For mdbook and plugin versions, see versions.toml | ||
| # Use the install scripts in better-code/ to install the correct versions | ||
| rust stable | ||
|
|
Uh oh!
There was an error while loading. Please reload this page.