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
@@ -0,0 +1,107 @@
|
||||
name: Regression Test Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
regression-test:
|
||||
name: Regression test enforcement
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check for regression tests
|
||||
env:
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_LABELS: ${{ join(github.event.pull_request.labels.*.name, ',') }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
BASE_REF="origin/${{ github.event.pull_request.base.ref }}"
|
||||
|
||||
# --- 1. Is this a fix PR? Check title first, then commit messages ---
|
||||
IS_FIX=false
|
||||
|
||||
if grep -qiE '^(fix(\(.*\))?|hotfix|bugfix):' <<< "$PR_TITLE"; then
|
||||
IS_FIX=true
|
||||
fi
|
||||
|
||||
if [ "$IS_FIX" = false ]; then
|
||||
COMMITS=$(git log --format='%s' "${BASE_REF}..HEAD")
|
||||
if grep -qiE '^(fix(\(.*\))?|hotfix|bugfix):' <<< "$COMMITS"; then
|
||||
IS_FIX=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$IS_FIX" = false ]; then
|
||||
echo "Not a fix PR — skipping regression test check."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Fix PR detected."
|
||||
|
||||
# --- 2. Skip label or commit message marker ---
|
||||
if grep -qF ',skip-regression-check,' <<< ",$PR_LABELS,"; then
|
||||
echo "skip-regression-check label present — skipping."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
COMMIT_BODIES=$(git log --format='%B' "${BASE_REF}..HEAD")
|
||||
if grep -qF '[skip-regression-check]' <<< "$COMMIT_BODIES"; then
|
||||
echo "[skip-regression-check] found in commit message — skipping."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- 3. Exempt static-only / docs-only changes ---
|
||||
CHANGED_FILES=$(git diff --name-only "${BASE_REF}...HEAD")
|
||||
|
||||
if [ -z "$CHANGED_FILES" ]; then
|
||||
echo "No changed files — skipping."
|
||||
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 <<< "$CHANGED_FILES"
|
||||
|
||||
if [ "$ALL_EXEMPT" = true ]; then
|
||||
echo "All changes are static assets or docs — skipping."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- 4. Look for test changes ---
|
||||
|
||||
# Fast path: new test attributes or test modules in added lines.
|
||||
if git diff "${BASE_REF}...HEAD" -U0 -- '*.rs' | grep -qE '^\+.*(#\[test\]|#\[tokio::test\]|#\[cfg\(test\)\]|mod tests)'; then
|
||||
echo "Test changes found in .rs files."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Whole-function context: detect edits inside existing test functions.
|
||||
if git diff "${BASE_REF}...HEAD" -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
|
||||
echo "Test changes found in existing test functions."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if grep -qE '^tests/' <<< "$CHANGED_FILES"; then
|
||||
echo "Test file changes found under tests/."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- 5. No tests found ---
|
||||
echo "::warning::This PR looks like a bug fix but contains no test changes. Every fix should include a regression test. Add a #[test] or #[tokio::test], or apply the 'skip-regression-check' label if not feasible."
|
||||
exit 1
|
||||
Reference in New Issue
Block a user