diff --git a/.github/scripts/resolve-preview-pull-request.ts b/.github/scripts/resolve-preview-pull-request.ts index 6f3becb..b30406a 100644 --- a/.github/scripts/resolve-preview-pull-request.ts +++ b/.github/scripts/resolve-preview-pull-request.ts @@ -48,6 +48,11 @@ interface PermissionResponse { role_name: string | null; } +interface PullRequestFile { + filename: string; + previous_filename: string | null; +} + const parsePullRequest = (value: JsonValue): PullRequest => { const item = asRecord(value); const base = asRecord(getJsonField(item, "base")); @@ -145,6 +150,17 @@ const parsePermissionResponse = (value: JsonValue): PermissionResponse => { }; }; +const parsePullRequestFile = (value: JsonValue): PullRequestFile => { + const item = asRecord(value); + + return { + filename: asString(getJsonField(item, "filename")), + previous_filename: asOptionalString( + getJsonField(item, "previous_filename") + ), + }; +}; + const payload = parsePayload(await readEvent()); const defaultBranch = payload.repository?.default_branch ?? null; @@ -256,6 +272,30 @@ if (eventName() === "workflow_run" && !matchesWorkflowRun(pullRequest)) { process.exit(0); } +const pullRequestFiles = + eventName() === "pull_request_target" + ? [] + : await githubPaginate( + `/repos/${githubRepository.owner}/${githubRepository.repo}/pulls/${pullRequest.number}/files`, + parsePullRequestFile + ); + +const docsChanged = + eventName() === "pull_request_target" || + pullRequestFiles.some( + (file) => + file.filename.startsWith("apps/web/") || + file.previous_filename?.startsWith("apps/web/") === true + ); + +await setOutput("docs_changed", String(docsChanged)); + +if (!docsChanged && eventName() === "workflow_run") { + console.info( + `Pull request #${pullRequest.number} does not change apps/web; skipping documentation preview deployment.` + ); +} + const username = pullRequest.user?.login ?? null; if (!username) { diff --git a/.github/workflows/deploy-preview.yml b/.github/workflows/deploy-preview.yml index 16a5346..f686956 100644 --- a/.github/workflows/deploy-preview.yml +++ b/.github/workflows/deploy-preview.yml @@ -32,6 +32,7 @@ jobs: outputs: pull_request_number: ${{ steps.resolve.outputs.pull_request_number }} trusted: ${{ steps.resolve.outputs.trusted }} + docs_changed: ${{ steps.resolve.outputs.docs_changed }} steps: - name: Checkout trusted workflow scripts uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -56,7 +57,7 @@ jobs: name: Announce preview approval needs: resolve if: >- - github.event_name == 'workflow_run' && needs.resolve.outputs.pull_request_number != '' && needs.resolve.outputs.trusted != 'true' + github.event_name == 'workflow_run' && needs.resolve.outputs.pull_request_number != '' && needs.resolve.outputs.docs_changed == 'true' && needs.resolve.outputs.trusted != 'true' runs-on: ubuntu-24.04 permissions: issues: write @@ -85,7 +86,7 @@ jobs: deploy: name: Deploy preview (review required) needs: resolve - if: needs.resolve.outputs.pull_request_number != '' && needs.resolve.outputs.trusted != 'true' + if: needs.resolve.outputs.pull_request_number != '' && needs.resolve.outputs.docs_changed == 'true' && needs.resolve.outputs.trusted != 'true' runs-on: ubuntu-24.04 # Required reviewers protect the Cloudflare credentials when the PR author # does not have write access and the deployment executes pull-request code. @@ -110,7 +111,7 @@ jobs: deploy-trusted: name: Deploy preview (trusted author) needs: resolve - if: needs.resolve.outputs.pull_request_number != '' && needs.resolve.outputs.trusted == 'true' + if: needs.resolve.outputs.pull_request_number != '' && needs.resolve.outputs.docs_changed == 'true' && needs.resolve.outputs.trusted == 'true' runs-on: ubuntu-24.04 # A write-level PR author is trusted to run pull-request code with the # repository's Cloudflare credentials, so no reviewer gate is needed.