Engineering quality
Every push and pull request to NextPDF runs build-blocking CI gates for static analysis, changed-line coverage, mutation score, and tagged-output validation.
Static analysis
Section titled “Static analysis”Three PHPStan gates run on every push and pull request:
| Gate | Scope | Blocking |
|---|---|---|
| Level 10 | src/ | Yes |
| Level max (strict profile) | src/ | Yes |
| SARIF annotation | src/ | Advisory |
CI treats PHPStan Level 10 findings in src/ as build-blocking. Two settings raise the
bar above a default Level 10 run:
treatPhpDocTypesAsCertain— PHPStan trusts the PHPDoc annotation as ground truth rather than re-widening to the native type, so a narrowing annotation that contradicts what static analysis can derive is a reported finding.reportUnmatchedIgnoredErrors— every suppression must match a currently-reported error, or the build fails.
Each ignoreErrors entry for src/ is pinned to a PHPStan identifier, an exact file
path, and where relevant an exact occurrence count — a new occurrence of the same
identifier anywhere else, or a second occurrence in the same file, fails the build.
Coverage
Section titled “Coverage”CI enforces a 90% coverage threshold on the lines each pull request changes, measured with PCOV against the base branch. A pull request below the threshold fails the build.
Mutation testing
Section titled “Mutation testing”Mutation testing checks that the tests assert on behaviour: CI mutates the code and requires a test to fail. Three mutation score indicators carry monotonically non-decreasing floors:
| Metric | Enforced minimum |
|---|---|
raw_msi | 88.9% |
effective_msi | 89.0% |
covered_msi | 88.9% |
A pull request that would drop any metric below its floor is rejected. CI applies a documented variance tolerance before comparing a run against the floors.
Output validation
Section titled “Output validation”CI runs veraPDF 1.30.1 with the pdfua.strict profile as a build-blocking gate on the
tagged-output corpus.