Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 75 additions & 9 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -269,11 +269,56 @@
- name: "Tests"
run: "make tests"

mutation-testing-changed-files:
name: "Mutation Testing: changed files"
runs-on: "ubuntu-latest"
if: github.event_name == 'pull_request'

permissions:
contents: read

env:
# The branch the diff is taken against - the branch this file lives on.
# Flipped by the "Open X.Y.x" commit, like the push branch above.
MUTATION_TESTING_BASE_BRANCH: "2.2.x"

outputs:
base-branch: ${{ env.MUTATION_TESTING_BASE_BRANCH }}
any: ${{ steps.changed-files.outputs.any }}
files: ${{ steps.changed-files.outputs.files }}

steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit

- name: "Checkout"
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
with:
persist-credentials: false

# The same files Infection picks with --git-diff-base and its default AM
# filter over its source directories
- name: "Find changed source files"
id: changed-files
run: |
git fetch --depth=1 origin "$MUTATION_TESTING_BASE_BRANCH"
base=$(git merge-base "origin/$MUTATION_TESTING_BASE_BRANCH" HEAD || echo "origin/$MUTATION_TESTING_BASE_BRANCH")
files=$(git diff "$base" --diff-filter=AM --name-only -- src build/PHPStan/Build | grep '\.php$' || true)
echo "$files"
{
if [ -n "$files" ]; then echo "any=true"; else echo "any=false"; fi
echo 'files<<EOF'
echo "$files"
echo 'EOF'
} >> "$GITHUB_OUTPUT"

mutation-testing:
name: "Mutation Testing"
runs-on: "ubuntu-latest"
needs: ["tests"]
if: github.event_name == 'pull_request'
needs: ["tests", "mutation-testing-changed-files"]
if: github.event_name == 'pull_request' && needs.mutation-testing-changed-files.outputs.any == 'true'

strategy:
fail-fast: false
Expand Down Expand Up @@ -328,11 +373,6 @@
> infection.json5
jq < infection.json5

- name: "Determine default branch"
id: default-branch
run: |
echo "name=$(git remote show origin | sed -n '/HEAD branch/s/.*: //p')" >> "$GITHUB_OUTPUT"

- name: "Restore result cache"
uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0
with:
Expand All @@ -341,10 +381,34 @@
restore-keys: |
result-cache-v1-${{ matrix.php-version }}-

# Infection reads the coverage report of every source file it lists, and
# the whole of src/ outgrew the runner's memory - only the mutated files
# need it
- name: "Restrict coverage to the changed source files"
env:
CHANGED_FILES: ${{ needs.mutation-testing-changed-files.outputs.files }}
run: |
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
echo "$CHANGED_FILES" > "$RUNNER_TEMP/changed-files.txt"
php -- "$RUNNER_TEMP/changed-files.txt" <<'PHP'
<?php
$document = new DOMDocument();
$document->load('phpunit.xml');
$include = $document->getElementsByTagName('source')->item(0)->getElementsByTagName('include')->item(0);
while ($include->firstChild !== null) {
$include->removeChild($include->firstChild);
}
foreach (file($argv[1], FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $file) {
$include->appendChild($document->createElement('file', $file));
}
$document->save('phpunit-mutation-testing.xml');
PHP
grep -A5 "<source" phpunit-mutation-testing.xml

# see https://infection.github.io/guide/command-line-options.html#coverage
- name: "Create coverage in parallel"
run: |
php -d pcov.enabled=1 tests/vendor/bin/paratest \
--configuration=phpunit-mutation-testing.xml \
--passthru-php="'-d' 'pcov.enabled=1'" \
--coverage-xml=tmp/coverage/coverage-xml \
--coverage-clover=tmp/coverage/clover.xml \
Expand All @@ -357,10 +421,12 @@
path: tmp/coverage

- name: "Run infection"
env:
BASE_BRANCH: ${{ needs.mutation-testing-changed-files.outputs.base-branch }}
run: |
git fetch --depth=1 origin ${{ steps.default-branch.outputs.name }}
git fetch --depth=1 origin "$BASE_BRANCH"
infection \
--git-diff-base=origin/${{ steps.default-branch.outputs.name }} \
--git-diff-base="origin/$BASE_BRANCH" \
--git-diff-lines \
--coverage=tmp/coverage \
--skip-initial-tests \
Expand Down
Loading