Releases: pento/lcov-coverage-check
The One That Got Away
Fix: Baseline retrieval pages back through default-branch runs
The action found the baseline by inspecting only the single most recent successful default-branch run for the lcov-baseline artifact. But a successful run doesn't guarantee a baseline — the coverage job is often conditional (path filters, matrix skips, flaky reruns), so the latest run can complete without one while an older run still holds a perfectly valid baseline.
When that happened, the action silently fell back to summary-only mode: ratcheting wasn't enforced (passed=true hardcoded) and no PR comparison comment was posted. Coverage could regress behind a green check, intermittently, depending only on what the most recent default-branch commit happened to touch.
Retrieval now pages back through recent successful default-branch runs (newest first) and uses the first that still holds a non-expired lcov-baseline[-<label>] artifact, only falling back to summary-only mode when none of the inspected runs has one. Pagination follows the Link: rel="next" header (per_page=100, 50-page cap). (#15)
Also
- Hardened the per-run artifact query so a transient failure (or malformed response) for one run skips that run and keeps paging, instead of aborting the whole search.
mktempcalls now use a${TMPDIR:-/tmp}/…template, matching the rest of the codebase (portable; the previous baremktemp -dignored$TMPDIRon macOS).
No workflow changes needed. Existing setups pick up the fix automatically.
One Comment to Rule Them All
New: Consolidated PR comments
Multiple coverage labels now share a single PR comment instead of posting separate comments per label. Each label occupies its own section within the comment, independently updated on each run.
Sections are sorted alphabetically (unlabeled runs appear first as "default"). A read-modify-write cycle with retry handles concurrent updates from parallel jobs. (#14)
Migration
Old-format per-label comments are automatically deleted on the first run after upgrading. No manual cleanup needed.
Single-invocation users without coverage-label are unaffected — the comment format changes internally but the visible content is identical.
Label Me Impressed
Breaking changes
The new coverage-label input namespaces PR comments and baseline artifacts per label (e.g., lcov-baseline-go instead of lcov-baseline). If you add a coverage-label to an existing invocation, it won't find the previous unlabeled baseline artifact — a fresh baseline will be created on the next push to your default branch. Any open PRs should be rebased or updated after that merge to pick up the new baseline.
Single-invocation users who don't use coverage-label are unaffected.
New: Multi-language coverage labels
The coverage-label input lets you run the action multiple times in the same workflow without PR comment or artifact collisions. Each label gets its own namespaced comment and baseline artifact.
- uses: pento/lcov-coverage-check@v3
with:
lcov-file: coverage/go.lcov
coverage-label: go
github-token: ${{ secrets.GITHUB_TOKEN }}
- uses: pento/lcov-coverage-check@v3
with:
lcov-file: coverage/frontend.lcov
coverage-label: frontend
github-token: ${{ secrets.GITHUB_TOKEN }}Smart collision detection warns when labels are inconsistently applied across runs. (#8)
Fix: PR comment pagination
The action now paginates the PR comment lookup, fixing duplicate comment posting on PRs with more than 100 comments. (#10)
Fix: Temp file cleanup
Temporary files created during LCOV filtering are now properly cleaned up. (#13)
Internal: Module restructuring
Split large script files into smaller, focused library modules under scripts/lib/. No user-facing changes. (#11)
These Paths Were Made for Walking
New: Multiple path prefixes
The path input now accepts multiple path prefixes, one per line. Projects with source code in multiple directories can enforce coverage checks across all of them.
- uses: pento/lcov-coverage-check@v2
with:
path: |
lib/
src/
github-token: ${{ secrets.GITHUB_TOKEN }}Previously, path accepted a single prefix. Existing single-path usage is unchanged. (#7)
Still Waters Run Shallow
Fix: New/modified file detection in shallow clones
actions/checkout defaults to fetch-depth: 1, which means only the merge commit is available locally. The action's git diff calls used three-dot syntax (A...B), which requires merge-base computation and connected history between commits — neither of which exist in a shallow clone. The error was silently swallowed, causing the action to report "No new files detected" and "No modified files detected" even when the PR had changed files.
Three changes:
- Auto-fetch refs: Before running
git diff, the action now fetches the base and head refs withgit fetch --depth=1. No workflow changes needed. - Two-ref diff syntax: Switched from
A...B(merge-base) toA B(direct tree comparison), which only needs the two commits to be present. - Warnings on failure: If
git diffstill fails (e.g., no remote access), a::warning::annotation is emitted instead of silently returning zero files. (#6)
Ignorance is Bliss
New: Ignore patterns
A new ignore-patterns input lets you exclude files from all coverage checks. Specify one glob pattern per line — matched files are filtered out of LCOV data before parsing, skipped in new-file minimum coverage checks, and skipped in changed-file ratchet checks.
- uses: pento/lcov-coverage-check@v2
with:
ignore-patterns: |
**/generated/**
**/*.g.dartFix: Actionable error for missing actions:read permission
When GITHUB_TOKEN lacks actions: read permission, the action now emits a clear notice naming the missing permission instead of silently falling back to summary-only mode with a generic error. (#4)
Chore: Updated dependencies
actions/upload-artifactupgraded from v4 to v7actions/download-artifactupgraded to latest
Smarter, Better, Faster, Stronger
What's New
Language-agnostic file type support
The action no longer hardcodes .dart as the only supported file extension. File extensions are now derived automatically from the SF: lines in your LCOV data, so it works out of the box with any language that produces LCOV coverage — Go, Python, TypeScript, C/C++, Ruby, and more. No configuration needed; existing Dart projects behave identically.
Automatic baseline management
The action now manages baseline coverage artifacts end-to-end. Provide a github-token and:
- On pushes to the default branch: the current LCOV file is uploaded as an
lcov-baselineartifact - On pull requests: the baseline is auto-retrieved from the latest successful default-branch run, and git refs are auto-detected from the PR event payload
This replaces the previous manual lcov-base, base-ref, and head-ref inputs — users just provide github-token and the action handles the rest.
Bug fixes
- Fix PR comment posting: reads the PR number from
GITHUB_EVENT_PATHpayload instead of the non-existentGITHUB_EVENT_NUMBERenv var (#1) - GHES compatibility: all API calls now use
GITHUB_API_URLinstead of hardcodedapi.github.com(#2)
Breaking changes
- The
lcov-base,base-ref,head-ref, andnew-file-path-prefixinputs have been removed in favor of automatic management via
github-token new-file-path-prefixis replaced bypath
Testing
Test suite expanded from 3 to 25 tests covering baseline retrieval, PR comments, GHES compatibility, and multi-language extension support.
Hello, World!
LCOV Coverage Check
A composite GitHub Action that parses LCOV coverage files and enforces coverage standards on pull requests.
Features
- Coverage summary — Reports overall line coverage from any LCOV file.
- Baseline comparison — Compare current coverage against a baseline LCOV file to catch regressions.
- New file thresholds — Enforce a minimum coverage percentage on newly added files (configurable path prefix and threshold).
- Per-file regression guard — Optionally fail when modified files lose coverage vs. the baseline.
- PR comments — Post a formatted coverage summary directly on the pull request (requires
github-token). - Outputs — Exposes
overall-coverage,baseline-coverage, andpassedfor downstream steps.
Usage
- uses: pento/lcov-coverage-check@v1
with:
lcov-file: coverage/lcov.info
lcov-base: coverage/lcov-base.info
base-ref: ${{ github.event.pull_request.base.sha }}
github-token: ${{ secrets.GITHUB_TOKEN }}