mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
ci(mutants): skip the nightly registry on a proven tree; install only the shard's environment
#620. Mutants were ~70 % of CI machine time. 1. mutation-gate.yml: a green full run (aggregator verified all six shards) leaves a cache marker keyed by material tree + workflow SHA. A scheduled night with the same tree and workflow, marker not older than 7 days, skips the shards and writes "reused from run N" to the run summary. Red runs leave no marker, so the next night runs again and still files the issue (#472). Manual dispatch always runs the full registry. Decision is a pure function in scripts/mutation-nightly-reuse.mjs. 2. changed_mutants: the shard plan (already computed before setup, #518) now names the environment of its guards (plan-browser=/plan-python=, from scripts/mutation-environment.mjs). Python + backend deps only for shards with pytest guards, Chromium only for shards whose guards reach Playwright; pip wheels cached. Every shard still runs and reports, so the six mutant jobs of the review proof are unchanged. Item 3 of the issue (smoke guards -> node --test) is out of scope here. Issue: #620 User-Visible: no
This commit is contained in:
@@ -482,6 +482,36 @@ test('#518: пустой план шарда не ставит окружени
|
||||
assert.match(save, /if: always\(\)/);
|
||||
});
|
||||
|
||||
test('#620 AC2: Python и Chromium ставятся только шарду, чьим гардам они нужны', () => {
|
||||
const workflow = read('validate.yml');
|
||||
const start = workflow.indexOf('\n changed_mutants:\n');
|
||||
const job = workflow.slice(start, workflow.indexOf('\n frontend:\n', start));
|
||||
const stepOf = (needle) => {
|
||||
const at = job.indexOf(needle);
|
||||
assert.ok(at > 0, `нет шага ${needle}`);
|
||||
const from = job.lastIndexOf('\n - ', at);
|
||||
const to = job.indexOf('\n - ', at + needle.length);
|
||||
return job.slice(from, to < 0 ? job.length : to);
|
||||
};
|
||||
// План называет окружение; при непустом плане непрочитанная строка — «ставить».
|
||||
const plan = stepOf('name: План шарда');
|
||||
assert.match(plan, /echo "browser=\$\{browser:-true\}" >> "\$GITHUB_OUTPUT"/);
|
||||
assert.match(plan, /echo "python=\$\{python:-true\}" >> "\$GITHUB_OUTPUT"/);
|
||||
assert.match(plan, /sed -n 's\/\^plan-browser=\/\/p'/);
|
||||
assert.match(plan, /sed -n 's\/\^plan-python=\/\/p'/);
|
||||
for (const step of ['actions/setup-python@', 'pip install -r tests_backend/requirements.txt']) {
|
||||
assert.match(stepOf(step), /if: steps\.plan\.outputs\.count != '0' && steps\.plan\.outputs\.python == 'true'\n/, step);
|
||||
}
|
||||
for (const step of ['name: Кэш браузеров Playwright', 'npx playwright install --with-deps chromium']) {
|
||||
assert.match(stepOf(step), /if: steps\.plan\.outputs\.count != '0' && steps\.plan\.outputs\.browser == 'true'/, step);
|
||||
}
|
||||
// npm ci и сам прогон нужны любому непустому плану — без условия по окружению.
|
||||
for (const step of ['run: npm ci', 'name: Затронутые мутанты ловятся']) {
|
||||
assert.doesNotMatch(stepOf(step), /outputs\.(browser|python)/, step);
|
||||
}
|
||||
assert.match(stepOf('actions/setup-python@'), /cache: pip\n\s+cache-dependency-path: tests_backend\/requirements\.txt/);
|
||||
});
|
||||
|
||||
test('ручной/ночной полный прогон не делит concurrency с push (#479)', () => {
|
||||
const text = read('validate.yml');
|
||||
assert.match(text, /group: validate-\$\{\{ github\.event_name == 'workflow_dispatch' && 'dispatch-' \|\| '' \}\}/);
|
||||
|
||||
Reference in New Issue
Block a user