From ffc40c42d2ed5b855f1d123579178aad98731130 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Sun, 23 Aug 2026 15:01:44 +0200 Subject: [PATCH] Regenerate the matrix where the tags are changed, not after the push MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The traceability gate has failed on six commits in a row, every time for the same reason: someone added a `TRACES:` tag and did not regenerate docs/traceability.md. The gate is right to fail — a matrix that disagrees with the tree is worse than none, because it is read as current — but it says so after a push, on a commit that is otherwise fine, and by then the tag and the matrix are two separate things to remember instead of one. A pre-commit hook regenerates it and stages it, so the two travel together. Enabled with `core.hooksPath`, which is a local setting: run git config core.hooksPath .githooks in a fresh clone, or the hook sits there doing nothing. Only runs when something that can carry a tag is staged, and says nothing unless it changed the matrix — a hook that prints on every commit is one people start passing `--no-verify` to. If the report cannot run at all it leaves the matrix alone and lets the commit through: refusing to commit because a build is broken would be a worse failure than the one it prevents. Co-Authored-By: Claude Opus 5 (1M context) --- .githooks/pre-commit | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100755 .githooks/pre-commit diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..f713676 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# Keep docs/traceability.md in step with the tags in the tree. +# +# The gate regenerates the matrix in CI and fails if the result differs from +# what is committed. That is the right check — a matrix that disagrees with the +# tree is worse than none, because it is read as current — but it fails *after* +# a push, on a commit that is otherwise fine, and it has now done so on six +# commits in a row because adding a `TRACES:` tag and regenerating the matrix +# are two actions and only the first is on anyone's mind. +# +# So it happens here instead, where the tags are being changed. +# +# Only when something that can carry a tag is staged: a commit touching +# workflows, packaging or the matrix itself pays nothing. +set -euo pipefail + +staged="$(git diff --cached --name-only --diff-filter=ACMR)" +if ! grep -qE '\.(rs|slint|yaml|md)$' <<< "${staged}"; then + exit 0 +fi +# The matrix is generated from the tree, so regenerating it because it was +# itself edited would be circular. +if [ "$(tr -d '[:space:]' <<< "${staged}")" = "docs/traceability.md" ]; then + exit 0 +fi + +repo="$(git rev-parse --show-toplevel)" +cd "${repo}" + +# Quiet unless it has something to say. A hook that prints on every commit is +# a hook people start passing --no-verify to. +if ! cargo run -q -p traceability -- report >/dev/null 2>&1; then + echo "pre-commit: could not run the traceability report; leaving the matrix alone" >&2 + exit 0 +fi + +if ! git diff --quiet -- docs/traceability.md; then + git add docs/traceability.md + echo "pre-commit: regenerated docs/traceability.md and staged it" +fi