Preventing "Deploy Succeeded but Nothing Changed" on Cloudflare Workers
# How Workers gradual deployments can leave an old version serving traffic after a successful wrangler deploy, and how to build a deploy script that verifies 100% activation before exiting.
Turnstile site key が未設定のため、このフォームは送信できません。管理者は NEXT_PUBLIC_TURNSTILE_SITE_KEY を設定してください。
[ ]まだコメントはありません。
What happened: deploy succeeded, site stayed old
If you deploy to Cloudflare Workers, you may eventually hit this: wrangler deploy exits successfully, but the site keeps serving the previous version.
The cause is Workers' gradual deployments. An uploaded version does not necessarily receive 100% of traffic immediately — uploading and activating (traffic assignment) are separate operations.
The basic fix
Explicitly activate the version at 100% after uploading:
The remaining problems: obtaining <ID> reliably, and confirming it actually reached 100%.
Getting the version ID without trusting text output
wrangler deploy prints Current Version ID: <uuid>, but human-readable CLI output can change shape at any time. Parse it with a strict regex, and fall back to JSON output when that fails:
js
const UUID = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";function extractCurrentVersionId(output) { return output.match(new RegExp(`Current Version ID:\\s*(${UUID})`, "i"))?.[1] ?? null;}// fallback: take the newest from `wrangler versions list --json`function parseLatestVersionId(jsonText) { const versions = JSON.parse(jsonText); const sorted = [...versions].sort((a, b) => Date.parse(b?.metadata?.created_on ?? 0) - Date.parse(a?.metadata?.created_on ?? 0)); return sorted[0]?.id ?? null;}
JSON is far more shape-stable than display text — prefer --json wherever it exists.
Verifying activation: unverifiable means failed
This is the part that matters. Don't trust the exit code of versions deploy; read deployments list --json and confirm the newest deployment contains your version at 100%:
js
function isVersionActiveAtFullTraffic(jsonText, versionId) { const deployments = JSON.parse(jsonText); const latest = [...deployments].sort((a, b) => Date.parse(b?.created_on ?? 0) - Date.parse(a?.created_on ?? 0))[0]; const versions = Array.isArray(latest?.versions) ? latest.versions : []; return versions.some((v) => v?.version_id === versionId && Number(v?.percentage) === 100);}if (!isVersionActiveAtFullTraffic(deploymentsOutput, versionId)) { throw new Error(`Version ${versionId} was uploaded but could not be confirmed active at 100%`);}
The philosophy is fail-loud. "Looks deployed but the old version is serving" is the worst failure mode, so anything you cannot confirm is treated as a failure.
Mask secrets in CI logs
Deploy logs leak env var names and account details. Pipe everything through a sanitizer so the logs stay safe even if the CI output becomes public:
js
function sanitizeLog(value) { return value .replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, "[email]") .replace(/ca-pub-\d+/g, "[adsense-client]");}
Takeaways
• Uploading and activating are separate operations — activate explicitly with versions deploy
• Prefer --json over parsing display text
• Verify 100% activation via deployments list --json and fail hard when unconfirmed
Turnstile site key が未設定のため、このフォームは送信できません。管理者は NEXT_PUBLIC_TURNSTILE_SITE_KEY を設定してください。