feat(ui): reload the SPA on maintenance recovery
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 1m6s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m47s

The deploy that ends a maintenance window may ship a client-incompatible change
(wire/schema bump), and the in-session bundle is the old one. On recovery, reload to
pick up the fresh client instead of just hiding the overlay. Ordering is safe: the edge
maintenance flag (deploy/prod-deploy.sh) spans the WHOLE roll and clears only at script
exit — after the gateway (which serves the embedded SPA) has rolled — so the edge 503s
everything until the entire deploy is live; recovery therefore always serves the new SPA.
A window.__maint.recover() hook + e2e cover the reload.
This commit is contained in:
Ilia Denisov
2026-07-03 22:46:55 +02:00
parent d67e582c03
commit 7dcd62fdd7
4 changed files with 43 additions and 6 deletions
+16
View File
@@ -20,3 +20,19 @@ test('maintenance overlay covers the app and lifts on recovery', async ({ page }
await page.evaluate(() => (window as unknown as { __maint: { off(): void } }).__maint.off());
await expect(page.getByRole('alertdialog')).toHaveCount(0);
});
test('recovery reloads the SPA to pick up the fresh client', async ({ page }) => {
await page.goto('/');
await page.evaluate(() => (window as unknown as { __maint: { on(): void } }).__maint.on());
await expect(page.getByRole('alertdialog')).toBeVisible();
// Real recovery reloads the page (the deploy may have shipped an incompatible client, and the
// running bundle is the old one). Wait for the forced navigation, then confirm the app
// re-bootstrapped: the overlay is gone (the store reset by the reload) and the login is back.
await Promise.all([
page.waitForEvent('load'),
page.evaluate(() => (window as unknown as { __maint: { recover(): void } }).__maint.recover()),
]);
await expect(page.getByRole('alertdialog')).toHaveCount(0);
await expect(page.getByRole('button', { name: /guest/i })).toBeVisible();
});