From 280deac494d8984c3a4ef314b8cb331ac4a83c0b Mon Sep 17 00:00:00 2001 From: Matheus Martins Date: Mon, 27 Jul 2026 21:37:21 +0000 Subject: [PATCH] ci(mutation): run mutation tests only when src/ or test/ changed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Infection is the slowest CI job (full coverage run + thousands of mutants), and it can only change outcome when the mutated code (src/) or the tests that kill mutants (test/) change. Gate it: a `changes` job (dorny/paths-filter) detects whether src/ or test/ was touched, and the `infection` job runs only when it was — so a docs- or config-only PR skips mutation entirely. The `needs: phpunit` ordering is preserved (mutation still waits for unit tests). --- .github/workflows/ci-core.yml | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index 9aef9380..f622b027 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -14,6 +14,27 @@ concurrency: cancel-in-progress: true jobs: + # Detect whether this PR/push touches code that mutation testing covers. + # Infection is expensive, so the `infection` job below runs only when src/ + # or test/ changed — a docs-only or config-only change skips it. + changes: + name: Detect code changes + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + outputs: + code: ${{ steps.filter.outputs.code }} + steps: + - uses: actions/checkout@v4 + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + code: + - 'src/**' + - 'test/**' + phpunit: # 8.4 is the supported/default runtime and runs the full suite minus the # `php85` group; a dedicated 8.5 container runs only that group, which @@ -116,7 +137,10 @@ jobs: infection: name: Mutation testing runs-on: ubuntu-latest - needs: phpunit + # Only after unit tests pass, and only when src/ or test/ changed + # (see the `changes` job) — mutation is skipped for docs/config-only work. + needs: [phpunit, changes] + if: needs.changes.outputs.code == 'true' steps: - uses: actions/checkout@v4