A phase may only be committed, and a unit may only move to phases/complete/, when this script exits 0. It runs the project's real gate from AGENTS.md §4 (full pytest including browser E2E, ruff check, ruff format --check, pyright) so a failure anywhere blocks the commit, plus language-agnostic repo-hygiene checks that reject tracked files matching .gitignore rules and log-drop / key-material shapes (.env.example stays allowed as a config template). LLM-Generated: true
77 lines
3.4 KiB
Bash
Executable File
77 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# .agents/validate.sh — validation gate for the phased-execution pipeline.
|
|
#
|
|
# A unit is only moved to .agents/phases/complete/ if this script exits 0,
|
|
# and a phase is only COMMITTED if its final pass exits 0 — so this script
|
|
# is the last line of defense for "no phase commits unless 100% passing".
|
|
# It MUST run the project's FULL test suite (every test, not a subset) plus
|
|
# its linter, so a failure anywhere in the project blocks the commit.
|
|
#
|
|
# Adapt the checks below to this project's real test suite, linter, and
|
|
# coverage floor, then commit the result.
|
|
set -uo pipefail
|
|
rc=0
|
|
|
|
if [[ -f pyproject.toml || -f pytest.ini || -f setup.py ]]; then
|
|
# A uv-managed project: the package and every dev tool live in .venv, so
|
|
# plain `python3`/`ruff` cannot see them. The project's real gate (AGENTS.md
|
|
# §4) is these four commands, and the full pytest run includes the browser
|
|
# E2E suite.
|
|
uv run pytest -q || rc=1
|
|
uv run ruff check . || rc=1
|
|
uv run ruff format --check . || rc=1
|
|
uv run pyright || rc=1
|
|
fi
|
|
|
|
if [[ -f package.json ]]; then
|
|
npm test --silent || rc=1
|
|
fi
|
|
|
|
# --- repo hygiene (language-agnostic; runs in every project) ------------------
|
|
# Scoped staging commits everything the phase touched, so a file that is not
|
|
# ignored gets committed — including raw log drops and key material. These
|
|
# gates make the phase fail instead. Fix by untracking, keeping the working
|
|
# copy: git rm --cached <file>
|
|
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
# 1. A tracked file that matches a .gitignore rule should never be tracked.
|
|
junk="$(git ls-files -i -c --exclude-standard 2>/dev/null || true)"
|
|
if [[ -n "$junk" ]]; then
|
|
echo "repo hygiene: TRACKED files match .gitignore rules (untrack with 'git rm --cached <file>'):" >&2
|
|
printf ' %s\n' "$junk" >&2
|
|
rc=1
|
|
fi
|
|
|
|
# 2. Personal-data / key-material file SHAPES that must never be tracked,
|
|
# even in a project with no .gitignore rule for them.
|
|
DANGEROUS='(^|/)[^/]*\.log$|(^|/)[^/]*\.jsonl$|(^|/)\.env($|\.)|\.(pem|key|crt|cer|p12|pfx|keystore|jks)$|(^|/)(id_rsa|id_ecdsa|id_ed25519)(\.pub)?$|(^|/)(credentials|service-account|client_secret)([-a-z0-9]*)\.json$'
|
|
# Project allow-list: `.env.example` is the committed configuration TEMPLATE
|
|
# (default/empty values only; .gitignore deliberately re-allows it with
|
|
# `!.env.example`). The real `.env` and any `.env.local` still fail.
|
|
ALLOW_LIST='^\.env\.example$'
|
|
bad="$(git ls-files | grep -E "$DANGEROUS" | grep -vE "$ALLOW_LIST" || true)"
|
|
if [[ -n "$bad" ]]; then
|
|
echo "repo hygiene: TRACKED files look like log drops / key material (untrack with 'git rm --cached <file>' and add a .gitignore rule):" >&2
|
|
printf ' %s\n' "$bad" >&2
|
|
rc=1
|
|
fi
|
|
|
|
# 3. Project-specific content scan for personal data inside tracked files
|
|
# (client IPs, account ids, ...). Empty by default — fill it in per
|
|
# project, and allow-list documentation ranges (RFC 5737 / 4193 / 3849,
|
|
# 127.0.0.0/8, RFC1918) so fixtures do not trip it. Format: one ERE.
|
|
PII_PATTERNS="${PII_PATTERNS:-}"
|
|
if [[ -n "$PII_PATTERNS" ]]; then
|
|
hits="$(git ls-files -z | xargs -0 grep -IHnE "$PII_PATTERNS" 2>/dev/null || true)"
|
|
if [[ -n "$hits" ]]; then
|
|
echo "personal-data gate: TRACKED files match PII_PATTERNS — redact them:" >&2
|
|
printf ' %s\n' "$hits" >&2
|
|
rc=1
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if [[ $rc -ne 0 ]]; then
|
|
echo "validation FAILED (see output above)"
|
|
fi
|
|
exit "$rc"
|