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

@@ -25,6 +25,7 @@ jobs:
head_sha: ${{ steps.preview.outputs.head_sha }}
is_fork: ${{ steps.preview.outputs.is_fork }}
pr_number: ${{ steps.preview.outputs.pr_number }}
resolution_source: ${{ steps.preview.outputs.resolution_source }}
should_deploy: ${{ steps.preview.outputs.should_deploy }}
steps:
@@ -105,6 +106,7 @@ jobs:
HEAD_SHA: ${{ needs.preview-gate.outputs.head_sha }}
IS_FORK: ${{ needs.preview-gate.outputs.is_fork }}
PR_NUMBER: ${{ needs.preview-gate.outputs.pr_number }}
RESOLUTION_SOURCE: ${{ needs.preview-gate.outputs.resolution_source }}
steps:
- name: Checkout trusted preview tooling
@@ -202,6 +204,9 @@ jobs:
cp trusted/workers/preview/tsconfig.json "$preview_dir/tsconfig.json"
cp trusted/workers/preview/wrangler.toml "$preview_dir/wrangler.toml"
cp -R trusted/workers/preview/src "$preview_dir/src"
mkdir -p "$preview_dir/deploy"
cp trusted/workers/preview/deploy/redact_preview_log.sh "$preview_dir/deploy/redact_preview_log.sh"
chmod 0755 "$preview_dir/deploy/redact_preview_log.sh"
diagnostics_nonce="$(openssl rand -hex 32)"
sed -i "s/\${PR_NUMBER}/${PR_NUMBER}/g" "$preview_dir/wrangler.toml"
@@ -245,32 +250,54 @@ jobs:
cd "$RUNNER_TEMP/sure-preview-worker"
config_path="$RUNNER_TEMP/sure-preview-worker/wrangler.toml"
image_tag="sure-preview-pr-${PR_NUMBER}:${HEAD_SHA}"
temporary_image_ref="registry.cloudflare.com/${CLOUDFLARE_ACCOUNT_ID}/${image_tag}"
push_log="$RUNNER_TEMP/wrangler-containers-push.log"
clean_log="$RUNNER_TEMP/wrangler-containers-push.clean.log"
push_status=0
# wrangler containers push validates wrangler.toml, so point the trusted
# config at the loaded CI image before replacing it with the registry ref.
LOCAL_IMAGE_TAG="$image_tag" node - "$config_path" <<'NODE'
# config at a registry-shaped ref while it pushes the verified local image.
TEMPORARY_IMAGE_REF="$temporary_image_ref" node - "$config_path" <<'NODE'
const fs = require('node:fs');
const configPath = process.argv[2];
const imageTag = process.env.LOCAL_IMAGE_TAG;
const imageRef = process.env.TEMPORARY_IMAGE_REF;
if (!/^sure-preview-pr-[1-9][0-9]*:[a-f0-9]{40}$/.test(imageTag || '')) {
throw new Error('Expected local preview image tag for wrangler containers push');
if (!/^registry\.cloudflare\.com\/[A-Za-z0-9_-]+\/sure-preview-pr-[1-9][0-9]*:[a-f0-9]{40}$/.test(imageRef || '')) {
throw new Error('Expected registry-shaped preview image ref before wrangler containers push');
}
const original = fs.readFileSync(configPath, 'utf8');
const updated = original.replace(/image = "[^"]+"/, `image = ${JSON.stringify(imageTag)}`);
const updated = original.replace(/image = "[^"]+"/, `image = ${JSON.stringify(imageRef)}`);
if (updated === original) {
throw new Error('Expected wrangler.toml to contain an image entry to rewrite before push');
}
fs.writeFileSync(configPath, updated);
NODE
./node_modules/.bin/wrangler containers push "$image_tag" 2>&1 | tee "$push_log"
set +e
./node_modules/.bin/wrangler containers push "$image_tag" 2>&1 | tee "$push_log" | ./deploy/redact_preview_log.sh
push_status=${PIPESTATUS[0]}
set -e
perl -pe 's/\e\[[0-9;]*[A-Za-z]//g' "$push_log" > "$clean_log"
image_ref=$(grep -Eo 'registry\.cloudflare\.com/[^[:space:]]+' "$clean_log" | tail -n 1 | tr -d '\r')
if [ "$push_status" -ne 0 ]; then
exit "$push_status"
fi
image_ref="$(node - "$clean_log" <<'NODE'
const fs = require('node:fs');
const logPath = process.argv[2];
const log = fs.readFileSync(logPath, 'utf8');
const expectedSuffix = `sure-preview-pr-${process.env.PR_NUMBER}:${process.env.HEAD_SHA}`;
const pattern = /registry\.cloudflare\.com\/[A-Za-z0-9_-]+\/sure-preview-pr-[1-9][0-9]*:[a-f0-9]{40}/g;
const matches = [...log.matchAll(pattern)].map((match) => match[0]);
const imageRef = matches.findLast((candidate) => candidate.endsWith(`/${expectedSuffix}`));
if (imageRef) process.stdout.write(imageRef);
NODE
)"
if [ -z "$image_ref" ]; then
echo "Could not find Cloudflare registry image reference in wrangler output" >&2
@@ -292,11 +319,16 @@ jobs:
const configPath = process.argv[2];
const imageRef = process.env.IMAGE_REF;
const expectedSuffix = `sure-preview-pr-${process.env.PR_NUMBER}:${process.env.HEAD_SHA}`;
if (!imageRef || !imageRef.startsWith('registry.cloudflare.com/')) {
if (!/^registry\.cloudflare\.com\/[A-Za-z0-9_-]+\/sure-preview-pr-[1-9][0-9]*:[a-f0-9]{40}$/.test(imageRef || '')) {
throw new Error('Expected a Cloudflare registry image reference');
}
if (!imageRef.endsWith(`/${expectedSuffix}`)) {
throw new Error('Cloudflare registry image reference does not match this preview artifact');
}
const original = fs.readFileSync(configPath, 'utf8');
const updated = original.replace(/image = "[^"]+"/, `image = ${JSON.stringify(imageRef)}`);
if (updated === original) {
@@ -305,7 +337,10 @@ jobs:
fs.writeFileSync(configPath, updated);
NODE
cat "$config_path"
# Print a redacted copy for logs without mutating the config used by deploy.
redacted_config="$RUNNER_TEMP/wrangler-redacted.toml"
"$RUNNER_TEMP/sure-preview-worker/deploy/redact_preview_log.sh" < "$config_path" > "$redacted_config"
cat "$redacted_config"
- name: Deploy to Cloudflare Containers
id: deploy
@@ -321,7 +356,11 @@ jobs:
clean_deploy_log="$RUNNER_TEMP/wrangler-deploy.clean.log"
deploy_once() {
./node_modules/.bin/wrangler deploy --config wrangler.toml --var "PR_NUMBER:${PR_NUMBER}" 2>&1 | tee "$deploy_log"
set +e
./node_modules/.bin/wrangler deploy --config wrangler.toml --var "PR_NUMBER:${PR_NUMBER}" 2>&1 | tee "$deploy_log" | ./deploy/redact_preview_log.sh
local deploy_status=${PIPESTATUS[0]}
set -e
return "$deploy_status"
}
if ! deploy_once; then
@@ -406,12 +445,90 @@ jobs:
if-no-files-found: error
retention-days: 3
- name: Collect preview failure diagnostics
if: failure()
run: |
set -euo pipefail
diagnostics_dir="$RUNNER_TEMP/preview-failure-diagnostics"
manifest_file="$RUNNER_TEMP/preview-image/sure-preview-image.manifest.json"
redaction_helper="$RUNNER_TEMP/sure-preview-worker/deploy/redact_preview_log.sh"
mkdir -p "$diagnostics_dir"
jq -n \
--arg artifactName "$ARTIFACT_NAME" \
--arg headSha "$HEAD_SHA" \
--arg isFork "$IS_FORK" \
--arg prNumber "$PR_NUMBER" \
--arg resolutionSource "$RESOLUTION_SOURCE" \
'{
artifactName: $artifactName,
headSha: $headSha,
isFork: $isFork,
prNumber: $prNumber,
resolutionSource: $resolutionSource
}' > "$diagnostics_dir/preview-request.json"
sanitize_copy() {
local source="$1"
local destination="$2"
if [ -f "$source" ]; then
if [ -x "$redaction_helper" ]; then
"$redaction_helper" < "$source" > "$destination"
else
cp "$source" "$destination"
fi
fi
}
if [ -f "$manifest_file" ]; then
jq '{
artifactVersion,
archivePath,
archiveSha256,
headSha,
imageId,
imageTag,
prNumber
}' "$manifest_file" > "$diagnostics_dir/preview-image-manifest.json"
fi
sanitize_copy "$RUNNER_TEMP/sure-preview-worker/wrangler.toml" "$diagnostics_dir/wrangler.toml"
sanitize_copy "$RUNNER_TEMP/wrangler-containers-push.clean.log" "$diagnostics_dir/wrangler-containers-push.log"
if [ -f "$RUNNER_TEMP/wrangler-deploy.clean.log" ]; then
sanitize_copy "$RUNNER_TEMP/wrangler-deploy.clean.log" "$diagnostics_dir/wrangler-deploy.log"
else
sanitize_copy "$RUNNER_TEMP/wrangler-deploy.log" "$diagnostics_dir/wrangler-deploy.log"
fi
find "$diagnostics_dir" -maxdepth 1 -type f -print
- name: Upload preview failure diagnostics
if: failure()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: preview-failure-diagnostics-pr-${{ env.PR_NUMBER }}-${{ env.HEAD_SHA }}
path: ${{ runner.temp }}/preview-failure-diagnostics
if-no-files-found: error
retention-days: 3
- name: Prepare cleanup metadata
if: success()
run: |
set -euo pipefail
metadata_dir="$RUNNER_TEMP/preview-cleanup-metadata"
mkdir -p "$metadata_dir"
"$RUNNER_TEMP/sure-preview-worker/deploy/redact_preview_log.sh" \
< "$RUNNER_TEMP/sure-preview-worker/wrangler.toml" \
> "$metadata_dir/wrangler.toml"
- name: Store cleanup metadata
if: success()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: preview-cleanup-pr-${{ env.PR_NUMBER }}
path: ${{ runner.temp }}/sure-preview-worker/wrangler.toml
path: ${{ runner.temp }}/preview-cleanup-metadata/wrangler.toml
retention-days: 2
deployment_status: