build: stop committing the stand copy of the bundle

Issue: #255
User-Visible: no
This commit is contained in:
Matysh
2026-08-23 10:15:45 +03:00
parent 7e69b4bb28
commit 6d0fa3b819
17 changed files with 74 additions and 7358 deletions
+2 -2
View File
@@ -147,9 +147,9 @@ jobs:
- name: Build both exact source trees
run: |
npm --prefix candidate run build
cp candidate/dist/houseplan-card.js candidate/demo/srv/assets/houseplan-card.js
(cd candidate && node scripts/bundle-sync.mjs)
npm --prefix baseline run build
cp baseline/dist/houseplan-card.js baseline/demo/srv/assets/houseplan-card.js
(cd baseline && node scripts/bundle-sync.mjs)
- name: Capture base and candidate profiles
working-directory: candidate
-1
View File
@@ -81,7 +81,6 @@ jobs:
npm ci
npm run build
cmp dist/houseplan-card.js custom_components/houseplan/frontend/houseplan-card.js
cmp dist/houseplan-card.js demo/srv/assets/houseplan-card.js
VERSION=${TAG#v}
grep -Fq "$VERSION" dist/houseplan-card.js
(cd custom_components/houseplan && zip -qr ../../houseplan.zip .)
+1 -1
View File
@@ -57,7 +57,7 @@ jobs:
if: ${{ !github.event.release.prerelease }}
run: |
npx playwright install --with-deps chromium
cp dist/houseplan-card.js demo/srv/assets/houseplan-card.js
node scripts/bundle-sync.mjs
npm run continuity:screencast
- name: Upload failed continuity frames
if: ${{ failure() && !github.event.release.prerelease }}
+5 -6
View File
@@ -273,10 +273,9 @@ jobs:
run: npm test
- name: Build
run: npm run build
# Копия стенда больше не коммитится (#255): сверяются две обязательные.
- name: Card bundle snapshots in sync
run: |
cmp dist/houseplan-card.js custom_components/houseplan/frontend/houseplan-card.js
cmp dist/houseplan-card.js demo/srv/assets/houseplan-card.js
run: cmp dist/houseplan-card.js custom_components/houseplan/frontend/houseplan-card.js
smoke:
# Gated on `frontend` so a typecheck failure does not burn browser minutes.
@@ -312,7 +311,7 @@ jobs:
if: steps.pw.outputs.cache-hit != 'true'
run: npx playwright install chromium
- name: Build a fresh bundle for the smokes
run: npm run build && cp dist/houseplan-card.js demo/srv/assets/houseplan-card.js
run: npm run bundle:sync
- name: Smoke suite (шард ${{ matrix.shard }} из 3)
env:
SHARD: ${{ matrix.shard }}
@@ -398,7 +397,7 @@ jobs:
if: steps.pw.outputs.cache-hit != 'true'
run: npx playwright install chromium
- name: Build the exact source under review
run: npm run build && cp dist/houseplan-card.js demo/srv/assets/houseplan-card.js
run: npm run bundle:sync
- name: Capture or verify golden matrix
id: golden
run: |
@@ -464,7 +463,7 @@ jobs:
if: steps.pw.outputs.cache-hit != 'true'
run: npx playwright install chromium
- name: Build the exact candidate source
run: npm run build && cp dist/houseplan-card.js demo/srv/assets/houseplan-card.js
run: npm run bundle:sync
- name: Capture the heaviest Glow state
run: |
npm run benchmark:glow -- --profile=large-house-glow-overlay-v1 --variants=60 --samples=3 --warmups=1 --output=artifacts/performance-smoke/candidate.json
+5
View File
@@ -7,3 +7,8 @@ __pycache__/
.venv-backend/
artifacts/
.agents/
# Копия бандла для стенда: её собирает `npm run bundle:sync`, а в репозитории
# она только росла — 364 версии по 1.16 МБ за семь недель (#255). Обязательных
# копий две: `dist/` (артефакт сборки) и `custom_components/` (её ставит HACS).
demo/srv/assets/houseplan-card.js
+2 -2
View File
@@ -87,7 +87,7 @@ Start with the spec?" is the correct answer, not a smaller patch.
| **A — product** | `src/**`, `custom_components/houseplan/**/*.py`, `manifest.json`, `hacs.json`, i18n, `custom_components/**/translations/**` | yes |
| **B — gates and tooling** | `test/**`, `tests_backend/**`, `demo/**`, `scripts/**`, `.github/workflows/**`, `rollup.config.mjs`, `tsconfig*.json` | yes; may reuse the issue it covers |
| **C — documentation** | `docs/**`, `README*`, `CHANGELOG*`, `AGENTS.md` | not if it is part of its issue's DoD |
| **D — generated** | `dist/**`, `custom_components/houseplan/frontend/**`, `demo/srv/assets/houseplan-card.js`, `demo/golden/baselines/**` | never changes on its own |
| **D — generated** | `dist/**`, `custom_components/houseplan/frontend/**`, `demo/golden/baselines/**` | never changes on its own. The stand copy `demo/srv/assets/houseplan-card.js` is no longer committed (#255): build it with `npm run bundle:sync` |
The table above is a summary; `PROCESS.md` §1 is the authority and now covers the
configuration files this one omits — `package.json`, `package-lock.json`,
@@ -322,7 +322,7 @@ byte-for-byte:
```
cp dist/houseplan-card.js custom_components/houseplan/frontend/houseplan-card.js
cp dist/houseplan-card.js demo/srv/assets/houseplan-card.js
npm run bundle:sync # dist → custom_components + demo/srv/assets (#255)
```
During the implementation cycle the fast gates always run. Since 2026-08-14 the
+2 -2
View File
@@ -35,7 +35,7 @@
| **A. Продукт** | `src/**`, `custom_components/houseplan/**/*.py`, `manifest.json`, `hacs.json`, `src/i18n/*.json`, `custom_components/**/translations/*` | **Да, обязательно.** Только из «Готово к разработке» или дальше |
| **B. Гейты и инструменты** | `test/**`, `tests_backend/**`, `demo/**`, `scripts/**`, весь `.github/**`, `.githooks/**`, `rollup.config.mjs`, `tsconfig*.json`, `package.json`, `package-lock.json`, `pytest.ini`, `.gitignore`, `.gitattributes` | **Да.** Может использовать issue того изменения, которое покрывает; самостоятельная работа над гейтом получает свой issue (тип `tech-debt`) |
| **C. Документация** | `docs/**`, `README*`, `CHANGELOG*`, `AGENTS.md`, `CONTRIBUTING.md`, `PROCESS*.md`, `LICENSE`, `(CODE\|SPEC)-REVIEW-*.md` | Документирование A/B в том же коммите — часть DoD своего issue. Самостоятельная работа над документацией — свой issue |
| **D. Сгенерированное** | `dist/**`, `custom_components/houseplan/frontend/**`, `demo/srv/assets/houseplan-card.js`, `demo/golden/baselines/**` | Никогда не меняется само по себе. Коммит **только** класса D допустим лишь как релизный промоушен или как принятие эталонов с доказательством ревью |
| **D. Сгенерированное** | `dist/**`, `custom_components/houseplan/frontend/**`, `demo/golden/baselines/**` (копия стенда `demo/srv/assets/houseplan-card.js` с #255 не коммитится вовсе) | Никогда не меняется само по себе. Коммит **только** класса D допустим лишь как релизный промоушен или как принятие эталонов с доказательством ревью |
Практический смысл таблицы: «я только поправил тест» и «я только пересобрал
бандл» перестают быть лазейками.
@@ -537,7 +537,7 @@ issue #NN
npx tsc --noEmit
npm test
npm run build && cmp dist/houseplan-card.js custom_components/houseplan/frontend/houseplan-card.js \
&& cmp dist/houseplan-card.js demo/srv/assets/houseplan-card.js
# копия стенда собирается `npm run bundle:sync`, в репозитории её нет (#255)
node scripts/smoke-select.mjs --base origin/dev --head HEAD # какие смоки относятся к диффу
node demo/smoke_<целевые>.mjs
npm run golden:verify # если менялся визуал
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -8,7 +8,7 @@ public materials.
fake `hass` (registries, states, `callWS`, `callService`, floors).
- `srv/assets/` — generated plan SVGs and `icons.js` (`node demo/gen_icons.mjs`,
needs the repo's devDependencies). The card bundle is copied from `dist/`:
`cp dist/houseplan-card.js demo/srv/assets/`.
`npm run bundle:sync` (копия стенда не коммитится, #255).
- `serve.mjs` — playwright launcher (route interception, no web server).
- `smoke_*.mjs` — feature smoke tests; run with a Chromium installed via
`PLAYWRIGHT_BROWSERS_PATH=<dir> npx playwright install chromium-headless-shell`.
+1 -1
View File
@@ -35,7 +35,7 @@ Build and copy the exact current source first:
```bash
npm run build
cp dist/houseplan-card.js demo/srv/assets/houseplan-card.js
npm run bundle:sync
npm run golden:capture
```
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -386,7 +386,7 @@ await finish(browser, out);
`finish` prints the JSON dump (useful on failure), reports named mismatches and
sets a non-zero exit code — including when the card threw during the run. The
suite runs in CI (`smoke` job) against a freshly built bundle; never test the
committed `demo/srv/assets/houseplan-card.js` snapshot.
`demo/srv/assets/houseplan-card.js` copy, which `npm run bundle:sync` writes and which is not committed (#255).
When adding a checklist line marked `[auto: ...]` in docs/TESTING.md, add the
failing check in the same commit — that is what the marker now promises.
+1
View File
@@ -9,6 +9,7 @@
"watch": "rollup -c --watch",
"typecheck": "tsc --noEmit",
"test": "tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs && node --test test/*.test.mjs",
"bundle:sync": "npm run build && node scripts/bundle-sync.mjs",
"invariants": "node scripts/model-invariants.mjs",
"docs:accept": "node scripts/docs-accept.mjs",
"smokes:select": "node scripts/smoke-select.mjs",
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env node
/**
* Разложить собранный бандл по местам, которым он нужен (#255).
*
* Копий две с половиной. `custom_components/houseplan/frontend` — та, что
* ставит HACS, она в репозитории и обязана совпадать с `dist` побайтово.
* `demo/srv/assets` — рабочая копия стенда: её читают браузерные смоки, golden
* и съёмка скриншотов, но в репозитории её больше нет. Раньше «скопировать
* туда» жило шестью разными `cp` в воркфлоу и трижды в документации; когда
* копию забывали, смок врал согласованно (#236).
*/
import { copyFileSync, existsSync, mkdirSync } from 'node:fs';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const SOURCE = resolve(ROOT, 'dist/houseplan-card.js');
const TARGETS = [
'custom_components/houseplan/frontend/houseplan-card.js',
'demo/srv/assets/houseplan-card.js',
];
if (!existsSync(SOURCE)) {
console.error('dist/houseplan-card.js не найден: сначала `npm run build`');
process.exit(1);
}
for (const target of TARGETS) {
const path = resolve(ROOT, target);
mkdirSync(dirname(path), { recursive: true });
copyFileSync(SOURCE, path);
console.log(`бандл → ${target}`);
}
+3 -1
View File
@@ -249,10 +249,12 @@ if (invokedDirectly) {
const sha256Path = (name) => sha256Bytes(readFileSync(name));
const committedFile = (sha, name) => runBytes('git', ['show', `${sha}:${name}`]);
const assertBundleSnapshots = (sha) => {
// Копия стенда (`demo/srv/assets`) больше не коммитится (#255): её собирает
// `npm run bundle:sync` перед браузерными прогонами. В релиз входят ровно
// две копии — артефакт сборки и та, что ставит HACS.
const names = [
'dist/houseplan-card.js',
'custom_components/houseplan/frontend/houseplan-card.js',
'demo/srv/assets/houseplan-card.js',
];
// Hash Git blobs, not checkout bytes. On Windows, Git can expose CRLF in
// the worktree while the exact tagged blobs and Linux release checkout use
+16
View File
@@ -19,3 +19,19 @@ test('the tree carries exactly one *manifest.json: HACS rejects a repository wit
const found = tracked.filter((path) => path.split('/').pop().endsWith('manifest.json'));
assert.deepEqual(found, ['custom_components/houseplan/manifest.json']);
});
// #255. Копия бандла для стенда весит 1.16 МБ и переписывается почти каждым
// продуктовым коммитом: 364 версии за семь недель — примерно четверть всего
// репозитория. Она нужна только браузерным прогонам, которые собирают её сами
// (`npm run bundle:sync`), поэтому в дереве её быть не должно. Проверка стоит
// здесь, а не в глазах ревьюера: вернуть файл обратно проще всего случайно,
// одним `git add -A` после локальной сборки.
test('копия бандла для стенда не коммитится (#255)', () => {
const tracked = execFileSync('git', ['ls-files', '-z', 'demo/srv/assets'], { cwd: ROOT })
.toString('utf8').split('\0').filter(Boolean);
assert.ok(!tracked.includes('demo/srv/assets/houseplan-card.js'),
'demo/srv/assets/houseplan-card.js снова в индексе: соберите его `npm run bundle:sync`, '
+ 'а из коммита уберите');
// Остальное содержимое стенда (иконки, страницы) коммитится и должно остаться.
assert.ok(tracked.length > 0, 'каталог стенда пуст: проверьте, что убрали только бандл');
});