michaelmoussa/php-coverage-checker
A PHP tool that reads Clover-format code coverage XML and fails the build when coverage drops below a configured threshold. Drop it into CI to enforce minimum coverage on every run.
Architecture fit. Despite being requested as a Laravel/PHP package, this is not a Laravel package in any meaningful sense: no service provider, no facade, no publishable config, no framework coupling. It is a standalone CLI development utility that reads a Clover-format XML coverage report and exits non-zero if coverage falls below a supplied percentage threshold. That means its only legitimate architectural slot is the CI/dev-tooling layer, invoked as a composer script or a pipeline step after PHPUnit emits clover.xml. Nothing in the application runtime, container, or deployment topology should ever depend on it. The absence of framework coupling is, in isolation, a virtue — it will not constrain a Laravel upgrade — but it also means there is no Laravel-specific value to weigh against its age.
Integration feasibility. Mechanically trivial and strategically dubious. The happy path is composer require --dev plus one CI line. The realistic path is friction: a 2015-vintage package almost certainly caps symfony/console at a 2.x line, which conflicts with the 6.x/7.x Console that Laravel 9/10/11 pulls in transitively. That is a root-level dependency-resolution failure, not a warning, so the package can typically only be installed in isolation (a separate Composer project, a global binary, or a downloaded release archive) rather than in the app's composer.json. Runtime compatibility with PHP 8.x is unverified and likely broken; the Clover schema has also evolved since 2015, so parsing behavior against modern php-code-coverage output must be proven, not assumed.
Technical risk. High and asymmetric. The repository is archived with a last release in September 2015, a single historical maintainer, 24 stars, and effectively no user base to surface regressions. There is no security response path, no PHP-version roadmap, and it will be flagged as abandoned by Composer audit and SCA tooling, generating a permanent allowlist exception. Correctness risk is subtle: a coverage gate that silently passes on a missing, stale, or partially parsed report is worse than no gate, because it manufactures false confidence in the exact metric leadership will cite.
Key questions.
composer.json, composer.lock, CI YAML, Makefiles, Docker images?Stack fit. Treat it as CI glue, never as application code. If it must survive short-term, install it outside the application dependency graph — a pinned archive invoked by absolute path in the pipeline, or a separate tools/ Composer project with its own lockfile — so it cannot influence the app's resolved dependency set or the production image.
Migration path. Recommended posture: replace rather than adopt.
clover.xml and confirm the computed percentage matches PHPUnit's own coverage summary. Any divergence is a stop-work signal on the gate's credibility.rregeer/phpunit-coverage-check), which minimizes CI churn. Second choice is a short in-repo script against the phpunit/php-code-coverage API, which removes the third-party dependency entirely. Third choice is delegating the gate to a hosted coverage service, which also delivers trend history and per-team dashboards.Compatibility. Three surfaces to validate explicitly: Composer constraint solvability against the current Laravel skeleton, PHP runtime compatibility (fatals on 8.x are likely), and Clover schema tolerance — new attributes or nesting introduced by modern php-code-coverage can shift a reported percentage without any test changing. Also confirm exit-code conventions propagate through the CI runner so a failure actually fails the job rather than being swallowed by continue-on-error.
Sequencing. Inventory → isolate/pin → parity check → parallel run → cutover → removal → documentation. Expect a few engineer-days, almost entirely CI configuration and verification; no application code changes, no release coordination, no database or API migration. That low cost is the main argument for doing it now rather than carrying the exception indefinitely.
Maintenance. Zero upstream maintenance means all maintenance is ours: patching for PHP upgrades, adapting to schema changes, and re-justifying the exception at every audit cycle. The recurring cost is small in engineer-hours but non-trivial in governance overhead — abandoned dependencies accumulate as audit findings and erode the credibility of the allowlist process if exceptions are granted casually.
Support. There is no support channel, no issue triage, and thin documentation beyond a README. With 24 stars, the practical support model is "read the source," which is feasible given the small codebase but is a bus-factor risk concentrated in whoever originally wired it up. Name an internal owner or retire it.
Scaling. Technically it scales fine — parsing one XML file is sub-second for typical suites, with memory growth proportional to report size, so only very large monorepos risk timeouts. Organizationally it does not scale: no per-team thresholds, no historical trend, no dashboard, no aggregation across services. If coverage is a metric leadership tracks, a per-pipeline binary exit code is the wrong instrument; a hosted service or CI-native summary gives the same gate plus the reporting layer at comparable cost.
Failure modes. In rough order of likelihood: Composer constraint conflict blocking install; silent pass on a missing or stale clover.xml, producing a false green; PHP 8.x fatal errors after a runner image upgrade; misparsed percentages on newer Clover schemas; and threshold gaming — teams excluding generated or hard-to-test paths until the number is meaningless. That last one is the most expensive, because it converts a quality signal into a vanity metric and is invisible until someone audits the exclusions.
Ramp-up. Near zero for the mechanics — one command, one file path, one percentage. The real ramp-up is policy: defining coverage scope and exclusions, choosing a global floor versus a ratchet on changed lines, and deciding which teams are exempt during rollout. A TPM should own that policy explicitly, because the tool's blunt single-threshold model will otherwise shape behavior toward whatever is easiest to exclude.
How can I help you explore Laravel packages today?