zudo-cloudflare-wisdom

Type to search...

to open search from anywhere

PR Preview

CreatedApr 4, 2026Takeshi Takatsudo

Per-PR preview deployment workflow

Standard PR Workflow

PR workflows run type checking, build, and preview deploy in parallel:

name: PR Checks

on:
  pull_request:
    branches:
      - main

concurrency:
  group: pr-checks-${{ github.event.pull_request.number }}
  cancel-in-progress: true

permissions:
  contents: read
  pull-requests: write

💡 Cancel In-Progress for PRs

Unlike production deploys, PR previews should cancel in-progress runs when a new push arrives (cancel-in-progress: true). This saves CI minutes when pushing rapid iterations.

Type Check Job

Run type checking in parallel with the build:

  typecheck:
    name: Type Check
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v5
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v5
        with:
          node-version: 22
      - run: pnpm install --frozen-lockfile
      - run: pnpm check

Preview Deploy Job

Deploy with a branch name based on the PR number:

  preview:
    name: Preview Deploy
    needs: [build-site]
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - name: Download site artifact
        uses: actions/download-artifact@v7
        with:
          name: dist-out
          path: dist-out/

      - name: Prepare and deploy
        id: cf-deploy
        run: |
          mkdir -p deploy/pj/my-site
          cp -r dist-out/. deploy/pj/my-site/
          echo '/ /pj/my-site/ 302' > deploy/_redirects

          PR_NUMBER="${{ github.event.pull_request.number }}"
          npx wrangler@4 pages deploy deploy \
            --project-name=my-site \
            --branch="pr-${PR_NUMBER}" \
            --commit-hash="${GITHUB_SHA}" \
            --commit-message="Preview: PR #${PR_NUMBER}"

          echo "deploy_url=https://pr-${PR_NUMBER}.takazudo-my-site.pages.dev" >> "$GITHUB_OUTPUT"
        env:
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

See Preview Deploys for the full PR comment script.