1+ name : PR Preview (GitHub Pages)
2+
3+ # Build and deploy to GitHub Pages on pull requests
4+ on :
5+ pull_request :
6+ branches :
7+ - main
8+ - master
9+
10+ jobs :
11+ build-preview :
12+ runs-on : ubuntu-latest
13+ permissions :
14+ contents : write # Allow pushing to gh-pages branch
15+ pull-requests : write # Allow commenting on PRs
16+ steps :
17+ - uses : actions/checkout@v4
18+
19+ # Install uv for faster dependency management
20+ - name : Install uv
21+ uses : astral-sh/setup-uv@v4
22+ with :
23+ enable-cache : true
24+
25+ # Set up Python using uv
26+ - name : Set up Python
27+ run : uv python install 3.11
28+
29+ # Install dependencies using uv
30+ - name : Install dependencies
31+ run : uv sync
32+
33+ # Cache executed notebooks between runs
34+ - name : Cache executed notebooks
35+ uses : actions/cache@v4
36+ with :
37+ path : _build/.jupyter_cache
38+ key : jupyter-book-cache-${{ hashFiles('uv.lock') }}
39+
40+ # Build the book
41+ - name : Build the book
42+ run : |
43+ uv run jupyter-book build .
44+
45+ # Deploy to GitHub Pages preview folder
46+ - name : Deploy PR Preview
47+ run : |
48+ # Configure git
49+ git config --global user.name 'github-actions[bot]'
50+ git config --global user.email 'github-actions[bot]@users.noreply.github.com'
51+
52+ # Clone gh-pages branch
53+ git clone --branch gh-pages --single-branch https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} gh-pages
54+
55+ # Create preview directory for this PR
56+ PR_PREVIEW_DIR="gh-pages/preview/pr-${{ github.event.pull_request.number }}"
57+ rm -rf "$PR_PREVIEW_DIR"
58+ mkdir -p "$PR_PREVIEW_DIR"
59+
60+ # Copy built site to preview directory
61+ cp -r _build/html/* "$PR_PREVIEW_DIR/"
62+
63+ # Add .nojekyll to ensure GitHub Pages processes the site correctly
64+ touch "$PR_PREVIEW_DIR/.nojekyll"
65+
66+ # Commit and push
67+ cd gh-pages
68+ git add .
69+ git commit -m "Deploy preview for PR #${{ github.event.pull_request.number }}" || echo "No changes to commit"
70+ git push origin gh-pages
71+
72+ # Comment on PR with preview link
73+ - name : Comment PR
74+ uses : actions/github-script@v7
75+ with :
76+ script : |
77+ const baseUrl = 'https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}';
78+ const previewUrl = `${baseUrl}/preview/pr-${{ github.event.pull_request.number }}`;
79+ const body = `🚀 **GitHub Pages Deploy Preview ready!**\n\n📖 Preview: ${previewUrl}\n\n_This preview will be updated on every commit to this PR._`;
80+
81+ // Find and update existing comment or create new one
82+ const { data: comments } = await github.rest.issues.listComments({
83+ owner: context.repo.owner,
84+ repo: context.repo.repo,
85+ issue_number: context.issue.number,
86+ });
87+
88+ const botComment = comments.find(comment =>
89+ comment.user.type === 'Bot' && comment.body.includes('GitHub Pages Deploy Preview ready!')
90+ );
91+
92+ if (botComment) {
93+ await github.rest.issues.updateComment({
94+ owner: context.repo.owner,
95+ repo: context.repo.repo,
96+ comment_id: botComment.id,
97+ body: body
98+ });
99+ } else {
100+ await github.rest.issues.createComment({
101+ owner: context.repo.owner,
102+ repo: context.repo.repo,
103+ issue_number: context.issue.number,
104+ body: body
105+ });
106+ }
0 commit comments