brianhenryie / php-codecoverage-markdown
Generate markdown coverage reports from PHPUnit code coverage data for GitHub PR comments
Installs: 44
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/brianhenryie/php-codecoverage-markdown
Requires
- php: >=7.4
- phpunit/php-code-coverage: ^9|^10|^11|^12
- phpunit/php-text-template: ^2.0|^3.0|^4.0
- symfony/console: ^5|^6|^7
Requires (Dev)
This package is auto-updated.
Last update: 2026-01-19 01:40:54 UTC
README
PHP Code Coverage Markdown Report Printer
Generate Markdown coverage reports from PHPUnit code coverage data, for GitHub PR comments.
Features
- 📊 Convert PHPUnit
.covcoverage files to Markdown - 🔗 Link files to GitHub blob URLs
- 📝 Filter reports to specific files
- 🎨 Visual coverage bars using emojis (🟩🟧🟥⬜)
The Markdown report includes:
- Total coverage summary
- Per-file coverage details with:
- Lines coverage percentage
- Visual coverage bar
- Methods coverage
- Classes coverage
- Clickable source/HTML report links, set with
--base-url
Options
Primary input: coverage file in PHP format from phpunit/php-code-coverage:^9|^10|^11|^12, i.e. phpunit --coverage-php coveragephp.cov.
| Option | Short | Description |
|---|---|---|
--input-file |
-i |
Path to PHPUnit .cov coverage file (required) |
--output-file |
-o |
Output file path (default: stdout) |
--base-url |
-b |
Base URL for source file links (use %s as relative path placeholder) |
--covered-files |
-c |
Comma-separated list of files to include (i.e. the files in the PR) |
Limitation
GitHub Actions permissions limit new comments to users with write access to the repo. I.e. this works great for teams using private repos and works ok for PRs on public repos. There is a workaround at mshick/add-pr-comment-proxy which runs on Google Cloud.
Installation
composer require --dev brianhenryie/php-codecoverage-markdown:"^0.1|^1.0"
Usage
CLI
Generate a Markdown report from a PHPUnit coverage file:
php-codecoverage-markdown \ --input-file tests/_reports/coveragephp.cov \ --output-file coverage-report.md
With GitHub links:
php-codecoverage-markdown \
--input-file tests/_reports/coveragephp.cov \
--base-url "https://github.com/user/repo/blob/main/%s" \
--output-file coverage-report.md
Filter to specific files:
php-codecoverage-markdown \
--input-file tests/_reports/coveragephp.cov \
--covered-files "src/MyClass.php,src/AnotherClass.php" \
--output-file coverage-report.md
GitHub Actions
Use this to post coverage reports as PR comments:
name: PHP Tests with Code Coverage Report Comment on: pull_request: types: [opened, synchronize] env: COVERAGE_PHP_VERSION: '8.4' jobs: php-tests: runs-on: ubuntu-latest permissions: pull-requests: write strategy: matrix: php: [ '8.2', '8.3', '8.4', '8.5' ] steps: - uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} coverage: ${{ matrix.php == env.COVERAGE_PHP_VERSION && 'xdebug' || 'none' }} - name: Install dependencies run: composer install - name: Run tests with coverage if: ${{ matrix.php == env.COVERAGE_PHP_VERSION }} # We only need the coverage data once run: XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-php coveragephp.cov - name: Run tests without coverage if: ${{ matrix.php != env.COVERAGE_PHP_VERSION }} run: vendor/bin/phpunit - name: Get changed files if: ${{ matrix.php == env.COVERAGE_PHP_VERSION }} id: changed-files uses: tj-actions/changed-files@v47 with: separator: ',' files: '**/**.php' - name: Generate markdown report if: ${{ matrix.php == env.COVERAGE_PHP_VERSION }} run: | vendor/bin/php-codecoverage-markdown \ --input-file coveragephp.cov \ --covered-files=${{ steps.changed-files.outputs.all_changed_files }} \ --base-url "https://github.com/${{ github.repository }}/blob/${{ github.event.pull_request.head.sha }}/%s" \ --output-file coverage-report.md - name: Comment on PR uses: mshick/add-pr-comment@v2 if: ${{ matrix.php == env.COVERAGE_PHP_VERSION }} with: message-id: coverage-report # Causes it to update the same PR comment each time. message-path: coverage-report.md continue-on-error: true # When a PR is opened by a non-member, there are no write permissions (and no access to secrets), so this step will always fail.
Programmatic
use BrianHenryIE\CodeCoverageMarkdown\MarkdownReport; use SebastianBergmann\CodeCoverage\CodeCoverage; /** @var CodeCoverage $coverage */ $coverage = include 'path/to/coveragephp.cov'; $report = new MarkdownReport(); $markdown = $report->process( coverage: $coverage, projectRoot: '/path/to/project/', baseUrl: 'https://github.com/user/repo/blob/main/%s', coveredFilesList: ['src/MyClass.php'] ); file_put_contents('coverage-report.md', $markdown);
Status
- Ironically, this project's tests pass locally but fail in GitHub Actions! I'll tag 1.0 when I figure that out
- This should be spun into its own GitHub Action so it is not a dependency in a project
