mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
Ревьюер гонял tsc, юниты и сборку заново в каждом раунде, хотя Validate на том же SHA уже зелёный. Промпт прямо это требовал. Теперь шаг `validated` спрашивает у Validate состояние ровно этого SHA, и доказательство такое же строгое, как у reuse-маркеров (#208): не «недавно было зелено», а completed success на этом коммите. После ребейза SHA другой, прогона для него нет — ревьюер честно гоняет сам, и промпт это говорит. Что Validate не покрывает, в примечании названо отдельно: смоки по диффу, golden при правке рендера, инварианты на конкретной конфигурации. Иначе экономия превратилась бы в «CI зелёный, значит всё проверено». scripts/pre-push-gate.mjs — локальный набор: tsc, юниты, смоки по диффу (smoke-select), мутанты по диффу (mutation-gate --changed). Замер на реальном диапазоне 953f675~1..953f675: 46 секунд на всё вместе с двумя смоками. Три свойства, без которых набор бесполезен: не останавливается на первом упавшем; громко перечисляет, чего не проверял; не претендует на полноту. Бандл не собирает — раскладывает закоммиченный dist, а свежесть проверяет сам продукт через assertFreshDemoBundle внутри смока. В хуке выключен по умолчанию: 20-45 секунд на каждый пуш, включая пуш одной строки документации, — цена осознанная, включается HP_PREPUSH_GATE=1. Дельта-промпт для spec-ревью (пункт 2) уже существует: блок «объём разбора по дельте» из #214 покрывает оба этапа и прямо называет «дифф файла ТЗ или тела issue для spec». Ничего не добавлял. Issue: #343 User-Visible: no
91 lines
3.6 KiB
Bash
Executable File
91 lines
3.6 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
# PROCESS.md 10.1: the blocking process gate lives here, because commits go
|
|
# straight to dev without pull requests and GitHub blocks nothing on its side.
|
|
# CI still runs the same script (10.3), but by then the code is already in dev —
|
|
# that catch-up pass reports, it does not prevent.
|
|
#
|
|
# Git feeds one line per ref on stdin:
|
|
# <local ref> <local sha> <remote ref> <remote sha>
|
|
|
|
repo_root=$(git rev-parse --show-toplevel)
|
|
gate="$repo_root/scripts/process-gate.mjs"
|
|
zero=$(printf '%040d' 0)
|
|
|
|
# The gate reasons about commits. A repository without it — an old checkout, a
|
|
# bisect, a worktree from before the script existed — must still be pushable.
|
|
if [ ! -f "$gate" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Reading issue status needs gh, and a hook that cannot work on a train is a
|
|
# hook people disable. Offline the checks that need no network still run, and the
|
|
# strict pass happens in CI, where gh is always present.
|
|
issues_flag=""
|
|
if command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1; then
|
|
issues_flag="--issues"
|
|
else
|
|
echo "process-gate: gh недоступен, проверка статуса issue пропущена — её выполнит CI" >&2
|
|
fi
|
|
|
|
status=0
|
|
|
|
# Локальный набор гейтов (#343). Выключен по умолчанию намеренно: 20-45 секунд на
|
|
# каждый пуш, включая пуши одной строки документации, — цена, которую стоит
|
|
# платить осознанно. Документация: docs/TESTING.md.
|
|
if [ "${HP_PREPUSH_GATE:-}" = "1" ] && [ -f "$repo_root/scripts/pre-push-gate.mjs" ]; then
|
|
echo "pre-push-gate: HP_PREPUSH_GATE=1, прогоняю локальный набор" >&2
|
|
if ! node "$repo_root/scripts/pre-push-gate.mjs" >&2; then
|
|
status=1
|
|
fi
|
|
fi
|
|
|
|
while read -r local_ref local_sha remote_ref remote_sha; do
|
|
# Deleting a remote branch pushes nothing to examine.
|
|
if [ "$local_sha" = "$zero" ]; then
|
|
continue
|
|
fi
|
|
|
|
# Tags carry no process state of their own: the commit they point at was
|
|
# already checked when it was pushed.
|
|
case "$local_ref" in
|
|
refs/tags/*) continue ;;
|
|
esac
|
|
|
|
if [ "$remote_sha" = "$zero" ]; then
|
|
# A branch that does not exist on the remote yet. Everything it adds on top
|
|
# of dev is new, so that is the range — not the whole history, which would
|
|
# drag in every violation committed before the gate existed.
|
|
base=$(git merge-base "$local_sha" refs/remotes/origin/dev 2>/dev/null || true)
|
|
if [ -z "$base" ]; then
|
|
echo "process-gate: не нашёл общего предка с origin/dev, проверяю последние 20 коммитов" >&2
|
|
base="$local_sha~20"
|
|
fi
|
|
else
|
|
base="$remote_sha"
|
|
fi
|
|
|
|
echo "process-gate: $local_ref, диапазон ${base}..${local_sha}" >&2
|
|
# shellcheck disable=SC2086
|
|
if ! node "$gate" --range "${base}..${local_sha}" --target-ref "$remote_ref" $issues_flag >&2; then
|
|
status=1
|
|
fi
|
|
done
|
|
|
|
if [ "$status" -ne 0 ]; then
|
|
cat >&2 <<'EOF'
|
|
|
|
Push остановлен: нарушен процесс (PROCESS.md §10.2).
|
|
|
|
Починить надо причину, а не симптом. Если нарушение уже опубликовано, его
|
|
исправляет следующий коммит плюс issue с меткой `process` — не force-push
|
|
(§12, правило 17).
|
|
|
|
Обойти проверку можно через `git push --no-verify`, и тогда то же самое найдёт
|
|
job `process-gate` в Validate — уже после того, как код окажется в dev.
|
|
EOF
|
|
fi
|
|
|
|
exit "$status"
|