diff --git a/apps/website/src/lib/releases.ts b/apps/website/src/lib/releases.ts index b0944ae5..ffcea9ca 100644 --- a/apps/website/src/lib/releases.ts +++ b/apps/website/src/lib/releases.ts @@ -18,7 +18,9 @@ const cached = (body: string, seconds: number) => new Response(body, { headers: /** * Latest published release, cached at the edge for five minutes. Without a token the API allows 60 calls an hour - * per Cloudflare IP, so when it refuses, the last known release (kept a week) or the public release pages answer. + * per Cloudflare IP, so when it refuses, github.com says which release is the latest (no API call): the last known + * copy (kept a week) answers while it is still that one, the public release pages once a newer one is out. Never an + * older release just because the API was busy: the app would not see the update. */ export async function latestRelease(): Promise { const cache = await caches.open('godmode-releases'); @@ -32,9 +34,11 @@ export async function latestRelease(): Promise { await Promise.all([cache.put(fresh, cached(body, 300)), cache.put(known, cached(body, 604800))]); return JSON.parse(body); } - const old = await cache.match(known); - if (old) return old.json(); - const release = await releaseFromPages(await latestTag()); + const old = (await cache.match(known)?.then((r) => r?.json() as Promise | undefined)) ?? null; + const tag = await latestTag().catch(() => null); + if (old && (!tag || old.tag_name === tag)) return old; + if (!tag) throw new Error(`GitHub latest release: API ${res?.status ?? 'unreachable'}, release page unreadable`); + const release = await releaseFromPages(tag); await cache.put(fresh, cached(JSON.stringify(release), 300)); return release; } diff --git a/packages/core/test/scheduler.test.ts b/packages/core/test/scheduler.test.ts index 5a43dd81..9bfdbfa8 100644 --- a/packages/core/test/scheduler.test.ts +++ b/packages/core/test/scheduler.test.ts @@ -362,6 +362,8 @@ describe("triggering", () => { }); test("a computer that starts standing in runs the automations that came due since the primary went, once", async () => { + // Only this test's automations: earlier ones may come due at the time of day the suite runs. + exec("UPDATE routines SET enabled = 0"); const hourly = createRoutine({ agentId: agent.id, name: "Hourly", cron: "0 * * * *", timezone: "UTC", prompt: "hourly" }); const ranThere = createRoutine({ agentId: agent.id, name: "Ran there", cron: "0 * * * *", timezone: "UTC", prompt: "done there" }); const before = createRoutine({ agentId: agent.id, name: "Before", cron: "0 0 1 1 *", timezone: "UTC", prompt: "yearly" });