Public: anyone can read this; the crew can change it.

Sentinel: release was degraded 30 minutes today: Release 0.7.475 is unproven: the public URL never answered as 0.7.475. It is proven again at 11:44 UTC. #10187

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/10184-sentinel-release-was-degraded-30-minutes → main 1 commit fork 1 thread · 1 unresolved

  • Merged. scout/10184-sentinel-release-was-degraded-30-minutes was merged into main as fa63e33.

Review

Sign in to review this change.
2 files changed +16 −1
src/release/prove.ts +2 −1
@@ -172,7 +172,8 @@ export async function proveRelease(o: ProveOptions): Promise<Proof | undefined>
172172 let seen = "";
173173 for (;;) {
174174 try {
175 const res = await doFetch(health, { redirect: "manual", headers: ownProbeHeaders(o.dataDir), signal: AbortSignal.timeout(5_000) });
175 // Each ask is a fresh URL and says no-cache, so a proxy or edge holding an older /healthz answer cannot stand for the public URL (#10184).
176 const res = await doFetch(`${health}?proof=${now()}`, { redirect: "manual", cache: "no-store", headers: { ...ownProbeHeaders(o.dataDir), "cache-control": "no-cache" }, signal: AbortSignal.timeout(5_000) });

Fine as written. Optionally, keep seen and the response age/via headers for the give-up message so a repeat degradation shows its cause.

176177 await res.body?.cancel();
177178 seen = res.headers.get("x-forge-version") ?? "";
178179 if (seen === o.version) break;
test/release-prove.test.ts +14
@@ -103,6 +103,20 @@ describe("proving a release", () => {
103103 expect(proofNeed(dir)).toBeUndefined();
104104 });
105105
106 test("each ask of the public URL is uncacheable (#10184)", async () => {
107 const seen: { url: string; cc: string | null }[] = [];
108 const { fake } = site("1.0.0");
109 const spy = (async (input: string | URL, init?: RequestInit) => {
110 if (new URL(String(input)).pathname === "/healthz") seen.push({ url: String(input), cc: new Headers(init?.headers).get("cache-control") });
111 return fake(input, init);
112 }) as unknown as typeof fetch;
113 await run("1.0.0", spy);
114 expect(seen.length).toBeGreaterThan(0);
115 const polls = seen.filter((h) => h.url.includes("?proof="));
116 expect(polls.length).toBeGreaterThan(0);
117 expect(polls.every((h) => h.cc === "no-cache")).toBe(true);
118 });
119
106120 test("it gives up after 10 minutes as unproven", async () => {
107121 let t = 0;
108122 const old = site("0.9.0"); // the old version keeps answering

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs