Files
ComfyAssets-ComfyUI_PromptM…/tests/vendor/browser-image.test.mjs
T
Vito 0652beba90 ci: run the required workflows for the merge queue (#382)
* ci: run the required workflows for the merge queue

main no longer requires a branch to be up to date before it merges, so a
PR no longer re-runs CI after every other merge. The Tests, Code Quality
and Viewer.js workflows also run on merge_group, so the merge queue can
test each PR against the latest main once, in order. The tracked
protection record now says strict: false.

* test(history): give waits that span a database restore their own ceiling

The merge queue's Windows py3.12 job failed
test_restore_or_generation_rotation_between_transactions_discards_evidence
(restore=True): the restore it waits for, a full verify/migrate/backup/
replace cycle, took over the 10 s BLOCK_SECONDS on a busy runner. The two
waits that span a restore now use RESTORE_SECONDS (90 s), which stays under
the suite's 120 s hang watchdog, so a real hang still fails with its thread
dump. Behavioral waits keep BLOCK_SECONDS.

* test(history): drain the writer before every bounded close or dispose

The merge queue's Windows py3.12 job failed
test_saturated_start_cannot_capture_outputs_or_retain_previous_roots:
dispose(2) ran while the writer still worked through 1,024 queued
commands on a busy runner. Like #370, the test now drains first; the 2 s
bound is not what it tests. Four more closes that follow a released
block get the same drain, so the next slow runner can't fail them one at
a time.

* ci(comfyui): run the real-host job in the pinned Playwright image

The real ComfyUI compatibility job installed Chromium with
`playwright install --with-deps`, which pulls the browser's system
packages from Ubuntu's apt mirror on every run. Three runs (#349 run
40367579020, #378, #382 job 122287230985: "Fetched 19.7 MB in 12min 23s
(26.5 kB/s)") spent 11-12 minutes there and were cancelled at the
24-minute limit after all 89 tests had passed.

The job now runs inside mcr.microsoft.com/playwright:v1.64.1-noble, the
same image as the frontend coverage and page workflow jobs, which ships
Chromium and its libraries, so the job has no apt step at all. The
whole job moves rather than only the browser part: the Playwright
suites launch the managed ComfyUI host themselves (PM_TEST_PYTHON), so
splitting the browser off would mean running the host on the runner and
the browser in a container across a network boundary, a larger change
than moving one job whose host is plain Python and pip wheels.

Python follows the other image jobs: the image's own Python 3.12 with a
user-space venv bootstrapped from a checksum-pinned pip wheel (toolcache
setup-python builds do not run in the container). A step fails the job
when the image Python differs from pythonVersion in
tools/vendor/comfyui-runtime.json, so the pinned host stays honest;
torch, torchvision and ComfyUI's requirements install from the same
pins as before. pip and npm download caches replace setup-python's and
setup-node's.

tests/vendor/browser-image.test.mjs now checks this job like the other
browser jobs: image tag equals @playwright/test in the lockfile, no
browser install or apt, no setup-python/setup-node, checksum-pinned pip,
Node 24, and the runtime Python check. The 24-minute limit is unchanged.
2026-10-27 16:35:01 +00:00

52 lines
3.9 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
// Concept comparisons measure layout, and layout depends on the fonts a browser falls back to (the concept names Inter,
// which neither environment ships). Page-workflow jobs therefore run in the same pinned Playwright image as local runs,
// so CI and a developer machine resolve identical fonts and engines.
const workflow = readFileSync(new URL('../../.github/workflows/viewerjs-check.yml', import.meta.url), 'utf8');
const lock = JSON.parse(readFileSync(new URL('../../tools/vendor/package-lock.json', import.meta.url), 'utf8'));
const version = lock.packages['node_modules/@playwright/test'].version;
function job(name) {
const match = workflow.match(new RegExp(`^ ${name}:\\n([\\s\\S]*?)(?=^ [a-z][a-z-]*:\\n|(?![\\s\\S]))`, 'm'));
assert.ok(match, `${name} job exists`);
return match[1];
}
for (const name of ['frontend-coverage', 'browser-workflows']) {
test(`${name} runs in the pinned Playwright image matching @playwright/test`, () => {
const body = job(name);
assert.match(body, new RegExp(`^ container:\\n image: mcr\\.microsoft\\.com/playwright:v${version.replaceAll('.', '\\.')}-noble$`, 'm'));
assert.doesNotMatch(body, /playwright install/, 'browsers and their fonts come from the image, not a runner install');
// Toolcache interpreters are the runner's own builds: their entry points name host paths that do not exist in
// the container (setup-python failed with `spawn .../bin/pip ENOENT`). Use the image's Python and Node.
assert.doesNotMatch(body, /actions\/setup-(python|node)@/);
assert.match(body, /python3 -m venv --without-pip /, 'a user-space venv on the image Python (no ensurepip, no root)');
assert.match(body, /sha256sum -c/, 'the pip wheel that bootstraps the venv is checksum-pinned');
assert.match(body, /node --version \| grep -q '\^v24\\\.'/, 'the image Node is the Node 24 the project requires');
});
}
// The real-host job drives Chromium against a managed ComfyUI. `playwright install --with-deps` pulled the browser's
// system packages from Ubuntu's apt mirror on every run, and three runs (#349, #378, #382) crawled at ~26 kB/s until
// the job hit its limit after every test had passed. The pinned image ships Chromium and its libraries, so the job runs
// there; the image Python must be the reviewed host Python from tools/vendor/comfyui-runtime.json.
test('real ComfyUI compatibility runs in the pinned Playwright image on the reviewed host Python', () => {
const testWorkflow = readFileSync(new URL('../../.github/workflows/test.yml', import.meta.url), 'utf8');
const runtime = JSON.parse(readFileSync(new URL('../../tools/vendor/comfyui-runtime.json', import.meta.url), 'utf8'));
const match = testWorkflow.match(/^ {2}comfyui:\n([\s\S]*?)(?=^ {2}[a-z][a-z-]*:\n|(?![\s\S]))/m);
assert.ok(match, 'comfyui job exists');
const body = match[1];
assert.match(body, new RegExp(`^ container:\\n image: mcr\\.microsoft\\.com/playwright:v${version.replaceAll('.', '\\.')}-noble$`, 'm'));
assert.doesNotMatch(body, /playwright install/, 'Chromium and its system libraries come from the image, not apt');
assert.doesNotMatch(body, /apt-get|actions\/setup-(python|node)@/);
assert.match(body, /python3 -m venv --without-pip /, 'a user-space venv on the image Python');
assert.match(body, /sha256sum -c/, 'the pip wheel that bootstraps the venv is checksum-pinned');
assert.match(body, /node --version \| grep -q '\^v24\\\.'/, 'the image Node is Node 24');
// The image Python is checked against the pin at run time, so a pin or image bump that disagrees fails loudly.
assert.match(body, /steps\.runtime\.outputs\.pythonVersion/, 'the job compares the image Python with the reviewed pin');
assert.match(runtime.pythonVersion, /^3\.12$/, 'the reviewed host Python is the image Python (3.12 on noble)');
});