mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-04 21:58:56 +00:00
ci: the backend gate now checks exactly what it promises (#399)
Three claims a green backend used to make, each slightly wider than the truth — and #392 happened in exactly that gap. The frontend pin said 20260826.1 next to homeassistant==2026.8.3, whose package_constraints.txt requires 20260729.7: a combination that exists in no HA release. It was never derived from anything — someone once picked it. It is now taken from the constraints, the source is named in the file, and a test holds both numbers together so raising HA cannot quietly desync them. ruff's include declared three trees while CI linted one. Narrowed the declaration rather than widening CI: the debt in scripts/ and tests_backend/ (56 findings, mostly E402/I001, plus 7 B023 and 5 B017) has its own cost and its own decisions, and belongs in its own task, not in a visibility fix. test/lint-scope.test.mjs now compares the two, so they can only move together. The pin check skipped a workflow when it found neither the package name nor the requirements path — and both vanish together the moment someone returns to Defaulting to user installation because normal site-packages is not writeable, i.e. the gate switched itself off under precisely the change it exists to catch. It now walks the whole .github/workflows directory and decides per file by a positive sign: if a file installs python packages, it must install them from the pins file. Verified by dropping a rogue workflow into the directory — it reddens without touching any list. Three mutants registered and each run by hand. User-Visible: no Issue: #399
This commit is contained in:
@@ -207,16 +207,56 @@ test('гейты диапазона судят от доказанного пр
|
||||
assert.match(frontend, /git merge-base origin\/dev "\$HEAD_SHA"/);
|
||||
});
|
||||
|
||||
test('HA-харнесс ставится по точным версиям, а не по воле резолвера (#392)', () => {
|
||||
/** Ставит ли workflow python-зависимости — по собственному содержимому.
|
||||
*
|
||||
* #399: раньше проверка перебирала два имени и молча пропускала файл, где
|
||||
* не нашлось ни имени пакета, ни пути к пинам. Обе зацепки исчезают разом
|
||||
* при возврате к `pip install pytest …`, то есть гейт выключался ровно тем
|
||||
* изменением, ради которого заведён. Признак теперь положительный: есть
|
||||
* установка python-пакетов — файл обязан ставить их из файла пинов. */
|
||||
const installsPythonDeps = (workflow) => /(?:^|\s)(?:python -m )?pip\s+install\s/.test(workflow);
|
||||
|
||||
test('HA-харнесс ставится по точным версиям, а не по воле резолвера (#392, #399)', () => {
|
||||
// Плавающие версии означают, что «зелёный backend» значит разное в разные
|
||||
// дни: по SHA коммита нельзя сказать, чем его проверяли. Ровно так харнесс
|
||||
// полгода тихо проверял интеграцию против февральского Home Assistant.
|
||||
for (const file of ['validate.yml', 'mutation-gate.yml']) {
|
||||
//
|
||||
// Перебирается ВЕСЬ каталог, а не список имён: новый workflow с
|
||||
// неверсионированной установкой обязан краснеть сам, без правки теста.
|
||||
const workflows = readdirSync(WORKFLOWS).filter((name) => name.endsWith('.yml'));
|
||||
assert.ok(workflows.length >= 2, 'каталог workflows обязан читаться');
|
||||
const installers = [];
|
||||
for (const file of workflows) {
|
||||
const workflow = read(file);
|
||||
if (!/pytest-homeassistant-custom-component|tests_backend\/requirements\.txt/.test(workflow)) continue;
|
||||
if (!installsPythonDeps(workflow)) continue;
|
||||
installers.push(file);
|
||||
assert.match(workflow, /pip install -r tests_backend\/requirements\.txt/,
|
||||
`${file}: зависимости харнесса ставятся мимо файла пинов`);
|
||||
`${file}: ставит python-зависимости мимо файла пинов`);
|
||||
assert.equal(/pip install pytest /.test(workflow), false,
|
||||
`${file}: остался установ без версий`);
|
||||
}
|
||||
// Факт выводится проверкой, а не задаётся ей: список нужен для сообщения об
|
||||
// ошибке, а не для решения, кого проверять.
|
||||
assert.ok(installers.length > 0,
|
||||
'ни один workflow не ставит python-зависимости — либо каталог прочитан'
|
||||
+ ' неверно, либо бэкенд-гейт исчез; и то и другое стоит увидеть');
|
||||
});
|
||||
|
||||
test('#399 AC5: проверка ловит новый workflow, которого нет ни в каком списке', () => {
|
||||
// Синтетический третий файл: при переборе по именам он бы не попал в
|
||||
// проверку вовсе — именно так гейт и обходили бы, ничего не нарушая.
|
||||
const rogue = [
|
||||
'name: rogue',
|
||||
'jobs:',
|
||||
' backend:',
|
||||
' steps:',
|
||||
' - run: pip install pytest voluptuous homeassistant',
|
||||
].join('\n');
|
||||
assert.equal(installsPythonDeps(rogue), true,
|
||||
'установка python-зависимостей обязана распознаваться по содержимому');
|
||||
assert.equal(/pip install -r tests_backend\/requirements\.txt/.test(rogue), false,
|
||||
'и такой файл обязан провалить проверку пинов');
|
||||
// Обратный случай: файл без установки не должен требовать пинов.
|
||||
const innocent = 'name: docs\njobs:\n build:\n steps:\n - run: npm ci\n';
|
||||
assert.equal(installsPythonDeps(innocent), false);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user