Skip to content
Draft
Show file tree
Hide file tree
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
95 changes: 95 additions & 0 deletions .github/workflows/patch-coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
#
# DRAFT — patch (PR-affected lines only) coverage gate via shipmonk/coverage-guard.
# See https://github.com/shipmonk-rnd/coverage-guard
#
# Only runs on pull_request: it gates the lines the PR changed, so it has no
# meaning on push to a maintained branch.

name: "Patch coverage"

on:
pull_request:
paths-ignore:
- 'compiler/**'
- 'apigen/**'
- 'changelog-generator/**'
- 'issue-bot/**'

concurrency:
group: patch-coverage-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
patch-coverage:
name: "Patch coverage"
runs-on: ubuntu-latest
timeout-minutes: 60

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

# The default refs/pull/N/merge checkout: the coverage report and the
# diff below are both taken on the merge commit, so their line numbers
# refer to the same tree. Its first parent is the base branch tip, so
# fetch-depth: 2 is enough for the diff. (A pull_request run does not
# exist for a PR that conflicts with its base.)
- name: "Checkout"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 2
Comment on lines +40 to +43

- name: "Install PHP"
uses: "shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc" # v2.37.1
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
with:
coverage: "pcov"
php-version: "8.3"
tools: pecl
extensions: ds,mbstring
ini-file: development
ini-values: memory_limit=-1

- uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed

- uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
with:
working-directory: "tests/"

# coverage-guard is not yet a dependency; install it ad-hoc for the gate.
# If we decide to keep this, move it into require-dev instead.
- name: "Install coverage-guard"
run: composer require --dev shipmonk/coverage-guard --ignore-platform-reqs

# Mirror the proven-green coverage step from `make infection` /
# the mutation-testing job (paratest + pcov over the whole suite), but
# emit clover so coverage-guard can read it. paratest merges the
# per-worker coverage for us, so no `coverage-guard merge` step is needed.
- name: "Tests with coverage"
run: |
php -d pcov.enabled=1 tests/vendor/bin/paratest \
--runner WrapperRunner \
--passthru-php="'-d' 'pcov.enabled=1'" \
--coverage-clover=coverage/clover.xml

# The merge commit against its first parent is exactly what merging
# the PR changes on the base branch, with the "+" line numbers in the
# coordinate system of the coverage report collected above.
- name: "Compute PR diff"
run: |
git diff HEAD^1 HEAD > changes.patch
echo "----- changed files -----"
git diff --name-only HEAD^1 HEAD

- name: "Check patch coverage"
run: vendor/bin/coverage-guard check coverage/clover.xml --patch changes.patch

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: ${{ !cancelled() }}
with:
name: patch-coverage
path: |
coverage/clover.xml
changes.patch
30 changes: 30 additions & 0 deletions coverage-guard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php declare(strict_types = 1);

// DRAFT config for shipmonk/coverage-guard — https://github.com/shipmonk-rnd/coverage-guard
//
// Used by .github/workflows/patch-coverage.yml to gate coverage on the lines a
// PR changes. Thresholds below are a starting point, tune to taste.

use ShipMonk\CoverageGuard\Config;
use ShipMonk\CoverageGuard\Rule\EnforceCoverageForMethodsRule;

$config = new Config();

// Replace prefix of absolute paths in coverage files
// Handy if you want to reuse clover.xml generated in CI
$config->addCoveragePathMapping('/home/runner/work/phpstan-src/phpstan-src', __DIR__);

// The coverage report is produced by PHPUnit/paratest on the same runner that
// runs the gate, so the absolute file paths inside clover.xml already live
// under this directory — git root is enough, no path mapping needed.
// (The monorepo needs addCoveragePathMapping() only because PHPUnit there runs
// inside a container at a different WORKDIR than the checkout.)
$config->setGitRoot(__DIR__);

$config->addRule(new EnforceCoverageForMethodsRule(
requiredCoveragePercentage: 50,
minMethodChangePercentage: 50,
minExecutableLines: 5,
));

return $config;
Loading