ci(preview): fix Cloudflare registry image deployment (#2124)

* ci(preview): fix Cloudflare registry image deployment

Keep the preview workflow's secret-bearing deploy path on trusted tooling while
rewriting Wrangler config through registry-shaped image refs for push and deploy.
Centralize preview log redaction and extend resolver/security guard coverage for
artifact identity conflicts.

* ci(preview): keep failure diagnostics resilient

* ci(preview): redact private key diagnostics
This commit is contained in:
ghost
2026-06-02 15:11:36 -07:00
committed by GitHub
parent f7b66d40ff
commit 92fa73ef00
5 changed files with 347 additions and 51 deletions

View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail
perl -pe '
s#registry\.cloudflare\.com/[^/]+/#registry.cloudflare.com/<redacted-account>/#g;
s#((?:Authorization|Proxy-Authorization):\s*Bearer\s+)[^[:space:]]+#$1<redacted-token>#gi;
s#((?:X-Auth-Key|X-Auth-Email|X-Api-Key|Api-Key):\s*)[^[:space:]]+#$1<redacted-token>#gi;
s#([?&](?:token|api_key|access_token|refresh_token|auth_token|key|private_key)=)[^&[:space:]]+#$1<redacted-token>#gi;
s#("(?:token|api_key|access_token|refresh_token|auth_token|secret|client_secret|private_key)"\s*:\s*")[^"]*#$1<redacted-token>#gi;
s#(CLOUDFLARE_ACCOUNT_ID=)[^[:space:]]+#$1<redacted-account>#g;
s#((?:CLOUDFLARE_API_TOKEN|API_KEY|ACCESS_TOKEN|REFRESH_TOKEN|AUTH_TOKEN|PRIVATE_KEY)=)[^[:space:]]+#$1<redacted-token>#g;
'

View File

@@ -32,6 +32,10 @@ function uniqueNumbers(candidates) {
return [...new Set(candidates.map((candidate) => candidate.parsed.prNumber))];
}
function uniquePullRequestNumbers(pullRequests) {
return [...new Set(pullRequests.map((pullRequest) => pullRequest.number))];
}
function associatedPullRequestsForHead(associatedPullRequests, context, headSha) {
const baseRepo = repoFullName(context);
@@ -43,15 +47,65 @@ function associatedPullRequestsForHead(associatedPullRequests, context, headSha)
}
function selectPullRequestNumber({ runPullRequest, artifacts, associatedPullRequests, context, headSha }) {
if (runPullRequest?.number) {
const associatedHeadPullRequests = associatedPullRequestsForHead(associatedPullRequests, context, headSha);
const associatedPullRequestNumbers = uniquePullRequestNumbers(associatedHeadPullRequests);
const artifactPullRequestNumbers = uniqueNumbers(artifactCandidates(artifacts, headSha));
const workflowRunPullRequestNumber = runPullRequest?.number ?? null;
if (artifactPullRequestNumbers.length > 1) {
return {
prNumber: runPullRequest.number,
source: "workflow_run",
error: `Workflow run ${headSha} published preview artifacts for multiple pull requests`,
};
}
const associatedHeadPullRequests = associatedPullRequestsForHead(associatedPullRequests, context, headSha);
const artifactPullRequestNumbers = uniqueNumbers(artifactCandidates(artifacts, headSha));
if (artifactPullRequestNumbers.length === 1) {
const artifactPullRequestNumber = artifactPullRequestNumbers[0];
if (workflowRunPullRequestNumber && workflowRunPullRequestNumber !== artifactPullRequestNumber) {
return {
error: `Preview artifact PR ${artifactPullRequestNumber} conflicts with workflow_run PR ${workflowRunPullRequestNumber}`,
};
}
if (
associatedPullRequestNumbers.length > 0 &&
!associatedPullRequestNumbers.includes(artifactPullRequestNumber)
) {
return {
error: `Preview artifact PR ${artifactPullRequestNumber} conflicts with commit-associated PRs ${associatedPullRequestNumbers.join(", ")}`,
};
}
const corroboratingSources = [];
if (workflowRunPullRequestNumber === artifactPullRequestNumber) corroboratingSources.push("workflow_run");
if (associatedPullRequestNumbers.includes(artifactPullRequestNumber)) {
corroboratingSources.push("commit_association");
}
return {
prNumber: artifactPullRequestNumber,
source:
corroboratingSources.length > 0
? `artifact_name+${corroboratingSources.join("+")}`
: "artifact_name",
};
}
if (workflowRunPullRequestNumber) {
if (
associatedPullRequestNumbers.length > 0 &&
!associatedPullRequestNumbers.includes(workflowRunPullRequestNumber)
) {
return {
error: `workflow_run PR ${workflowRunPullRequestNumber} conflicts with commit-associated PRs ${associatedPullRequestNumbers.join(", ")}`,
};
}
return {
prNumber: workflowRunPullRequestNumber,
source: "workflow_run",
};
}
if (associatedHeadPullRequests.length === 1) {
return {
@@ -61,34 +115,11 @@ function selectPullRequestNumber({ runPullRequest, artifacts, associatedPullRequ
}
if (associatedHeadPullRequests.length > 1) {
const associatedNumbers = new Set(associatedHeadPullRequests.map((pullRequest) => pullRequest.number));
const artifactMatches = artifactPullRequestNumbers.filter((number) => associatedNumbers.has(number));
if (artifactMatches.length === 1) {
return {
prNumber: artifactMatches[0],
source: "artifact_and_commit_association",
};
}
return {
error: `Workflow run head SHA ${headSha} is associated with multiple open pull requests and no single preview artifact matched`,
};
}
if (artifactPullRequestNumbers.length === 1) {
return {
prNumber: artifactPullRequestNumbers[0],
source: "artifact_name",
};
}
if (artifactPullRequestNumbers.length > 1) {
return {
error: `Workflow run ${headSha} published preview artifacts for multiple pull requests`,
};
}
return {
prNumber: null,
source: "none",
@@ -186,6 +217,7 @@ async function resolvePreviewRequest({ github, context, core }) {
core.setOutput("head_sha", headSha);
core.setOutput("is_fork", String(isFork));
core.setOutput("pr_number", String(prNumber));
core.setOutput("resolution_source", selected.source);
core.setOutput("should_deploy", "true");
}