ci(preview): render Cloudflare config from trusted template (#2207)

This commit is contained in:
ghost
2026-06-05 21:54:40 -06:00
committed by GitHub
parent 1fd5c2e26d
commit 85d7695d1f
4 changed files with 307 additions and 67 deletions

View File

@@ -206,12 +206,14 @@ jobs:
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"
cp trusted/workers/preview/deploy/render_preview_config.cjs "$preview_dir/deploy/render_preview_config.cjs"
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"
sed -i "s/\${PR_NUMBER}/${PR_NUMBER}/g" "$preview_dir/src/index.ts"
sed -i "s/\${PREVIEW_DIAGNOSTICS_NONCE}/${diagnostics_nonce}/g" "$preview_dir/src/index.ts"
cp "$preview_dir/wrangler.toml" "$preview_dir/wrangler.source.toml"
if grep -F "\${PREVIEW_DIAGNOSTICS_NONCE}" "$preview_dir/src/index.ts" >/dev/null; then
echo "Preview diagnostics nonce placeholder was not replaced" >&2
@@ -248,6 +250,7 @@ jobs:
set -euo pipefail
cd "$RUNNER_TEMP/sure-preview-worker"
source_config="$RUNNER_TEMP/sure-preview-worker/wrangler.source.toml"
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}"
@@ -257,23 +260,8 @@ jobs:
# wrangler containers push validates wrangler.toml, so point the trusted
# 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 imageRef = process.env.TEMPORARY_IMAGE_REF;
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(imageRef)}`);
if (updated === original) {
throw new Error('Expected wrangler.toml to contain an image entry to rewrite before push');
}
fs.writeFileSync(configPath, updated);
NODE
PREVIEW_IMAGE_REF="$temporary_image_ref" node ./deploy/render_preview_config.cjs render "$source_config" "$config_path"
cp "$config_path" "$RUNNER_TEMP/wrangler-push.toml"
set +e
./node_modules/.bin/wrangler containers push "$image_tag" 2>&1 | tee "$push_log" | ./deploy/redact_preview_log.sh
@@ -285,19 +273,7 @@ jobs:
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
)"
image_ref="$(node ./deploy/render_preview_config.cjs find "$clean_log")"
if [ -z "$image_ref" ]; then
echo "Could not find Cloudflare registry image reference in wrangler output" >&2
@@ -312,30 +288,12 @@ jobs:
run: |
set -euo pipefail
source_config="$RUNNER_TEMP/sure-preview-worker/wrangler.source.toml"
config_path="$RUNNER_TEMP/sure-preview-worker/wrangler.toml"
# Use Node instead of sed so the replacement preserves TOML string syntax.
node - "$config_path" <<'NODE'
const fs = require('node:fs');
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 (!/^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) {
throw new Error('Expected wrangler.toml to contain an image entry to rewrite');
}
fs.writeFileSync(configPath, updated);
NODE
# Render from the preserved trusted source template so the push-time
# registry ref cannot make the final deploy rewrite stateful.
PREVIEW_IMAGE_REF="$IMAGE_REF" node "$RUNNER_TEMP/sure-preview-worker/deploy/render_preview_config.cjs" render "$source_config" "$config_path"
cp "$config_path" "$RUNNER_TEMP/wrangler-final.toml"
# Print a redacted copy for logs without mutating the config used by deploy.
redacted_config="$RUNNER_TEMP/wrangler-redacted.toml"
@@ -395,27 +353,66 @@ jobs:
run: |
set -euo pipefail
diagnostics_file="$RUNNER_TEMP/preview-diagnostics.json"
diagnostics_dir="$RUNNER_TEMP/preview-diagnostics"
diagnostics_file="$diagnostics_dir/preview-diagnostics.json"
latest_metrics_file="$diagnostics_dir/latest-metrics.json"
polls_log="$diagnostics_dir/metrics-polls.log"
summary_file="$diagnostics_dir/summary.md"
last_error=""
mkdir -p "$diagnostics_dir"
for attempt in $(seq 1 40); do
if curl -fsS --connect-timeout 5 --max-time 15 "$PREVIEW_URL/_container_status" -o "$diagnostics_file"; then
if jq -e '.previewReady == true or .previewFailed == true' "$diagnostics_file" >/dev/null; then
break
if jq -e . "$diagnostics_file" >/dev/null 2>&1; then
jq -c --argjson attempt "$attempt" --arg at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
'{attempt: $attempt, at: $at, previewReady: (.previewReady // false), previewFailed: (.previewFailed // false), progress: (.progress // {}), timings: (.timings // {})}' \
"$diagnostics_file" >> "$polls_log"
jq '{previewReady: (.previewReady // false), previewFailed: (.previewFailed // false), progress: (.progress // {}), timings: (.timings // {})}' "$diagnostics_file" > "$latest_metrics_file"
if jq -e '.previewReady == true or .previewFailed == true' "$diagnostics_file" >/dev/null; then
break
fi
else
last_error="invalid diagnostics JSON on attempt ${attempt}"
raw_snippet="$(head -c 2048 "$diagnostics_file")"
latest_metrics_snapshot="none"
if [ -f "$latest_metrics_file" ]; then
latest_metrics_snapshot="$(head -c 2048 "$latest_metrics_file")"
fi
jq -nc --argjson attempt "$attempt" --arg at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg error "$last_error" --arg latestMetrics "$latest_metrics_snapshot" --arg rawSnippet "$raw_snippet" \
'{attempt: $attempt, at: $at, error: $error, latestMetrics: $latestMetrics, rawSnippet: $rawSnippet}' >> "$polls_log"
fi
else
last_error="curl failed on attempt ${attempt}"
jq -nc --argjson attempt "$attempt" --arg at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg error "$last_error" \
'{attempt: $attempt, at: $at, error: $error}' >> "$polls_log"
fi
sleep 3
done
if [ ! -s "$diagnostics_file" ]; then
if [ ! -s "$diagnostics_file" ] || ! jq -e . "$diagnostics_file" >/dev/null 2>&1; then
jq -n --arg error "${last_error:-preview diagnostics unavailable}" \
--arg url "$PREVIEW_URL" \
'{previewReady: false, previewFailed: false, error: $error, previewUrl: $url}' > "$diagnostics_file"
fi
jq '{previewReady: (.previewReady // false), previewFailed: (.previewFailed // false), progress: (.progress // {}), timings: (.timings // {}), error: (.error // null)}' "$diagnostics_file" > "$latest_metrics_file"
{
echo "# Preview diagnostics"
echo
echo "- PR: ${PR_NUMBER}"
echo "- Commit: ${HEAD_SHA}"
echo "- Preview URL: ${PREVIEW_URL}"
echo "- Preview ready: $(jq -r '.previewReady // false' "$diagnostics_file")"
echo "- Preview failed: $(jq -r '.previewFailed // false' "$diagnostics_file")"
echo "- Phase: $(jq -r '.progress.phase // "unknown"' "$diagnostics_file")"
echo "- Stage: $(jq -r '.progress.stage // "unknown"' "$diagnostics_file")"
echo "- Seconds to Rails ready: $(jq -r '.timings.secondsToRailsReady // "unknown"' "$diagnostics_file")"
echo "- Seconds to demo data ready: $(jq -r '.timings.secondsToDemoDataReady // "unknown"' "$diagnostics_file")"
echo "- Seconds to preview ready: $(jq -r '.timings.secondsToPreviewReady // "unknown"' "$diagnostics_file")"
} > "$summary_file"
jq -c . "$diagnostics_file"
if jq -e '.previewFailed == true' "$diagnostics_file" >/dev/null; then
@@ -441,7 +438,7 @@ jobs:
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: preview-diagnostics-pr-${{ env.PR_NUMBER }}-${{ env.HEAD_SHA }}
path: ${{ runner.temp }}/preview-diagnostics.json
path: ${{ runner.temp }}/preview-diagnostics
if-no-files-found: error
retention-days: 3
@@ -493,6 +490,9 @@ jobs:
}' "$manifest_file" > "$diagnostics_dir/preview-image-manifest.json"
fi
sanitize_copy "$RUNNER_TEMP/sure-preview-worker/wrangler.source.toml" "$diagnostics_dir/wrangler-source.toml"
sanitize_copy "$RUNNER_TEMP/wrangler-push.toml" "$diagnostics_dir/wrangler-push.toml"
sanitize_copy "$RUNNER_TEMP/wrangler-final.toml" "$diagnostics_dir/wrangler-final.toml"
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