|
| 1 | +name: Documentation |
| 2 | +on: |
| 3 | + push: |
| 4 | + branches: |
| 5 | + - develop |
| 6 | + tags: |
| 7 | + - 'v*' |
| 8 | + pull_request: |
| 9 | + types: [opened, synchronize, reopened, closed] |
| 10 | + |
| 11 | +permissions: |
| 12 | + contents: write |
| 13 | + pull-requests: write |
| 14 | + |
| 15 | +jobs: |
| 16 | + # Job for versioned deployments (runs on develop branch and tags) |
| 17 | + deploy-versions: |
| 18 | + if: github.event_name == 'push' && (github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/tags/v')) |
| 19 | + runs-on: ubuntu-latest |
| 20 | + steps: |
| 21 | + - uses: actions/checkout@v4 |
| 22 | + with: |
| 23 | + fetch-depth: 0 # Important for mike to work with tags |
| 24 | + |
| 25 | + - uses: astral-sh/setup-uv@v3 |
| 26 | + with: |
| 27 | + version: "0.5.*" |
| 28 | + enable-cache: true |
| 29 | + - name: Sync |
| 30 | + run: | |
| 31 | + uv sync --locked |
| 32 | + git restore uv.lock |
| 33 | + |
| 34 | + - name: Configure Git |
| 35 | + run: | |
| 36 | + git config --local user.name "GitHub Actions" |
| 37 | + git config --local user.email "actions@github.com" |
| 38 | + |
| 39 | + - name: Deploy docs |
| 40 | + run: | |
| 41 | + if [[ $GITHUB_REF == refs/tags/* ]]; then |
| 42 | + # For tags, deploy the tagged version |
| 43 | + VERSION=${GITHUB_REF#refs/tags/v} |
| 44 | + uv run mike deploy --push $VERSION |
| 45 | + |
| 46 | + # If this is the latest version, update the 'latest' alias |
| 47 | + LATEST_TAG=$(git tag --sort=-creatordate | head -n 1) |
| 48 | + if [[ "v$VERSION" == "$LATEST_TAG" ]]; then |
| 49 | + uv run mike alias --push $VERSION latest |
| 50 | + uv run mike set-default --push latest |
| 51 | + fi |
| 52 | + else |
| 53 | + # For develop branch, deploy to 'dev' |
| 54 | + uv run mike deploy --push --update-aliases dev |
| 55 | + fi |
| 56 | +
|
| 57 | + # Job for PR previews |
| 58 | + preview: |
| 59 | + if: github.event_name == 'pull_request' |
| 60 | + runs-on: ubuntu-latest |
| 61 | + steps: |
| 62 | + - uses: actions/checkout@v4 |
| 63 | + |
| 64 | + - uses: astral-sh/setup-uv@v3 |
| 65 | + with: |
| 66 | + version: "0.5.*" |
| 67 | + enable-cache: true |
| 68 | + - name: Sync |
| 69 | + run: | |
| 70 | + uv sync |
| 71 | + git diff |
| 72 | +
|
| 73 | + # Only build and deploy if PR is opened/synchronized/reopened |
| 74 | + - name: Build docs |
| 75 | + if: github.event.action != 'closed' |
| 76 | + run: | |
| 77 | + uv run mkdocs build --site-dir site/pr-${{ github.event.pull_request.number }} |
| 78 | +
|
| 79 | + - name: Deploy preview |
| 80 | + id: deploy |
| 81 | + if: github.event.action != 'closed' |
| 82 | + run: | |
| 83 | + git config --global user.name "GitHub Actions" |
| 84 | + git config --global user.email "actions@github.com" |
| 85 | + |
| 86 | + # Checkout gh-pages branch |
| 87 | + git restore uv.lock |
| 88 | + git fetch origin gh-pages --depth=1 |
| 89 | + git checkout gh-pages |
| 90 | + |
| 91 | + # Create preview directory if it doesn't exist |
| 92 | + mkdir -p pr-previews |
| 93 | + |
| 94 | + # Check if there are actual changes in the built site |
| 95 | + if [ -d "pr-previews/pr-${{ github.event.pull_request.number }}" ]; then |
| 96 | + diff -r site/pr-${{ github.event.pull_request.number }} pr-previews/pr-${{ github.event.pull_request.number }} > /dev/null 2>&1 |
| 97 | + if [ $? -eq 0 ]; then |
| 98 | + echo "No changes in documentation. Skipping deployment." |
| 99 | + exit 0 |
| 100 | + fi |
| 101 | + fi |
| 102 | + |
| 103 | + # Remove old preview if it exists |
| 104 | + rm -rf pr-previews/pr-${{ github.event.pull_request.number }} |
| 105 | + # Copy new preview |
| 106 | + cp -r site/pr-${{ github.event.pull_request.number }} pr-previews/ |
| 107 | + |
| 108 | + # Commit and push |
| 109 | + git add pr-previews |
| 110 | + git commit -m "Deploy preview for PR #${{ github.event.pull_request.number }}" || echo "No changes to commit" |
| 111 | + git diff --staged --quiet || git push origin gh-pages |
| 112 | + echo "has_changes=true" >> $GITHUB_OUTPUT |
| 113 | +
|
| 114 | + - name: Post/Update PR Review |
| 115 | + if: github.event.action != 'closed' |
| 116 | + uses: actions/github-script@v6 |
| 117 | + with: |
| 118 | + github-token: ${{ secrets.GITHUB_TOKEN }} |
| 119 | + script: | |
| 120 | + const has_changes = '${{ steps.deploy.outputs.has_changes }}' === 'true'; |
| 121 | + const preview_url = `https://${context.repo.owner}.github.io/${context.repo.repo}/pr-previews/pr-${context.payload.pull_request.number}/`; |
| 122 | + const message = `📚 Documentation preview will be available at: ${preview_url} |
| 123 | +
|
| 124 | + Status: ${has_changes ? '✅ Preview is ready!' : '🔄 No changes in documentation since last update'}`; |
| 125 | + |
| 126 | + const reviews = await github.rest.pulls.listReviews({ |
| 127 | + owner: context.repo.owner, |
| 128 | + repo: context.repo.repo, |
| 129 | + pull_number: context.payload.pull_request.number, |
| 130 | + }); |
| 131 | + |
| 132 | + const docReview = reviews.data.find(review => |
| 133 | + review.user.login === 'github-actions[bot]' && |
| 134 | + review.body.includes('Documentation preview will be available at:') |
| 135 | + ); |
| 136 | + |
| 137 | + if (!docReview) { |
| 138 | + await github.rest.pulls.createReview({ |
| 139 | + owner: context.repo.owner, |
| 140 | + repo: context.repo.repo, |
| 141 | + pull_number: context.payload.pull_request.number, |
| 142 | + body: message, |
| 143 | + event: 'COMMENT' |
| 144 | + }); |
| 145 | + } |
| 146 | +
|
| 147 | + - name: Cleanup preview |
| 148 | + if: github.event.action == 'closed' |
| 149 | + run: | |
| 150 | + git config --global user.name "GitHub Actions" |
| 151 | + git config --global user.email "actions@github.com" |
| 152 | + |
| 153 | + # Checkout gh-pages branch |
| 154 | + git restore uv.lock |
| 155 | + git fetch origin gh-pages --depth=1 |
| 156 | + git checkout gh-pages |
| 157 | + |
| 158 | + # Remove the preview directory for this PR |
| 159 | + rm -rf pr-previews/pr-${{ github.event.pull_request.number }} |
| 160 | + |
| 161 | + # Commit and push if there are changes |
| 162 | + git add pr-previews |
| 163 | + git diff --staged --quiet || (git commit -m "Remove preview for PR #${{ github.event.pull_request.number }}" && git push origin gh-pages) |
| 164 | +
|
| 165 | + # Optional job to cleanup old PR previews |
| 166 | + cleanup-old-previews: |
| 167 | + if: github.event_name == 'push' && github.ref == 'refs/heads/develop' |
| 168 | + runs-on: ubuntu-latest |
| 169 | + steps: |
| 170 | + - uses: actions/checkout@v4 |
| 171 | + with: |
| 172 | + ref: gh-pages |
| 173 | + |
| 174 | + - name: Get closed PRs |
| 175 | + id: closed-prs |
| 176 | + uses: actions/github-script@v7 |
| 177 | + with: |
| 178 | + script: | |
| 179 | + const prs = await github.rest.pulls.list({ |
| 180 | + owner: context.repo.owner, |
| 181 | + repo: context.repo.repo, |
| 182 | + state: 'closed' |
| 183 | + }); |
| 184 | + return prs.data.map(pr => pr.number); |
| 185 | + result-encoding: string |
| 186 | + |
| 187 | + - name: Cleanup old previews |
| 188 | + run: | |
| 189 | + git config --global user.name "GitHub Actions" |
| 190 | + git config --global user.email "actions@github.com" |
| 191 | + |
| 192 | + # Get list of preview directories |
| 193 | + cd pr-previews |
| 194 | + for preview in pr-*; do |
| 195 | + if [ -d "$preview" ]; then |
| 196 | + PR_NUM=$(echo $preview | sed 's/pr-//') |
| 197 | + if ! echo "${{ steps.closed-prs.outputs.result }}" | grep -q "$PR_NUM"; then |
| 198 | + rm -rf "$preview" |
| 199 | + echo "Removed old preview: $preview" |
| 200 | + fi |
| 201 | + fi |
| 202 | + done |
| 203 | + |
| 204 | + # Commit and push if there are changes |
| 205 | + git add . |
| 206 | + git diff --staged --quiet || (git commit -m "Cleanup old PR previews" && git push origin gh-pages) |
| 207 | +
|
0 commit comments