mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-07 23:19:14 +00:00
infra: local contour — pre-push gate:small by default, sandbox bootstrap, test:chunk
- .githooks/pre-push + scripts/pre-push-gate.mjs --hook: gate:small runs by default for issue/* branches with an executable diff; C/D-only diffs and non-issue refs are skipped, HP_PREPUSH_GATE=0 turns it off, =1 forces it. A non-HEAD push with an executable diff is rejected (the gate checks the working tree). The gate runs with every GIT_* variable removed: git gives hooks GIT_DIR (and GIT_CONFIG_PARAMETERS with the pusher's -c), and unit tests that `git init` temporary repositories otherwise write into the real one — seen on the first live run. The manual #343 mode is unchanged. - scripts/sandbox-bootstrap.sh: idempotent worktree / deps / chromium (npm @sparticuz/chromium@152.0.0 + Playwright shims) / bundle / check steps, no owner paths or credentials. - scripts/test-chunk.mjs, npm run test:chunk -- N/M: round-robin over test/*.test.mjs sorted by code point. - Tests, seven mutants, docs/DEVELOPMENT.md «Локальный контур за 5 минут», docs/TESTING.md. package.json changed → bundle rebuilt (fingerprint input). Issue: #633 User-Visible: no
This commit is contained in:
@@ -39,6 +39,57 @@ the degradation is accepted.
|
||||
- GitHub pushes: classic PAT (repo+workflow scopes), created via the user's Chrome;
|
||||
stored in `~/.git-credentials` for the session.
|
||||
|
||||
## Local contour in 5 minutes (локальный контур за 5 минут, #633)
|
||||
|
||||
Three commands take a fresh Linux sandbox (agent session, WSL, a clean VM) from
|
||||
nothing to a green smoke, a full unit run in parts and a pre-push gate. Each
|
||||
step fits the ≈3-minute limit of one sandbox command; everything is idempotent,
|
||||
so after a timeout or a sandbox restart the same command is simply repeated.
|
||||
|
||||
```bash
|
||||
# 1. Worktree + dependencies + Chromium + bundle + one Playwright page.
|
||||
# HP_BRANCH picks the branch (taken from origin if it exists there);
|
||||
# without it the worktree is a detached origin/dev.
|
||||
HP_BRANCH=issue/NNN-slug HP_WORKTREE=/tmp/w-NNN bash scripts/sandbox-bootstrap.sh
|
||||
# or step by step: worktree | deps | chromium | bundle | check
|
||||
cd /tmp/w-NNN && node demo/smoke_edge_cases.mjs # AC2 of #633: green
|
||||
|
||||
# 2. The full unit suite in parts that each fit one command.
|
||||
npm run test:chunk -- 1/6 # builds test-build/, then the first sixth
|
||||
npm run test:chunk -- 2/6 --no-build
|
||||
npm run test:chunk -- 3/6 --list # only print the files of the part
|
||||
|
||||
# 3. Push: the pre-push hook runs npm run gate:small for issue/* branches.
|
||||
git push origin issue/NNN-slug
|
||||
HP_PREPUSH_GATE=0 git push origin issue/NNN-slug # explicit opt-out
|
||||
```
|
||||
|
||||
What each command guarantees:
|
||||
|
||||
- **`scripts/sandbox-bootstrap.sh`** — the worktree comes from the clone the
|
||||
script lives in (`HP_CLONE` overrides), `npm ci --ignore-scripts` runs only
|
||||
when `package-lock.json` changed (`HP_SHARED_NODE_MODULES` links a ready
|
||||
`node_modules` instead), Chromium comes from the npm package
|
||||
`@sparticuz/chromium@152.0.0` (the Playwright CDN is closed in the sandbox,
|
||||
the npm registry is not) and gets a shim at every path Playwright expects —
|
||||
a real browser already there is left alone. `bundle` is `npm run
|
||||
bundle:sync`; `check` opens one page in Playwright. The script carries no
|
||||
owner paths and no credentials: pushing is configured separately. Golden
|
||||
frames are still captured only in Linux CI (#455).
|
||||
- **`npm run test:chunk -- N/M`** — `test/*.test.mjs` sorted by code point,
|
||||
file *i* goes to part *i* mod M + 1 (round-robin). Chosen over size-balanced
|
||||
parts so that a file stays in the same part while tests are edited; the M
|
||||
parts together cover every file exactly once (`test/test-chunk.test.mjs`).
|
||||
The test build runs in every part unless `--no-build`, so a part is
|
||||
self-contained after a sandbox restart.
|
||||
- **pre-push** — see [TESTING.md «Локальный набор перед пушем»](TESTING.md#локальный-набор-перед-пушем-343):
|
||||
on by default for `issue/*` branches with an executable diff, skipped when the
|
||||
branch diff against `origin/dev` is class C/D only (review documents,
|
||||
changelogs, bundle), off with `HP_PREPUSH_GATE=0`, forced for any branch with
|
||||
`HP_PREPUSH_GATE=1`. `gate:small` takes minutes; when a push must fit a
|
||||
3-minute command, run `npm run gate:small` separately and push with
|
||||
`HP_PREPUSH_GATE=0`.
|
||||
|
||||
## Local Windows workstation
|
||||
|
||||
The CI contract is **Node.js 22 + Python 3.14**. Do not use Codex's bundled
|
||||
|
||||
+23
-8
@@ -1203,16 +1203,31 @@ node scripts/pre-push-gate.mjs --max-smokes=3 --max-mutants=1
|
||||
прогоняется; **связь не доказана** — отдельная громкая строка, потому что это не
|
||||
«проверять нечего»: молчание стоило #234 бета-блокирующего регресса.
|
||||
|
||||
### Как включить в хук
|
||||
### В хуке — по умолчанию для веток задач (#633)
|
||||
|
||||
Набор намеренно не включён в `.githooks/pre-push` по умолчанию: 20–45 секунд на
|
||||
каждый пуш, включая пуши одной строки документации, — цена, которую стоит платить
|
||||
осознанно. Включается переменной окружения:
|
||||
Прежде набор включался только переменной `HP_PREPUSH_GATE=1`, и ошибки, которые
|
||||
ловит `gate:small`, находил Validate с конвейером через полчаса после пуша. Теперь
|
||||
`.githooks/pre-push` сам вызывает `node scripts/pre-push-gate.mjs --hook`, и тот
|
||||
для каждой пушимой ветки решает:
|
||||
|
||||
```bash
|
||||
export HP_PREPUSH_GATE=1 # в профиль оболочки
|
||||
git push # хук прогонит набор перед процессным гейтом
|
||||
```
|
||||
| Случай | Что делает хук |
|
||||
|---|---|
|
||||
| ветка `issue/*`, в диффе от merge-base с `origin/dev` есть хоть один файл не класса C/D | `npm run gate:small` (`scripts/gate-small.mjs --base=<merge-base>`); красный — push отклонён |
|
||||
| дифф ветки — только класс C/D (документы ревью, changelog, бандл) или пуст | набор не гонится, причина печатается |
|
||||
| ветка не `issue/*`, тег, удаление | набор не гонится |
|
||||
| исполняемый дифф, но пушится не `HEAD` | push отклонён: набор проверяет рабочее дерево, а оно не совпадает с пушимым коммитом |
|
||||
| `HP_PREPUSH_GATE=0` | выключен явно |
|
||||
| `HP_PREPUSH_GATE=1` | гонится для любой ветки и любого диффа |
|
||||
|
||||
Процессный гейт идёт первым — он отвечает за секунды; набор — после, и
|
||||
прогоняются оба, чтобы все провалы были видны одним кругом. `gate:small` идёт
|
||||
минуты: в песочнице агента, где команда живёт ≈ 3 минуты, набор гоняют отдельной
|
||||
командой, а пушат с `HP_PREPUSH_GATE=0` — и пишут об этом в хендоффе.
|
||||
|
||||
Ручной режим выше (`node scripts/pre-push-gate.mjs` без `--hook`) остался как был:
|
||||
tsc, юниты, смоки и мутанты по диффу. Решение хука покрыто
|
||||
`test/pre-push-gate.test.mjs`, включая настоящий `.githooks/pre-push` на
|
||||
временном репозитории.
|
||||
|
||||
Обойти, как и процессный гейт, можно через `git push --no-verify` — и тогда то же
|
||||
самое найдёт Validate, уже после того как код окажется в `dev`.
|
||||
|
||||
Reference in New Issue
Block a user