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