Send Bonus Milestone self-report and use API season rules #581
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 PR preview | |
| on: | |
| pull_request: | |
| types: [opened, reopened, synchronize, closed] | |
| paths: | |
| - "app/**" | |
| - "components/**" | |
| - "public/**" | |
| - "package.json" | |
| - "yarn.lock" | |
| - "next.config.mjs" | |
| - ".github/workflows/pr-preview.yml" | |
| - ".github/workflows/nextjs.yml" | |
| jobs: | |
| preview-status: | |
| if: github.event.pull_request.head.repo.full_name == github.repository && github.event.action != 'closed' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 2 | |
| permissions: | |
| pull-requests: write | |
| steps: | |
| - name: Mark PR preview as building | |
| uses: actions/github-script@v7 | |
| env: | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| with: | |
| script: | | |
| const marker = '<!-- gcsb-pr-preview -->' | |
| const body = `${marker}\n## ⏳ PR preview building\n\nThe preview is queued or currently building.\n\n- Commit: \`${process.env.HEAD_SHA.slice(0, 7)}\`\n- The live preview link will appear only after deployment succeeds and the URL responds successfully.` | |
| const comments = await github.paginate(github.rest.issues.listComments, { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| per_page: 100, | |
| }) | |
| const existing = comments.find((comment) => comment.body?.includes(marker)) | |
| if (existing) { | |
| await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: existing.id, body }) | |
| } else { | |
| await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body }) | |
| } | |
| preview: | |
| if: github.event.pull_request.head.repo.full_name == github.repository | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| permissions: | |
| actions: read | |
| contents: write | |
| pull-requests: write | |
| pages: write | |
| id-token: write | |
| concurrency: | |
| group: gcsb-pages-content-v3 | |
| cancel-in-progress: false | |
| environment: | |
| name: pr-preview | |
| url: https://arcade.eplus.dev/pr-preview/pr-${{ github.event.number }}/ | |
| steps: | |
| - name: Checkout production source | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.base.ref }} | |
| path: production-source | |
| persist-credentials: false | |
| - name: Checkout pull request source | |
| if: github.event.action != 'closed' | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| path: preview-source | |
| persist-credentials: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "20" | |
| cache: yarn | |
| cache-dependency-path: production-source/yarn.lock | |
| - name: Build current production version | |
| working-directory: production-source | |
| env: | |
| NEXT_PUBLIC_ENABLE_ANALYTICS: "true" | |
| NEXT_PUBLIC_GA_ID: "G-SJNYKL2864" | |
| NEXT_PUBLIC_GA_IDS: "G-SJNYKL2864" | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| yarn install --frozen-lockfile --non-interactive | |
| cat > next.config.mjs <<'CONFIG' | |
| /** @type {import('next').NextConfig} */ | |
| const nextConfig = { | |
| output: "export", | |
| trailingSlash: true, | |
| images: { unoptimized: true }, | |
| } | |
| export default nextConfig | |
| CONFIG | |
| yarn build | |
| - name: Build pull request preview | |
| if: github.event.action != 'closed' | |
| working-directory: preview-source | |
| env: | |
| NEXT_STATIC_EXPORT: "true" | |
| NEXT_PUBLIC_BASE_PATH: "/pr-preview/pr-${{ github.event.number }}" | |
| NEXT_PUBLIC_ENABLE_ANALYTICS: "false" | |
| NEXT_PUBLIC_GA_ID: "" | |
| NEXT_PUBLIC_COOKIE_CONSENT_PREVIEW: "true" | |
| run: | | |
| yarn install --frozen-lockfile --non-interactive | |
| yarn build | |
| - name: Verify preview output | |
| if: github.event.action != 'closed' | |
| working-directory: preview-source | |
| env: | |
| PREVIEW_PATH: "/pr-preview/pr-${{ github.event.number }}" | |
| REPO_NAME: ${{ github.event.repository.name }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| test -f out/index.html | |
| grep -q "${PREVIEW_PATH}/_next/" out/index.html | |
| grep -q 'name="cookie-notice-preview" content="true"' out/index.html | |
| if grep -R -F -q "G-SJNYKL2864" out; then exit 1; fi | |
| if grep -R -F -q "www.googletagmanager.com/gtag/js" out; then exit 1; fi | |
| if grep -q "/${REPO_NAME}/pr-preview/" out/index.html; then exit 1; fi | |
| - name: Assemble production and preview content | |
| env: | |
| PR_NUMBER: ${{ github.event.number }} | |
| PR_ACTION: ${{ github.event.action }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| rm -rf published-site | |
| if git ls-remote --exit-code --heads "https://github.com/${GITHUB_REPOSITORY}.git" gh-pages >/dev/null 2>&1; then | |
| git clone --depth 1 --branch gh-pages "https://github.com/${GITHUB_REPOSITORY}.git" published-site | |
| rm -rf published-site/.git | |
| else | |
| mkdir -p published-site | |
| fi | |
| mkdir -p published-site/pr-preview | |
| find published-site -mindepth 1 -maxdepth 1 ! -name pr-preview -exec rm -rf {} + | |
| cp -a production-source/out/. published-site/ | |
| preview_dir="published-site/pr-preview/pr-${PR_NUMBER}" | |
| rm -rf "${preview_dir}" | |
| if [ "${PR_ACTION}" != "closed" ]; then | |
| mkdir -p "${preview_dir}" | |
| cp -a preview-source/out/. "${preview_dir}/" | |
| fi | |
| touch published-site/.nojekyll | |
| - name: Save complete Pages content | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR_NUMBER: ${{ github.event.number }} | |
| PR_ACTION: ${{ github.event.action }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| cd published-site | |
| git init | |
| git checkout -B gh-pages | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add -A | |
| git commit -m "preview: ${PR_ACTION} PR #${PR_NUMBER}" | |
| git push --force "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" gh-pages | |
| - name: Upload Pages artifact | |
| uses: actions/upload-pages-artifact@v5 | |
| with: | |
| path: published-site | |
| include-hidden-files: true | |
| - name: Deploy GitHub Pages | |
| id: deployment | |
| uses: actions/deploy-pages@v4 | |
| - name: Verify live preview URL | |
| if: success() && github.event.action != 'closed' | |
| env: | |
| PREVIEW_URL: https://arcade.eplus.dev/pr-preview/pr-${{ github.event.number }}/ | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| for attempt in $(seq 1 18); do | |
| if curl --fail --silent --show-error --location --max-time 15 "${PREVIEW_URL}" >/dev/null; then | |
| echo "Preview is live: ${PREVIEW_URL}" | |
| exit 0 | |
| fi | |
| echo "Preview not live yet (attempt ${attempt}/18); waiting 5s..." | |
| sleep 5 | |
| done | |
| echo "Preview URL did not become reachable after deployment: ${PREVIEW_URL}" >&2 | |
| exit 1 | |
| - name: Add preview link to pull request | |
| if: success() | |
| uses: actions/github-script@v7 | |
| env: | |
| PAGE_ROOT: https://arcade.eplus.dev/ | |
| PR_ACTION: ${{ github.event.action }} | |
| PR_NUMBER: ${{ github.event.number }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| with: | |
| script: | | |
| const marker = '<!-- gcsb-pr-preview -->' | |
| const root = process.env.PAGE_ROOT.endsWith('/') ? process.env.PAGE_ROOT : `${process.env.PAGE_ROOT}/` | |
| const previewUrl = `${root}pr-preview/pr-${process.env.PR_NUMBER}/` | |
| const removed = process.env.PR_ACTION === 'closed' | |
| const body = removed | |
| ? `${marker}\n## 🧹 PR preview removed\n\nThe preview for this pull request was removed after the PR was closed.` | |
| : `${marker}\n## 🚀 PR preview ready\n\n[Open the live preview](${previewUrl})\n\n- Commit: \`${process.env.HEAD_SHA.slice(0, 7)}\`\n- Pages artifact deployed successfully\n- Live URL verified successfully\n- Google Analytics remains disabled in previews\n- Updates automatically when new commits are pushed` | |
| const comments = await github.paginate(github.rest.issues.listComments, { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| per_page: 100, | |
| }) | |
| const existing = comments.find((comment) => comment.body?.includes(marker)) | |
| if (existing) { | |
| await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: existing.id, body }) | |
| } else { | |
| await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body }) | |
| } | |
| - name: Mark PR preview as failed | |
| if: failure() && github.event.action != 'closed' | |
| uses: actions/github-script@v7 | |
| env: | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| with: | |
| script: | | |
| const marker = '<!-- gcsb-pr-preview -->' | |
| const body = `${marker}\n## ❌ PR preview failed\n\nThe preview could not be deployed or verified for commit \`${process.env.HEAD_SHA.slice(0, 7)}\`.\n\nNo live preview link is published until deployment and live verification both succeed.` | |
| const comments = await github.paginate(github.rest.issues.listComments, { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| per_page: 100, | |
| }) | |
| const existing = comments.find((comment) => comment.body?.includes(marker)) | |
| if (existing) { | |
| await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: existing.id, body }) | |
| } else { | |
| await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body }) | |
| } |