ci: собирать dist до unit-контрактов бюджета (#663)

Issue: #663
User-Visible: no
This commit is contained in:
Matysh
2026-09-26 22:32:36 +03:00
parent efdc9df0c6
commit 060d9ea547
3 changed files with 18 additions and 4 deletions
+6 -2
View File
@@ -780,10 +780,14 @@ jobs:
node scripts/no-new-any.mjs --base "$base" --head "$HEAD_SHA" || status=1
node scripts/no-new-private-writes.mjs --base "$base" --head "$HEAD_SHA" || status=1
exit "$status"
- name: Unit tests
run: npm test
- name: Build
run: npm run build
# Часть unit-контрактов проверяет размеры реально поставляемых графов в
# dist/ (#438, #593, #627). В issue-ветке закоммиченный dist законно
# отстаёт от исходников (#657), поэтому юниты обязаны читать свежую
# сборку — тот же порядок закреплён локальным gate:small.
- name: Unit tests
run: npm test
# Entry, manifest and every content-hashed chunk are one artifact (#337).
# #657: the committed bundle changes only in a release candidate, so the
# fresh build must equal it only there; elsewhere the committed copy
+2 -2
View File
@@ -154,8 +154,8 @@ test('#624 живое дерево: база равна текущим числ
const { metrics, violations } = collectMetrics(root);
assert.deepEqual(violations, [], 'мёртвый код по noUnusedLocals вне порта и харнесса');
const { grown, shrunk } = compareWithBaseline(metrics, baseline);
// bundleBytes судит гейт после сборки (Validate: Unit tests идут до Build,
// локально dist может быть от другого дерева) — здесь пять чисел исходника.
// bundleBytes судит гейт после сборки; здесь пять чисел исходника, а
// фактический свежий dist отдельно проверяют bundle-budget и lint:unused.
const source = (list) => list.filter((s) => s.name !== 'bundleBytes');
assert.deepEqual(source(grown), [], 'связность выросла — вернуть или обосновать');
assert.deepEqual(source(shrunk), [], 'связность упала — опустить базу: node scripts/unused-locals-gate.mjs --update');
+10
View File
@@ -68,6 +68,16 @@ test('бандл собирается один раз и приезжает бр
assert.equal(workflow.match(/node scripts\/bundle-sync\.mjs/g)?.length, 3);
});
test('frontend собирает свежий dist до unit-контрактов бюджета (#663)', () => {
const workflow = read('validate.yml');
const frontend = workflow.slice(workflow.indexOf('\n frontend:\n'), workflow.indexOf('\n dev_build:\n'));
const build = frontend.indexOf('- name: Build');
const unit = frontend.indexOf('- name: Unit tests');
assert.ok(build >= 0 && unit >= 0, 'в frontend должны существовать Build и Unit tests');
assert.ok(build < unit,
'unit-контракты читают dist/ и обязаны идти после свежей сборки, как в gate:small');
});
test('#657 копии бандла сверяются только на релизном коммите, стенд dev — из артефакта', () => {
const workflow = read('validate.yml');
const frontend = workflow.slice(workflow.indexOf('\n frontend:\n'), workflow.indexOf('\n dev_build:\n'));