NAME
coverage-gate - run the whole four-metric coverage gate inside one environment
WHAT IT IS
The canonical entrypoint for the repository coverage gate. It drops the coverage database, runs the instrumented test suite, collects the lib/ report for statement, branch, condition and subroutine coverage, and enforces 100.0 on all four through script/check-all-metric-coverage.
WHAT IT IS FOR
It is the one command a developer, an automated round, or a continuous integration job runs to answer "does lib/ still measure 100.0 on every metric?". The documented gate and the executed gate are the same thing because there is only one of them.
WHY IT EXISTS
The gate used to be three shell lines. Each is its own interpreter with its own @INC, so the library path had to be repeated on all three, and Devel::Cover::DB::IO chooses its on-disk serialization format at BEGIN from whatever @INC makes visible - Sereal, then JSON, then Storable - without recording the choice beside the data.
On a host carrying two Devel::Cover installations whose available serializers differ, omitting the library path from one line of the chain leaves the reader unable to parse what the writer produced moments earlier. It surfaces as File is not a perl storable or Bad Sereal header: both read as a corrupt database, and the obvious response - delete it and run again - fails identically, spending another host-exclusive multi-minute suite slot every time. Two automated rounds paid that cost inside two hours, and the second did not recognise the first.
Documentation had already been written telling readers to repeat the library path, and it did not prevent the recurrence. Running the three commands as children of one process removes the hazard instead of warning about it: they inherit one environment because there is only one to inherit.
WHEN TO USE
Before claiming any change complete, and as the coverage step of every continuous integration workflow. Only one coverage run may be in flight on a host at a time, because instrumented timing-sensitive tests misread under contention.
HOW TO USE
Run it from anywhere; it enters the repository root itself. Give it test paths to narrow the instrumented run, --database to keep the database somewhere other than cover_db, and --dry-run to see the resolved environment and the exact commands before spending a suite slot.
Exit statuses are the interface:
0 - statement, branch, condition and subroutine are all 100.0.
1 - a genuine shortfall; the failing metrics are named.
2 - the gate could not run, or could not read its report.
3 - the coverage instrument could not read its own database.
WHAT USES IT
The test, release-cpan and release-github workflows, the contributor testing guide, and t/148-coverage-gate-entrypoint.t, which is its acceptance contract.
EXAMPLES
Example 1:
perl script/coverage-gate
Run the full gate over the whole suite.
Example 2:
perl script/coverage-gate --dry-run
Print the resolved interpreter, library path, serializer module and the three commands, and run none of them. Use this to confirm the instrument before committing a host-exclusive slot to it.
Example 3:
perl script/coverage-gate --database /tmp/scratch-db t/107-all-metric-coverage-gate.t
Collect coverage for a focused set of tests into a scratch database, leaving the repository's own cover_db untouched.