Deploy Preview #956
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 Preview | |
| on: | |
| workflow_run: | |
| workflows: | |
| - CI - Build and Test | |
| types: | |
| - completed | |
| pull_request_target: | |
| types: | |
| - closed | |
| permissions: | |
| actions: read | |
| contents: write | |
| pull-requests: write | |
| concurrency: | |
| group: deploy-preview-${{ github.event.workflow_run.id || github.event.pull_request.number }} | |
| cancel-in-progress: false | |
| jobs: | |
| deploy-preview: | |
| name: Deploy PR Preview | |
| if: > | |
| github.event_name == 'workflow_run' && | |
| github.event.workflow_run.event == 'pull_request' && | |
| github.event.workflow_run.conclusion == 'success' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Download CI web build artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: web-build | |
| path: web-build | |
| run-id: ${{ github.event.workflow_run.id }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Download CI coverage report artifact | |
| uses: actions/download-artifact@v8 | |
| continue-on-error: true | |
| with: | |
| name: coverage-report | |
| path: coverage-report | |
| run-id: ${{ github.event.workflow_run.id }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Resolve PR number from head branch | |
| id: resolve-pr | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const headSha = '${{ github.event.workflow_run.head_sha }}'; | |
| const headBranch = '${{ github.event.workflow_run.head_branch }}'; | |
| const headOwner = '${{ github.event.workflow_run.head_repository.owner.login }}'; | |
| // Works for same-repo and fork PRs | |
| const { data: prs } = await github.rest.pulls.list({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open', | |
| head: `${headOwner}:${headBranch}`, | |
| }); | |
| if (!prs.length) { | |
| core.setFailed(`No open PR found for branch ${headOwner}:${headBranch}`); | |
| return; | |
| } | |
| const pr = prs[0]; | |
| core.setOutput('pr_number', pr.number); | |
| core.setOutput('head_sha', headSha); | |
| core.setOutput('short_sha', headSha.slice(0, 7)); | |
| - name: Stage preview artifact | |
| id: preview-meta | |
| run: | | |
| pr_number="${{ steps.resolve-pr.outputs.pr_number }}" | |
| head_sha="${{ steps.resolve-pr.outputs.head_sha }}" | |
| mkdir -p preview | |
| mkdir -p preview/test-coverage | |
| for file in \ | |
| web-build/index.html \ | |
| web-build/index.js \ | |
| web-build/index.wasm \ | |
| web-build/index.data \ | |
| web-build/*.worker.js \ | |
| web-build/coi-serviceworker.js | |
| do | |
| [ -e "$file" ] && cp "$file" preview/ | |
| done | |
| if [ -d "coverage-report" ]; then | |
| cp -R coverage-report/* preview/test-coverage/ | |
| fi | |
| test -f preview/index.html | |
| test -f preview/index.js | |
| test -f preview/index.wasm | |
| touch preview/.nojekyll | |
| preview_path="pr-previews/pr-${pr_number}" | |
| preview_url="https://amplitron.sudipmondal.co.in/${preview_path}/" | |
| echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT" | |
| echo "head_sha=$head_sha" >> "$GITHUB_OUTPUT" | |
| echo "preview_path=$preview_path" >> "$GITHUB_OUTPUT" | |
| echo "preview_url=$preview_url" >> "$GITHUB_OUTPUT" | |
| echo "short_sha=${{ steps.resolve-pr.outputs.short_sha }}" >> "$GITHUB_OUTPUT" | |
| - name: Check pull request state | |
| id: pr-state | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const { owner, repo } = context.repo; | |
| const pull_number = Number('${{ steps.preview-meta.outputs.pr_number }}'); | |
| const { data: pull } = await github.rest.pulls.get({ | |
| owner, | |
| repo, | |
| pull_number, | |
| }); | |
| core.setOutput('state', pull.state); | |
| - name: Publish preview to GitHub Pages | |
| if: steps.pr-state.outputs.state == 'open' | |
| uses: peaceiris/actions-gh-pages@v4 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_dir: ./preview | |
| publish_branch: gh-pages | |
| destination_dir: ${{ steps.preview-meta.outputs.preview_path }} | |
| keep_files: true | |
| enable_jekyll: false | |
| - name: Comment preview URL on PR | |
| if: steps.pr-state.outputs.state == 'open' | |
| uses: actions/github-script@v9 | |
| env: | |
| PR_NUMBER: ${{ steps.preview-meta.outputs.pr_number }} | |
| PREVIEW_URL: ${{ steps.preview-meta.outputs.preview_url }} | |
| PREVIEW_PATH: ${{ steps.preview-meta.outputs.preview_path }} | |
| SHORT_SHA: ${{ steps.preview-meta.outputs.short_sha }} | |
| with: | |
| script: | | |
| const marker = '<!-- amplitron-pr-preview -->'; | |
| const { owner, repo } = context.repo; | |
| const issue_number = Number(process.env.PR_NUMBER); | |
| const body = [ | |
| marker, | |
| '### PR Preview Ready', | |
| '', | |
| `Preview URL: ${process.env.PREVIEW_URL}`, | |
| `Coverage Report: ${process.env.PREVIEW_URL}test-coverage/`, | |
| '', | |
| `Built from commit \`${process.env.SHORT_SHA}\` and deployed to \`${process.env.PREVIEW_PATH}\`.`, | |
| 'This preview updates automatically when the PR branch changes and is removed when the PR closes.', | |
| ].join('\n'); | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner, | |
| repo, | |
| issue_number, | |
| per_page: 100, | |
| }); | |
| const previous = comments.find((comment) => | |
| comment.user?.type === 'Bot' && comment.body?.includes(marker) | |
| ); | |
| if (previous) { | |
| await github.rest.issues.updateComment({ | |
| owner, | |
| repo, | |
| comment_id: previous.id, | |
| body, | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner, | |
| repo, | |
| issue_number, | |
| body, | |
| }); | |
| } | |
| cleanup-preview: | |
| name: Remove Closed PR Preview | |
| if: github.event_name == 'pull_request_target' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout GitHub Pages branch | |
| id: pages-checkout | |
| uses: actions/checkout@v6 | |
| continue-on-error: true | |
| with: | |
| ref: gh-pages | |
| path: pages | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Remove preview directory | |
| if: steps.pages-checkout.outcome == 'success' | |
| working-directory: pages | |
| env: | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: | | |
| target="pr-previews/pr-${PR_NUMBER}" | |
| if [ ! -d "$target" ]; then | |
| echo "No preview directory found at $target" | |
| exit 0 | |
| fi | |
| rm -rf "$target" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add -A "$target" | |
| git commit -m "Remove preview for PR #${PR_NUMBER}" | |
| git push | |
| - name: Comment cleanup on PR | |
| if: steps.pages-checkout.outcome == 'success' | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const marker = '<!-- amplitron-pr-preview -->'; | |
| const { owner, repo } = context.repo; | |
| const issue_number = context.payload.pull_request.number; | |
| const body = [ | |
| marker, | |
| '### PR Preview Removed', | |
| '', | |
| 'The GitHub Pages preview for this PR has been removed because the PR was closed.', | |
| ].join('\n'); | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner, | |
| repo, | |
| issue_number, | |
| per_page: 100, | |
| }); | |
| const previous = comments.find((comment) => | |
| comment.user?.type === 'Bot' && comment.body?.includes(marker) | |
| ); | |
| if (previous) { | |
| await github.rest.issues.updateComment({ | |
| owner, | |
| repo, | |
| comment_id: previous.id, | |
| body, | |
| }); | |
| } |