From 758cec0e9a8c307e8134268136a8d47dba8488d7 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Fri, 9 Oct 2026 21:35:30 +0400 Subject: [PATCH] ci: add mutation testing with Infection Infection is installed in the workflow instead of require-dev: it needs PHP >= 8.3 while the package supports 8.2, and its Phar can't run Testo mutants yet (the bundled adapter's bootstrap references the unscoped `IncludeInterceptor` class). Assisted-By: Claude Opus 5.5 --- .github/workflows/mutation.yml | 46 ++++++++++++++++++++++++++++++++++ README.md | 1 + infection.json5 | 19 ++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 .github/workflows/mutation.yml create mode 100644 infection.json5 diff --git a/.github/workflows/mutation.yml b/.github/workflows/mutation.yml new file mode 100644 index 0000000..fdcc673 --- /dev/null +++ b/.github/workflows/mutation.yml @@ -0,0 +1,46 @@ +--- + +name: Mutation Tests + +on: # yamllint disable-line rule:truthy + pull_request: + push: + branches: [3.x] + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + mutation: + timeout-minutes: 15 + runs-on: ubuntu-latest + steps: + - name: 📦 Check out the codebase + uses: actions/checkout@v7 + + - name: 🛠️ Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.4' + ini-values: error_reporting=E_ALL + coverage: xdebug + + - name: 📥 Install dependencies with composer + uses: ramsey/composer-install@v3 + with: + dependency-versions: highest + + # The Infection Phar can't run Testo yet: the bundled adapter's mutant bootstrap calls the + # unscoped `\Infection\StreamWrapper\IncludeInterceptor`, while the Phar ships it as + # `Infected\Infection\StreamWrapper\IncludeInterceptor`. Infection requires PHP >= 8.3, + # so it is installed here rather than in require-dev (the package supports PHP 8.2). + - name: 📥 Install Infection + run: | + composer config allow-plugins.infection/extension-installer true + composer require --dev --no-interaction --no-progress --with-all-dependencies infection/infection testo/bridge-infection + + - name: 🧬 Run mutation testing + run: vendor/bin/infection --threads=max --logger-github --show-mutations=0 --min-msi=70 + env: + STRYKER_DASHBOARD_API_KEY: ${{ github.event_name == 'push' && secrets.STRYKER_DASHBOARD_API_KEY || '' }} diff --git a/README.md b/README.md index 39c86a4..63face5 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ [![Psalm Level](https://shepherd.dev/github/roadrunner-php/worker/level.svg)](https://shepherd.dev/github/roadrunner-php/worker) [![Type Coverage](https://shepherd.dev/github/roadrunner-php/worker/coverage.svg)](https://shepherd.dev/github/roadrunner-php/worker) +[![Mutation testing badge](https://img.shields.io/endpoint?url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Froadrunner-php%2Fworker%2F3.x)](https://dashboard.stryker-mutator.io/reports/github.com/roadrunner-php/worker/3.x) diff --git a/infection.json5 b/infection.json5 new file mode 100644 index 0000000..d54063f --- /dev/null +++ b/infection.json5 @@ -0,0 +1,19 @@ +{ + "$schema": "https://raw.githubusercontent.com/infection/infection/0.35.6/resources/schema.json", + "source": { + "directories": ["src"] + }, + "testFramework": "testo", + "tmpDir": "runtime", + "timeout": 10, + "logs": { + "text": "runtime/infection.log", + "github": true, + "stryker": { + "report": "3.x" + } + }, + "mutators": { + "@default": true + } +}