verify-deploy: retry with backoff and check res.ok
The previous deploy (staff-tags 1.0.5) failed CI at this exact step with a raw "Failed to parse JSON" error, even though the deploy itself had succeeded seconds earlier (confirmed live) - Cloudflare's edge needs a moment to propagate a fresh deploy, and the script had no res.ok check to turn a transient non-OK response into a clear message, let alone retry it.
This commit is contained in:
parent
0439a6a67b
commit
74cc0e61a4
1 changed files with 28 additions and 2 deletions
30
.github/scripts/verify-deploy.mjs
vendored
30
.github/scripts/verify-deploy.mjs
vendored
|
|
@ -4,7 +4,33 @@
|
|||
|
||||
const BASE_URL = process.env.VERIFY_BASE_URL ?? "https://next.jarviscli.dev";
|
||||
|
||||
const idx = await (await fetch(`${BASE_URL}/index.json`)).json();
|
||||
// Cloudflare's edge can take a few seconds to propagate a fresh deploy - the very first run of
|
||||
// this script (2026-08-09, staff-tags 1.0.5) failed with a raw "Failed to parse JSON" error from
|
||||
// a non-OK response fetched immediately after `wrangler deploy` returned, even though the deploy
|
||||
// itself had succeeded (confirmed live seconds later). Retrying with a short backoff instead of
|
||||
// failing on the first transient response avoids that false negative, and checking `res.ok`
|
||||
// turns any real failure into a clear status-code message instead of an opaque parse error.
|
||||
async function fetchWithRetry(url, { attempts = 5, delayMs = 3000, binary = false } = {}) {
|
||||
let lastError;
|
||||
for (let attempt = 1; attempt <= attempts; attempt++) {
|
||||
try {
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) {
|
||||
throw new Error(`${url} responded ${res.status} ${res.statusText}`);
|
||||
}
|
||||
return binary ? await res.arrayBuffer() : await res.json();
|
||||
} catch (e) {
|
||||
lastError = e;
|
||||
if (attempt < attempts) {
|
||||
console.log(`Attempt ${attempt}/${attempts} for ${url} failed (${e.message}), retrying in ${delayMs}ms...`);
|
||||
await new Promise(r => setTimeout(r, delayMs));
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Error(`${url} failed after ${attempts} attempts: ${lastError.message}`);
|
||||
}
|
||||
|
||||
const idx = await fetchWithRetry(`${BASE_URL}/index.json`);
|
||||
const ids = Object.keys(idx.plugins ?? {});
|
||||
if (!ids.length) throw new Error("index.json has no plugins");
|
||||
|
||||
|
|
@ -12,7 +38,7 @@ const [id, plugin] = Object.entries(idx.plugins)[0];
|
|||
const version = plugin.channels.latest;
|
||||
const v = plugin.versions[version];
|
||||
|
||||
const buf = await (await fetch(v.url)).arrayBuffer();
|
||||
const buf = await fetchWithRetry(v.url, { binary: true });
|
||||
const hash = Buffer.from(await crypto.subtle.digest("SHA-256", buf)).toString("hex");
|
||||
|
||||
if (hash !== v.sha256) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue