mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-25 14:53:34 +00:00
ci: enforce regression tests for fix commits (#517)
* ci: enforce regression tests for fix commits Add a commit-msg hook and CI workflow that require test changes alongside bug fix commits, ensuring every fix includes a regression test that would have caught the bug. - scripts/commit-msg-regression.sh: local git hook (blocks fix commits without test changes; exempts static/docs-only; bypass via [skip-regression-check] marker) - .github/workflows/regression-test-check.yml: CI mirror on PRs (checks title + commit messages; skip via label) - scripts/dev-setup.sh: install hook in step 6 - .github/scripts/create-labels.sh: add skip-regression-check label - CLAUDE.md: document regression test policy Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: address PR review feedback on regression test enforcement - Use here-strings instead of echo|grep to avoid misinterpreting special characters in variables - Use git diff -W (whole-function context) to detect edits inside existing test functions, not just new #[test] attributes - Honor [skip-regression-check] in commit messages in CI (not just the PR label) - Use git rev-parse --git-path hooks for worktree-safe hook install [skip-regression-check] Co-Authored-By: Claude Opus 4.6 <[email protected]> * Update .github/workflows/regression-test-check.yml Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Claude Opus 4.6 <[email protected]> Co-authored-by: Copilot <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.6
Copilot
parent
a22d44f2b2
commit
f60c91e9a7
Executable
+81
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env bash
|
||||
# commit-msg hook: require regression tests for fix commits.
|
||||
#
|
||||
# Installed by scripts/dev-setup.sh as .git/hooks/commit-msg.
|
||||
# Bypass with [skip-regression-check] in the commit message.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
MSG_FILE="$1"
|
||||
FIRST_LINE=$(head -1 "$MSG_FILE")
|
||||
|
||||
# --- 1. Is this a fix commit? ---
|
||||
if ! grep -qiE '^(fix(\(.*\))?|hotfix|bugfix):' <<< "$FIRST_LINE"; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- 2. Skip marker ---
|
||||
if grep -qF '[skip-regression-check]' "$MSG_FILE"; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- 3. Exempt static-only / docs-only changes ---
|
||||
# Get staged files (commit-msg runs after staging is finalized).
|
||||
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR)
|
||||
|
||||
if [ -z "$STAGED_FILES" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ALL_EXEMPT=true
|
||||
while IFS= read -r file; do
|
||||
case "$file" in
|
||||
src/channels/web/static/*) ;;
|
||||
*.md) ;;
|
||||
*) ALL_EXEMPT=false; break ;;
|
||||
esac
|
||||
done <<< "$STAGED_FILES"
|
||||
|
||||
if [ "$ALL_EXEMPT" = true ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- 4. Look for test changes in staged .rs files ---
|
||||
|
||||
# Fast path: new test attributes or test modules in added lines.
|
||||
if git diff --cached -U0 -- '*.rs' | grep -qE '^\+.*(#\[test\]|#\[tokio::test\]|#\[cfg\(test\)\]|mod tests)'; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Whole-function context: detect edits inside existing test functions.
|
||||
# -W shows the full enclosing function, so #[test] appears in context
|
||||
# lines when changes are inside a test function.
|
||||
if git diff --cached -W -- '*.rs' | awk '
|
||||
/^@@/ { if (has_test && has_add) { found=1; exit } has_test=0; has_add=0 }
|
||||
/^ .*#\[test\]/ || /^ .*#\[tokio::test\]/ || /^ .*#\[cfg\(test\)\]/ || /^ .*mod tests/ { has_test=1 }
|
||||
/^\+.*#\[test\]/ || /^\+.*#\[tokio::test\]/ || /^\+.*#\[cfg\(test\)\]/ || /^\+.*mod tests/ { has_test=1 }
|
||||
/^\+[^+]/ { has_add=1 }
|
||||
END { if (has_test && has_add) found=1; exit !found }
|
||||
'; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Also check for new/modified files under tests/
|
||||
if grep -qE '^tests/' <<< "$STAGED_FILES"; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- 5. No test found — block the commit ---
|
||||
echo ""
|
||||
echo "╔══════════════════════════════════════════════════════════════╗"
|
||||
echo "║ REGRESSION TEST REQUIRED ║"
|
||||
echo "║ ║"
|
||||
echo "║ This commit looks like a bug fix but has no test changes. ║"
|
||||
echo "║ Every fix should include a test that reproduces the bug. ║"
|
||||
echo "║ ║"
|
||||
echo "║ Options: ║"
|
||||
echo "║ • Add a #[test] or #[tokio::test] that catches the bug ║"
|
||||
echo "║ • Add [skip-regression-check] to your commit message ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
exit 1
|
||||
+17
-5
@@ -24,14 +24,14 @@ if ! command -v rustup &>/dev/null; then
|
||||
echo "ERROR: rustup not found. Install from https://rustup.rs"
|
||||
exit 1
|
||||
fi
|
||||
echo "[1/5] rustup found: $(rustup --version 2>/dev/null | head -1)"
|
||||
echo "[1/6] rustup found: $(rustup --version 2>/dev/null | head -1)"
|
||||
|
||||
# 2. Add WASM target (required by build.rs for channel compilation)
|
||||
echo "[2/5] Adding wasm32-wasip2 target..."
|
||||
echo "[2/6] Adding wasm32-wasip2 target..."
|
||||
rustup target add wasm32-wasip2
|
||||
|
||||
# 3. Install wasm-tools (required by build.rs for WASM component model)
|
||||
echo "[3/5] Installing wasm-tools..."
|
||||
echo "[3/6] Installing wasm-tools..."
|
||||
if command -v wasm-tools &>/dev/null; then
|
||||
echo " wasm-tools already installed: $(wasm-tools --version)"
|
||||
else
|
||||
@@ -39,13 +39,25 @@ else
|
||||
fi
|
||||
|
||||
# 4. Verify the project compiles
|
||||
echo "[4/5] Running cargo check..."
|
||||
echo "[4/6] Running cargo check..."
|
||||
cargo check
|
||||
|
||||
# 5. Run tests using libsql temp DB (no Docker/external DB needed)
|
||||
echo "[5/5] Running tests (no external DB required)..."
|
||||
echo "[5/6] Running tests (no external DB required)..."
|
||||
cargo test
|
||||
|
||||
# 6. Install git hooks
|
||||
echo "[6/6] Installing git hooks..."
|
||||
HOOKS_DIR=$(git rev-parse --git-path hooks 2>/dev/null) || true
|
||||
if [ -n "$HOOKS_DIR" ]; then
|
||||
mkdir -p "$HOOKS_DIR"
|
||||
SCRIPT_ABS="$(cd "$(dirname "$0")" && pwd)/commit-msg-regression.sh"
|
||||
ln -sf "$SCRIPT_ABS" "$HOOKS_DIR/commit-msg"
|
||||
echo " commit-msg hook installed (regression test enforcement)"
|
||||
else
|
||||
echo " Skipped: not a git repository"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Setup complete ==="
|
||||
echo ""
|
||||
|
||||
Reference in New Issue
Block a user