v0.10.0 — the push gate can run more than one command, and says why it blocked
Minor. The generated espalier/hooks/pre-push-gate.sh changes shape. No pipeline stage, lane, gate semantic, or verdict changes.
{build_command} / {lint_command} / {test_command} are now function bodies
The old template substituted the test command inside a command substitution — TEST_OUTPUT=$({test_command} 2>&1) — so the value had to be a single expression. A repo needing several suites (one per container in a Docker-first stack, one per workspace in a monorepo) could not be expressed at all; init had to hand-write a bespoke gate, which then fell out of the migration chain because every later script's anchors missed it.
run_tests() {
{test_command}
}
TEST_OUTPUT=$(run_tests 2>&1)Single command or multi-line block. A block must return non-zero if any step fails — join with &&, or end each step with || return 1.
Build and lint stop discarding stderr
They ran <cmd> 2>/dev/null and, on failure, printed BLOCKED: Build fails and nothing else. Output is now captured and its tail printed. A gate that blocks without saying why gets disabled.
New: scripts/migrate-v0.9.6-to-v0.10.0.sh
A template change alone reaches only fresh inits. This rewrites the installed gate's three spans, preserving the commands substituted at init.
- Each span is handled independently — a gate half-migrated by running the v0.9.2 step against a v0.10.0 plugin has
run_testswith old build/lint. - A customised gate is left completely untouched, reported with the manual change list, exit 0.
A migrated gate is byte-identical to a fresh v0.10.0 init with the same commands. Idempotent.
Fixed
migrate-v0.9.1-to-v0.9.2.sh asserted ^TEST_OUTPUT=, which a customised gate can never satisfy — a correct migration reported ✗. The hard check is now the real invariant (no {test_command} placeholder survived); the shape assertion is warn-only.
Upgrading
/espalier-migrate — detects and applies the gate reshape. If your gate was customised at init, it is left alone and the manual change list is printed.
Full changelog: v0.9.6...v0.10.0