shipmonk/coverage-guard
Enforce code coverage in CI by targeting core functionality instead of percentages. Legacy-friendly and extensible, it lets you require coverage only for chosen methods and, with a patch, only for new code. Lightweight and easy to start.
Architecture fit: Strong fit for Laravel teams already using PHPUnit-compatible coverage. The package is a dev-only post-processor: PHPUnit/PCOV/Xdebug produces clover.xml, then coverage-guard enforces rules against executable lines and methods. That aligns with Laravel’s conventional CI shape and avoids runtime coupling. The targeted-method model is especially useful for Laravel’s critical surfaces—controllers, form requests, jobs, service classes, and app-specific facade accessors—where a global percentage is a poor proxy for release risk. Lightweight dependency footprint (nikic/php-parser) is a plus for supply-chain and CI stability.
Integration feasibility: High for a pilot. Installation is a single Composer dev dependency, init generates a starter coverage-guard.php, and the primary command runs after test coverage generation. --patch mode enables the highest-value TPM use case: enforce coverage only on new or changed methods, so legacy code does not block delivery. Path mapping and git-root settings address common CI/local mismatches. merge and convert are useful for parallel CI jobs and GitLab/JetBrains reporting.
Technical risk: Moderate overall, not because the code is complex, but because adoption evidence is thin. 60 stars and 0 dependents indicate limited real-world validation; the release metadata lists a future-dated release (2026-10-21), which should be verified against actual tags. The tool’s semantics depend on coverage report fidelity, so Laravel dynamic dispatch (__call facades, container-resolved controllers, middleware, macros, generated code) can create confusing false negatives or exemptions. Patch handling also depends on correct git base refs, rename detection, and non-shallow clones. PHP parser compatibility with newer PHP syntax is a forward risk.
Key questions: Can rules reliably exclude generated code, migrations, vendor paths, and Laravel macro-heavy classes? How are facade __call paths and container-resolved controller methods represented in coverage? Does --patch handle renamed/moved files and shallow-clone CI correctly? What is the supported PHPUnit/PHP/PHPUnit coverage-driver matrix, including Pest? Is output machine-readable for dashboards, or only terminal-friendly? What is the maintainer bus factor and response time? Can custom rules use reflection and attributes to encode team-specific exceptions without creating silent bypasses? What is the CI runtime overhead on a large Laravel monorepo?
Stack fit: Best suited to Laravel 9+ on PHP 8.1+, using PHPUnit or Pest with clover output. It complements, rather than replaces, Laravel’s overall coverage reporting: keep global coverage visible for trend analysis, use coverage-guard for surgical enforcement on critical methods and changed code. Prefer clover.xml because it supports IDE visualization, GitLab reporting, and better integrity checks; use cobertura only where GitLab visualization requires it; avoid the PHP coverage format for large suites.
Migration path: Start with a bounded pilot in one Laravel service. Generate clover coverage in CI, install the package, run init, and run check non-blocking to establish a baseline. Then enable --patch against the main branch so only new/changed methods are evaluated. Tune requiredCoveragePercentage, minMethodChangePercentage, and minExecutableLines to avoid noise from tiny or framework-driven methods. After the pilot, expand rules by risk tier: first controllers and payment/auth/order paths, then jobs and service classes, then broader application code. Keep legacy enforcement opt-in by directory or rule until teams have repaid test debt.
Compatibility: PHP 8.1+ is required. The README claims support for all PHPUnit versions and coverage formats; validate against the project’s actual PHPUnit/Pest version, coverage driver (PCOV preferred over Xdebug for speed), and CI provider. Optional extensions (dom, libxml, simplexml, tokenizer) and optional libraries (phpunit/php-code-coverage, sebastian/diff) should be confirmed in the CI image. Path mapping is mandatory when coverage is generated in a different absolute path than the checkout. Pest users should verify clover output and patch semantics before standardizing.
Sequencing: 1) Confirm CI can generate stable clover coverage. 2) Add the package and commit a reviewed coverage-guard.php. 3) Run a non-blocking baseline check and capture violations by team/module. 4) Add a non-blocking PR check in patch-only mode. 5) Tune thresholds and exclusions with tech leads. 6) Promote the new-code check to blocking. 7) Add merge for parallel jobs and patch-coverage for MR coverage comments. 8) Publish an org-wide CI template and rollback procedure. This sequencing limits delivery disruption and gives the TPM measurable adoption data before mandating the gate.
Maintenance: Low runtime maintenance, but not zero ownership. Treat coverage-guard.php as production-adjacent policy code: code review, ownership, and tests for custom rules. Pin the Composer version and upgrade deliberately, because parser or coverage-format changes can alter enforcement behavior. The small community and low dependent count mean the team should be prepared to fork or wrap the tool if maintenance stalls.
Support: Documentation is solid for first use, but external support is limited. Designate an internal owner—typically platform engineering or QA enablement—to own configuration patterns, CI troubleshooting, and rule exceptions. Provide a short runbook covering coverage-driver setup, path mapping, patch base refs, and how to request an approved exception. TPMs should expect to fund enablement, not just installation.
Scaling: Coverage generation, not coverage-guard parsing, will dominate CI cost. Use PCOV where possible, collect coverage once per job, cache Composer dependencies, and merge parallel reports with coverage-guard merge. Avoid oversized PHP coverage files. For monorepos, scope checks by changed paths and package boundaries. Rule complexity should scale with team maturity; overly clever custom rules become opaque and hard to audit.
Failure modes: Missing or empty coverage files, disabled coverage drivers, path mismatches between CI and checkout, incorrect patch base branches, shallow clones, renamed files, generated code, and parser incompatibility with new PHP syntax. The README notes that merge and convert produce minimal XML and do not retain all original data, so downstream tools should be validated. Policy failure modes are equally important: thresholds set too high block hotfixes, broad NoCoverageAllowed-style exceptions create silent bypasses, and patch-only mode can miss regressions in untouched but high-risk legacy methods. Mitigate with clear CI errors, artifact retention, audited exceptions, and a temporary non-blocking fallback.
Ramp-up: A one-service pilot should take roughly one to two engineering days plus one sprint of observation. Org-wide rollout is a quarter-scale change management effort: template the CI job, train tech leads on rule design, publish success metrics, and review false-positive rates. Useful TPM metrics are patch coverage on changed core methods, violation count by team, PR cycle-time impact, exception count, CI duration delta, and escaped defects in covered vs. uncovered areas. The package is best leveraged as a risk-based quality policy, not as a blanket coverage mandate.
How can I help you explore Laravel packages today?