diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 71a9100..744fb83 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,12 @@ on: permissions: contents: read + deployments: write + pull-requests: write + +concurrency: + group: ci-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: test-and-build: @@ -29,3 +35,50 @@ jobs: run: | npm ci npm run build + - name: Deploy PR preview + if: >- + github.event_name == 'pull_request' && + github.event.pull_request.head.repo.full_name == github.repository + id: preview + uses: cloudflare/wrangler-action@v4 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ vars.CLOUDFLARE_ACCOUNT_ID }} + command: >- + pages deploy dist + --project-name=display-list-explorer + --branch=pr-${{ github.event.number }} + gitHubToken: ${{ secrets.GITHUB_TOKEN }} + - name: Comment preview URLs + if: >- + github.event_name == 'pull_request' && + github.event.pull_request.head.repo.full_name == github.repository && + steps.preview.outcome == 'success' + uses: actions/github-script@v9 + env: + COMMIT_SHA: ${{ github.event.pull_request.head.sha }} + SNAPSHOT_URL: ${{ steps.preview.outputs.deployment-url }} + STABLE_URL: ${{ steps.preview.outputs.pages-deployment-alias-url }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const sha = process.env.COMMIT_SHA; + const snapshotUrl = process.env.SNAPSHOT_URL; + const stableUrl = process.env.STABLE_URL; + const shortSha = sha.slice(0, 7); + const commitUrl = `${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/commit/${sha}`; + const body = [ + "## Cloudflare Pages preview", + "", + `- **Latest PR preview:** [${stableUrl}](${stableUrl})`, + `- **Snapshot for [\`${shortSha}\`](${commitUrl}):** [${snapshotUrl}](${snapshotUrl})`, + "", + "The PR URL always points to the latest deployment; the commit snapshot is immutable.", + ].join("\n"); + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body, + }); diff --git a/README.md b/README.md index 5820d85..be0db37 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,12 @@ swift test The Pages workflow deploys every push to `main` and can also be run manually from any branch through `workflow_dispatch`. It tests the converter, builds the SwiftWasm package, bundles the site with the repository's Pages base path, and deploys the `dist` artifact to . +## Pull request previews + +Pull requests opened from branches in this repository are deployed to an isolated Cloudflare Pages preview after CI succeeds. Each pull request receives a stable branch alias such as `https://pr-42.display-list-explorer.pages.dev`, while every update also creates an immutable deployment URL. GitHub attaches the resulting URL to the pull request as a deployment and posts both URLs in a commit-specific PR comment, preserving access to earlier snapshots as new commits are pushed. + +The workflow expects a `CLOUDFLARE_API_TOKEN` repository secret with Cloudflare Pages edit access and a `CLOUDFLARE_ACCOUNT_ID` repository variable. Pull requests from forks still run the converter and site build, but skip deployment because repository secrets are not exposed to fork workflows. + ## License DisplayList Explorer is available under the MIT License. Third-party attributions are listed in [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md).