chore: add pre-push preflight + setup-hooks

Four-block pre-push gate matching the HellionChat pattern:

- Block A (verify-version-consistency.sh): csproj <Version> vs
  repo.json AssemblyVersion / TestingAssemblyVersion / DownloadLink*
  tag presence. Tolerant of repo.json being absent so v0.1.0 (which
  has no public release manifest yet) does not fail at push time;
  the missing-file path turns into the full cross-check once repo.json
  lands.
- Block B: dotnet build Anvil.sln -p:Platform=x64 -c Release. Platform
  pin is forge-wide (Forgeimizer v0.1.0 lesson: solution build defaults
  drift to AnyCPU otherwise).
- Block C: dotnet csharpier check ./Anvil. Catches the accumulated
  formatter drift that hit HellionChat v1.5.6 (12 files) when only
  build was checked per task.
- Block D: markdownlint-cli2 over the repo's *.md files (excludes node_modules,
  bin, obj, .claude, CLAUDE.md).

Plus setup-hooks.sh as the one-shot installer that points
core.hooksPath at .githooks/ and chmods the scripts.

README.md: MD040 fix for the custom-repo URL fence (added text language tag).
This commit is contained in:
2026-05-27 22:25:35 +02:00
parent 90803bcd3c
commit d8efc213e3
5 changed files with 95 additions and 1 deletions
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# verify-version-consistency.sh — Block A of preflight.
#
# v0.1.0 ships before the first repo.json release manifest exists, so this
# script is tolerant when the file is missing - the csproj <Version> is
# the single source of truth at the bootstrap stage. Once repo.json
# lands (probably v0.1.1 or v0.2.0), the missing-file path turns into a
# full csproj <-> repo.json AssemblyVersion + TestingAssemblyVersion +
# DownloadLink* tag check, matching the HellionChat preflight.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
CSPROJ="$ROOT/Anvil/Anvil.csproj"
REPO_JSON="$ROOT/repo.json"
fail() { echo "verify-version-consistency: FAIL — $1" >&2; exit 1; }
ok() { echo "verify-version-consistency: OK — $1"; }
CSPROJ_VER="$(grep -oE '<Version>[^<]+</Version>' "$CSPROJ" | head -1 | sed -E 's/<[^>]+>//g')"
[ -n "$CSPROJ_VER" ] || fail "$CSPROJ has no <Version> element"
if [ ! -f "$REPO_JSON" ]; then
ok "csproj=$CSPROJ_VER (repo.json absent - bootstrap stage, skipping cross-check)"
exit 0
fi
EXPECTED_4DIGIT="${CSPROJ_VER}.0"
REPO_VER="$(jq -r '.[0].AssemblyVersion' "$REPO_JSON")"
[ "$REPO_VER" = "$EXPECTED_4DIGIT" ] \
|| fail "csproj=$CSPROJ_VER expects repo.json AssemblyVersion=$EXPECTED_4DIGIT but got $REPO_VER. Fix: align in $REPO_JSON."
TEST_VER="$(jq -r '.[0].TestingAssemblyVersion' "$REPO_JSON")"
[ "$TEST_VER" = "$EXPECTED_4DIGIT" ] \
|| fail "TestingAssemblyVersion=$TEST_VER must match $EXPECTED_4DIGIT. Fix: align in $REPO_JSON."
TAG="v$CSPROJ_VER"
for KEY in DownloadLinkInstall DownloadLinkUpdate DownloadLinkTesting; do
URL="$(jq -r ".[0].$KEY" "$REPO_JSON")"
case "$URL" in
*"/$TAG/"*) ;;
*) fail "$KEY=$URL does not contain tag $TAG. Fix: update $REPO_JSON $KEY to releases/download/$TAG/latest.zip." ;;
esac
done
ok "csproj=$CSPROJ_VER, repo.json=$EXPECTED_4DIGIT, tag $TAG present in DownloadLinks"