Skip to content

Split pr-preview-artifact into separate build and deploy jobs with pull_request_target#185

Merged
LittleLittleCloud merged 11 commits intomainfrom
copilot/update-pr-preview-artifact-trigger
Nov 25, 2025
Merged

Split pr-preview-artifact into separate build and deploy jobs with pull_request_target#185
LittleLittleCloud merged 11 commits intomainfrom
copilot/update-pr-preview-artifact-trigger

Conversation

Copy link
Contributor

Copilot AI commented Nov 24, 2025

Refactors the preview deployment workflow into two separate jobs for better security and control: a build job using pull_request trigger and a deploy job using pull_request_target trigger with Cloudflare environment protection.

Changes

Build Job (CI workflow)

  • Builds the website and uploads it as a GitHub Actions artifact
  • Added if: github.event_name == 'pull_request' condition to artifact upload step to avoid wasting storage on main branch pushes
  • No access to secrets, ensuring secure builds from forks

Deploy Job (pull_request_target trigger)

  • Uses pull_request_target with cloudflare environment for secure secret access
  • Discovers and downloads artifacts from the CI workflow run
  • Deploys to Cloudflare Pages using environment-scoped secrets
  • Posts PR comment with artifact download link and deployment URL

Context

This separation provides:

Original prompt

This section details on the original issue you should resolve

<issue_title>update pr-preview-artifact's trigger to pull-request-target and consume environment: cloudflare</issue_title>
<issue_description></issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

…oudflare environment

Co-authored-by: LittleLittleCloud <16876986+LittleLittleCloud@users.noreply.github.com>
Copilot AI changed the title [WIP] Update pr-preview-artifact's trigger to pull-request-target and consume environment Switch pr-preview-artifact to pull_request_target with cloudflare environment Nov 24, 2025
Copy link
Member

@LittleLittleCloud LittleLittleCloud left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot

On build stage, still use pull request trigger. And upload the artifact. Then On deploy stage, use pull request target trigger to deploy to cloudflare and post the comment under thread

@LittleLittleCloud
Copy link
Member

@copilot Fix the comment

Copilot AI and others added 4 commits November 24, 2025 21:36
Co-authored-by: LittleLittleCloud <16876986+LittleLittleCloud@users.noreply.github.com>
Co-authored-by: LittleLittleCloud <16876986+LittleLittleCloud@users.noreply.github.com>
Co-authored-by: LittleLittleCloud <16876986+LittleLittleCloud@users.noreply.github.com>
Co-authored-by: LittleLittleCloud <16876986+LittleLittleCloud@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 24, 2025

@copilot

On build stage, still use pull request trigger. And upload the artifact. Then On deploy stage, use pull request target trigger to deploy to cloudflare and post the comment under thread

Done! The workflow is now split into two jobs:

  • Build job (pull_request): Builds and uploads artifact
  • Deploy job (pull_request_target with cloudflare environment): Deploys to Cloudflare and posts comment

Commit: be6aeba

@copilot Fix the comment

Fixed the PR comment script to:

  • Correctly find the build job's workflow run for artifact link
  • Use consistent artifact naming (website-preview-{prNumber})
  • Add null-safety checks and increase API fetch limit

Commit: be6aeba

Copilot AI changed the title Switch pr-preview-artifact to pull_request_target with cloudflare environment Split pr-preview-artifact into separate build and deploy jobs with pull_request_target Nov 24, 2025
@LittleLittleCloud LittleLittleCloud marked this pull request as ready for review November 24, 2025 23:54
Copilot AI review requested due to automatic review settings November 24, 2025 23:54
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the preview deployment workflow to improve security by separating the build and deployment stages. The CI workflow now builds and uploads the website artifact on pull requests with minimal permissions, while the new deployment workflow downloads this artifact and deploys it to Cloudflare Pages using pull_request_target trigger with environment protection.

Key changes:

  • CI workflow uploads website preview artifacts for all pull requests
  • Preview deployment workflow uses pull_request_target with cloudflare environment for secure secret access
  • Deployment workflow discovers and downloads artifacts from the CI workflow run

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
.github/workflows/ci.yml Added artifact upload step to build website previews for PRs with 30-day retention
.github/workflows/pr-preview-artifact.yml Converted from build-and-deploy to deploy-only workflow using pull_request_target trigger, discovering CI runs, downloading artifacts, and deploying to Cloudflare

Comment on lines +78 to +83
- name: Upload preview artifact
uses: actions/upload-artifact@v4
with:
name: website-preview-${{ github.event.pull_request.number || format('{0}-{1}', github.ref_name, github.run_number) }}
path: website/dist
retention-days: 30
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The artifact upload runs unconditionally on both push and pull_request events. This wastes storage and CI time for pushes to main branch since the preview workflow only consumes artifacts from PRs. Add a condition if: github.event_name == 'pull_request' to this step.

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added if: github.event_name == 'pull_request' condition to the artifact upload step. Also simplified the artifact name since it will only run on pull requests now. Commit: 4486232

Comment on lines +77 to +92
while (status !== 'completed') {
await new Promise(resolve => setTimeout(resolve, 30000)); // Wait 30 seconds

const { data: run } = await github.rest.actions.getWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: runId
});

status = run.status;
console.log(`CI run status: ${status}`);

if (status === 'completed' && run.conclusion !== 'success') {
throw new Error(`CI workflow failed with conclusion: ${run.conclusion}`);
}
}
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The while loop polling for CI completion has no timeout or maximum iteration limit. If the CI workflow hangs or takes unexpectedly long, this step will run until the GitHub Actions job timeout (default 360 minutes), wasting resources. Add a maximum iteration counter (e.g., 40 iterations = 20 minutes) and throw an error if exceeded.

Copilot uses AI. Check for mistakes.
// Look for CI runs that match this PR's head SHA or are associated with this PR
const ciRun = runs.workflow_runs.find(run =>
run.head_sha === headSha ||
(run.pull_requests && run.pull_requests.some(pr => pr.number == prNumber))
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using loose equality (==) to compare PR numbers can lead to type coercion issues. The prNumber variable is a string (from step output), while pr.number is a number. Use strict equality (===) with explicit type conversion: run.pull_requests.some(pr => pr.number === parseInt(prNumber, 10)).

Suggested change
(run.pull_requests && run.pull_requests.some(pr => pr.number == prNumber))
(run.pull_requests && run.pull_requests.some(pr => pr.number === parseInt(prNumber, 10)))

Copilot uses AI. Check for mistakes.
Comment on lines +54 to +57
const ciRun = runs.workflow_runs.find(run =>
run.head_sha === headSha ||
(run.pull_requests && run.pull_requests.some(pr => pr.number == prNumber))
);
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The find() method returns the first matching workflow run without ensuring it's the most recent. If multiple CI runs exist for the same PR (e.g., from re-runs or multiple commits), this could select an older run. Sort runs.workflow_runs by created_at descending before finding: runs.workflow_runs.sort((a, b) => new Date(b.created_at) - new Date(a.created_at)).find(...).

Suggested change
const ciRun = runs.workflow_runs.find(run =>
run.head_sha === headSha ||
(run.pull_requests && run.pull_requests.some(pr => pr.number == prNumber))
);
const ciRun = runs.workflow_runs
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at))
.find(run =>
run.head_sha === headSha ||
(run.pull_requests && run.pull_requests.some(pr => pr.number == prNumber))
);

Copilot uses AI. Check for mistakes.
Comment on lines +59 to +61
if (!ciRun) {
throw new Error(`No CI workflow run found for PR #${prNumber} with SHA ${headSha}`);
}
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message references both PR number and SHA, but when using workflow_dispatch, headSha will be github.sha which may not match the PR's actual head SHA. This makes debugging confusing. Consider enhancing the error message to clarify the search criteria used or fetch the actual PR head SHA from the GitHub API in workflow_dispatch mode.

Copilot uses AI. Check for mistakes.
let comment = `## 🚀 Preview Deployment

A preview build has been generated for this PR!
A preview build has been generated for this PR from CI run [#${ciRunId}](${artifactUrl})!
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The link text '#${ciRunId}' is misleading because it suggests a PR or issue number format, but workflow run IDs are not prefixed with '#' in GitHub's UI. Use descriptive text like 'CI run ${ciRunId}' or 'workflow run ${ciRunId}' instead.

Suggested change
A preview build has been generated for this PR from CI run [#${ciRunId}](${artifactUrl})!
A preview build has been generated for this PR from CI run [CI run ${ciRunId}](${artifactUrl})!

Copilot uses AI. Check for mistakes.
BigBigMiao and others added 3 commits November 24, 2025 16:07
Co-authored-by: LittleLittleCloud <16876986+LittleLittleCloud@users.noreply.github.com>
Co-authored-by: LittleLittleCloud <16876986+LittleLittleCloud@users.noreply.github.com>
@LittleLittleCloud LittleLittleCloud merged commit 08dc71f into main Nov 25, 2025
5 checks passed
@LittleLittleCloud LittleLittleCloud deleted the copilot/update-pr-preview-artifact-trigger branch November 25, 2025 00:55
@github-actions github-actions bot added this to the v0.2.0 milestone Nov 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

update pr-preview-artifact's trigger to pull-request-target and consume environment: cloudflare

4 participants