mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-10 04:36:40 +00:00
The docs suite of run 36745666606 ends on
Timed out waiting 3540s for the test suite to run
6 did not run
and says nothing about what it waited for. `test-languages.js:15` sets
`test.setTimeout(resolveTimeout(5_400_000))` and `_shared.js:40` capped the poll
with the same `resolveTimeout`, so both land on `budget - SUITE_RESERVE_MS` and
expire together. Playwright's test timeout wins the race, and the poll's own
message, "Expected the German site of the deployed working tree to be built",
is never printed.
`pollStatus` now keeps 60 s of its budget back, with a 30 s floor so a small
budget cannot go negative. The reserve sits in the helper rather than at its
three call sites, the same shape `SUITE_RESERVE_MS` uses in
`test-e2e-playwright/files/timeouts.js` to stop one test from consuming the
whole suite.
This does not make the cluster pass. The `deployed` build takes longer than the
suite budget allows, so the job stays red; it stops being red for an unstated
reason. Curing it means building that version before the suite runs or making
the build fit, which is role surgery and not this change.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
65 lines
1.9 KiB
JavaScript
65 lines
1.9 KiB
JavaScript
const { expect } = require("@playwright/test");
|
|
const { resolveTimeout } = require("./timeouts");
|
|
const {
|
|
normalizeBaseUrl,
|
|
requireDotenvValue,
|
|
} = require("./personas");
|
|
|
|
const appBaseUrl = normalizeBaseUrl(requireDotenvValue(process.env.APP_BASE_URL, "APP_BASE_URL"));
|
|
const canonicalDomain = requireDotenvValue(process.env.CANONICAL_DOMAIN, "CANONICAL_DOMAIN");
|
|
const RELEASE_TAG = /^v\d+\.\d+\.\d+$/;
|
|
|
|
async function fetchVersions(request) {
|
|
const response = await request.get(`${appBaseUrl}/api/versions`, { timeout: resolveTimeout(30_000) });
|
|
expect(response.status(), "Expected the versions api to answer").toBe(200);
|
|
return response.json();
|
|
}
|
|
|
|
async function versionState(request, name) {
|
|
const version = (await fetchVersions(request)).find((candidate) => candidate.name === name);
|
|
return version ? version.state : "unknown";
|
|
}
|
|
|
|
let lastTransportError = null;
|
|
|
|
async function statusOf(request, url) {
|
|
try {
|
|
const response = await request.get(url, { failOnStatusCode: false, maxRedirects: 0, timeout: resolveTimeout(30_000) });
|
|
lastTransportError = null;
|
|
return response.status();
|
|
} catch (error) {
|
|
lastTransportError = error;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
const POLL_REPORT_RESERVE_MS = 60_000;
|
|
|
|
async function pollStatus(request, url, expected, message, timeout) {
|
|
lastTransportError = null;
|
|
const budget = Math.max(
|
|
30_000,
|
|
resolveTimeout(timeout) - POLL_REPORT_RESERVE_MS,
|
|
);
|
|
try {
|
|
await expect
|
|
.poll(() => statusOf(request, url), { message, timeout: budget, intervals: [30_000] })
|
|
.toBe(expected);
|
|
} catch (failure) {
|
|
if (!lastTransportError) throw failure;
|
|
throw new Error(
|
|
`${failure.message}\nlast transport error reaching ${url}: ${lastTransportError.message}`,
|
|
{ cause: failure },
|
|
);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
appBaseUrl,
|
|
canonicalDomain,
|
|
RELEASE_TAG,
|
|
fetchVersions,
|
|
versionState,
|
|
pollStatus,
|
|
};
|