mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-05 06:08:59 +00:00
infra(process): bundle and review index change only on the way to dev (#657)
Решения владельца: 1б — индекс ревью не пересобирается в ветке задачи, только коммитами, идущими в dev; 2б — бандл меняет только кандидат беты/релиза, стенд dev берёт его из артефакта Validate. - scripts/bundle-policy.mjs: коммит, трогающий dist/** или custom_components/houseplan/frontend/**, обязан нести Release: (хук commit-msg и история в CI через validate-commit-provenance; коммиты с датой автора до 2026-09-27 не судятся); --verify судит целостность свежей сборки всегда, побайтовую сверку с закоммиченной копией — только на коммите, меняющем бандл, или кандидате; --clean. - release-prerelease: публикация отказывает, если отпечаток исходников в закоммиченном манифесте не равен отпечатку дерева (хотфикс поверх кандидата без пересборки). - bundle-sync: по умолчанию только demo/srv/assets; --release (npm run bundle:release) — ещё и custom_components. - rebase-on-dev: конфликт в бандле берёт копию dev, без пересборки и amend. - validate.yml: job dev_build публикует card-bundle головы dev в сиротскую ветку dev-build (scripts/dev-build.mjs); стенд накладывает её demo/stand/update-dev-bundle.sh. - _process.yml: индекс ревью больше не пересобирается при приведении к dev и при публикации документа в ветку задачи. - golden-wsl-artifact/golden-container: сборка перед съёмкой не считается правкой источника, после — bundle:clean. - test/bundle-tree-committed: судит закоммиченный снимок, не диск. - 11 мутантов в реестре; PROCESS/AGENTS/DEVELOPMENT/AUTHOR/REVIEWER. Issue: #657 User-Visible: no
This commit is contained in:
@@ -9460,6 +9460,73 @@ const MUTANT_DEFINITIONS = [
|
||||
}],
|
||||
},
|
||||
// #635: индекс ревью — база знаний; молчаливо неполный индекс хуже отсутствующего.
|
||||
// #657: бандл меняет только кандидат, индекс ревью — только коммиты в dev.
|
||||
{
|
||||
id: "bundle-policy-rule-off",
|
||||
guard: "node --test --test-name-pattern=\"#657 \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u043a\u043e\u043c\u043c\u0438\u0442\u0430\" test/bundle-policy.test.mjs",
|
||||
because: "#657: a non-release commit must not carry the bundle \u2014 otherwise every task rebuilds and commits it again",
|
||||
patches: [{ file: "scripts/bundle-policy.mjs", find: " if (!files.some(isBundlePath)) return [];", replace: " if (files.length >= 0) return [];" }],
|
||||
},
|
||||
{
|
||||
id: "bundle-policy-cutoff-inverted",
|
||||
guard: "node --test --test-name-pattern=\"#657 \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0434\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430\" test/bundle-policy.test.mjs",
|
||||
because: "#657: history before the rule is grandfathered, after it is judged \u2014 an inverted cutoff blocks old branches and frees new ones",
|
||||
patches: [{ file: "scripts/bundle-policy.mjs", find: " if (authorDate && Date.parse(authorDate) < Date.parse(since)) return [];", replace: " if (authorDate && Date.parse(authorDate) > Date.parse(since)) return [];" }],
|
||||
},
|
||||
{
|
||||
id: "bundle-policy-always-compares",
|
||||
guard: "node --test --test-name-pattern=\"#657 CLI --verify\" test/bundle-policy.test.mjs",
|
||||
because: "#657: comparing the committed copy on an ordinary commit would redden every task that no longer commits the bundle",
|
||||
patches: [{ file: "scripts/bundle-policy.mjs", find: " return files.some(isBundlePath) || isCandidateSubject(subject);", replace: " return files.length >= 0 || isCandidateSubject(subject);" }],
|
||||
},
|
||||
{
|
||||
id: "bundle-policy-candidate-not-compared",
|
||||
guard: "node --test --test-name-pattern=\"#657 \u0441\u0432\u0435\u0440\u043a\u0430 \u043a\u043e\u043f\u0438\u0439\" test/bundle-policy.test.mjs",
|
||||
because: "#657: a candidate whose bundle was forgotten must still be compared, or a stale bundle ships",
|
||||
patches: [{ file: "scripts/bundle-policy.mjs", find: " return files.some(isBundlePath) || isCandidateSubject(subject);", replace: " return files.some(isBundlePath);" }],
|
||||
},
|
||||
{
|
||||
id: "bundle-policy-fresh-check-off",
|
||||
guard: "node --test --test-name-pattern=\"#657 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0431\u0435\u0442\u044b\" test/bundle-policy.test.mjs",
|
||||
because: "#657: a hotfix on top of a beta candidate must not publish the candidate's stale bundle",
|
||||
patches: [{ file: "scripts/bundle-policy.mjs", find: " if (!actual || actual !== expectedFingerprint) {", replace: " if (!actual) {" }],
|
||||
},
|
||||
{
|
||||
id: "release-prerelease-skips-fresh-bundle",
|
||||
guard: "node --test --test-name-pattern=\"#657 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0431\u0435\u0442\u044b\" test/bundle-policy.test.mjs",
|
||||
because: "#657: the freshness check has to run in the publishing orchestrator, not only in a unit",
|
||||
patches: [{ file: "scripts/release-prerelease.mjs", find: " assertCommittedBundleFresh(manifest, sourceFingerprint(root));\n", replace: "" }],
|
||||
},
|
||||
{
|
||||
id: "provenance-skips-bundle-rule",
|
||||
guard: "node --test --test-name-pattern=\"#657 \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442 validate-commit-provenance\" test/bundle-policy.test.mjs",
|
||||
because: "#657: the commit-msg hook and the CI history check are where the bundle rule actually bites",
|
||||
patches: [{ file: "scripts/validate-commit-provenance.mjs", find: " errors.push(...bundleCommitErrors(message, normalizedFiles, { authorDate }));", replace: " void bundleCommitErrors;" }],
|
||||
},
|
||||
{
|
||||
id: "bundle-sync-release-by-default",
|
||||
guard: "node --test --test-name-pattern=\"#486/#657 bundle sync\" test/bundle-sync.test.mjs",
|
||||
because: "#657: an ordinary sync must not touch the committed HACS copy",
|
||||
patches: [{ file: "scripts/bundle-sync.mjs", find: "const TARGETS = process.argv.includes('--release') ? [RELEASE_TARGET, DEMO_TARGET] : [DEMO_TARGET];", replace: "const TARGETS = [RELEASE_TARGET, DEMO_TARGET];" }],
|
||||
},
|
||||
{
|
||||
id: "dev-build-publishes-stale-head",
|
||||
guard: "node --test --test-name-pattern=\"#657 dev-build: dev \u0443\u0448\u0451\u043b \u0432\u043f\u0435\u0440\u0451\u0434\" test/dev-build.test.mjs",
|
||||
because: "#657: an older run finishing late must not overwrite the stand bundle of a newer dev head",
|
||||
patches: [{ file: "scripts/dev-build.mjs", find: " if (head && head !== sha) {", replace: " if (head && head === '') {" }],
|
||||
},
|
||||
{
|
||||
id: "dev-build-keeps-history",
|
||||
guard: "node --test --test-name-pattern=\"#657 dev-build: \u043e\u0434\u043d\u0430 \u0432\u0435\u0442\u043a\u0430 \u0431\u0435\u0437 \u0438\u0441\u0442\u043e\u0440\u0438\u0438\" test/dev-build.test.mjs",
|
||||
because: "#657: dev-build is replaced, not appended \u2014 a growing branch would bring the bundle history back",
|
||||
patches: [{ file: "scripts/dev-build.mjs", find: " 'commit-tree', tree, '-m',", replace: " 'commit-tree', tree, '-p', git(['rev-parse', 'HEAD']).out, '-m'," }],
|
||||
},
|
||||
{
|
||||
id: "process-index-on-task-branch",
|
||||
guard: "node --test --test-name-pattern=\"#635/#657 \\\\(1\u0431\\\\)\" test/reviews-index.test.mjs",
|
||||
because: "#657 (1b): the review index is rebuilt only by commits that go to dev; in a task branch it conflicts by construction",
|
||||
patches: [{ file: ".github/workflows/_process.yml", find: " if [ -f \"$doc\" ] && [ \"$target\" = \"dev\" ]; then", replace: " if [ -f \"$doc\" ] && [ -n \"$target\" ]; then" }],
|
||||
},
|
||||
{
|
||||
id: 'reviews-index-skips-self-check',
|
||||
guard: 'node --test --test-name-pattern="#635 индекс покрывает" test/reviews-index.test.mjs',
|
||||
|
||||
Reference in New Issue
Block a user