Skip to content

Commit 8a268c8

Browse files
authored
Merge pull request #6 from shoptet/claude/switch-to-phpunit-xml-format
[WIP] Switch coverage format from Clover to PHPUnit XML
2 parents 4e94822 + 8ab27e3 commit 8a268c8

23 files changed

Lines changed: 824 additions & 198 deletions

.github/workflows/pr-check.yml

Lines changed: 76 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,30 @@ jobs:
1313
- name: Checkout code
1414
uses: actions/checkout@v4
1515

16-
- name: Verify clover.xml exists
16+
- name: Verify coverage-xml exists
1717
run: |
18-
if [ ! -f php-files/coverage/clover.xml ]; then
19-
echo "Error: clover.xml was not generated"
18+
if [ ! -d php-files/coverage-xml ]; then
19+
echo "Error: coverage-xml directory was not created"
2020
exit 1
2121
fi
22-
echo "✓ clover.xml exists"
23-
echo "Coverage file size: $(wc -c < php-files/coverage/clover.xml) bytes"
22+
if [ ! -f php-files/coverage-xml/index.xml ]; then
23+
echo "Error: coverage-xml/index.xml was not generated"
24+
exit 1
25+
fi
26+
echo "✓ coverage-xml directory exists"
27+
echo "✓ coverage-xml/index.xml exists"
28+
echo "Coverage index file size: $(wc -c < php-files/coverage-xml/index.xml) bytes"
2429
25-
- name: Display coverage file snippet
30+
- name: Display coverage index file snippet
2631
run: |
27-
echo "First 50 lines of clover.xml:"
28-
head -n 50 php-files/coverage/clover.xml
32+
echo "First 50 lines of coverage-xml/index.xml:"
33+
head -n 50 php-files/coverage-xml/index.xml
2934
3035
- name: Test PR Coverage Action
3136
id: coverage
3237
uses: ./
3338
with:
34-
clover-file: php-files/coverage/clover.xml
39+
coverage-xml-dir: php-files/coverage-xml
3540
github-token: ${{ secrets.GITHUB_TOKEN }}
3641
all-files-minimum-coverage: 0
3742
changed-files-minimum-coverage: 0
@@ -46,29 +51,77 @@ jobs:
4651
echo "Changed files lines: ${{ steps.coverage.outputs.changed-files-lines-hit }}/${{ steps.coverage.outputs.changed-files-lines-total }}"
4752
echo ""
4853
49-
# Validate outputs are not empty
50-
if [ -z "${{ steps.coverage.outputs.all-files-coverage }}" ]; then
51-
echo "❌ Error: all-files-coverage output is empty"
54+
# Expected values based on test data
55+
# All files: index.php (6/12) + service1.php (5/15) + service2.php (12/48) = 23/75 = 30.67%
56+
# Changed files detected by GitHub: index.php (6/12) + service2.php (12/48) = 18/60 = 30.00%
57+
# Note: service1.php appears in coverage but not detected as changed by GitHub in PR context
58+
EXPECTED_ALL_FILES_COVERAGE="30.67"
59+
EXPECTED_ALL_FILES_LINES_HIT="23"
60+
EXPECTED_ALL_FILES_LINES_TOTAL="75"
61+
EXPECTED_CHANGED_FILES_COVERAGE="30.00"
62+
EXPECTED_CHANGED_FILES_LINES_HIT="18"
63+
EXPECTED_CHANGED_FILES_LINES_TOTAL="60"
64+
65+
# Verify all-files-coverage
66+
ACTUAL_ALL_FILES_COVERAGE="${{ steps.coverage.outputs.all-files-coverage }}"
67+
if [ "$ACTUAL_ALL_FILES_COVERAGE" != "$EXPECTED_ALL_FILES_COVERAGE" ]; then
68+
echo "❌ Error: all-files-coverage mismatch"
69+
echo " Expected: $EXPECTED_ALL_FILES_COVERAGE"
70+
echo " Actual: $ACTUAL_ALL_FILES_COVERAGE"
71+
exit 1
72+
fi
73+
echo "✓ all-files-coverage: $ACTUAL_ALL_FILES_COVERAGE (matches expected)"
74+
75+
# Verify all-files-lines-hit
76+
ACTUAL_ALL_FILES_LINES_HIT="${{ steps.coverage.outputs.all-files-lines-hit }}"
77+
if [ "$ACTUAL_ALL_FILES_LINES_HIT" != "$EXPECTED_ALL_FILES_LINES_HIT" ]; then
78+
echo "❌ Error: all-files-lines-hit mismatch"
79+
echo " Expected: $EXPECTED_ALL_FILES_LINES_HIT"
80+
echo " Actual: $ACTUAL_ALL_FILES_LINES_HIT"
5281
exit 1
5382
fi
83+
echo "✓ all-files-lines-hit: $ACTUAL_ALL_FILES_LINES_HIT (matches expected)"
5484
55-
if [ -z "${{ steps.coverage.outputs.changed-files-coverage }}" ]; then
56-
echo "❌ Error: changed-files-coverage output is empty"
85+
# Verify all-files-lines-total
86+
ACTUAL_ALL_FILES_LINES_TOTAL="${{ steps.coverage.outputs.all-files-lines-total }}"
87+
if [ "$ACTUAL_ALL_FILES_LINES_TOTAL" != "$EXPECTED_ALL_FILES_LINES_TOTAL" ]; then
88+
echo "❌ Error: all-files-lines-total mismatch"
89+
echo " Expected: $EXPECTED_ALL_FILES_LINES_TOTAL"
90+
echo " Actual: $ACTUAL_ALL_FILES_LINES_TOTAL"
5791
exit 1
5892
fi
93+
echo "✓ all-files-lines-total: $ACTUAL_ALL_FILES_LINES_TOTAL (matches expected)"
5994
60-
# Validate coverage values are numeric and in valid range
61-
all_coverage="${{ steps.coverage.outputs.all-files-coverage }}"
62-
if ! [[ "$all_coverage" =~ ^[0-9]+\.?[0-9]*$ ]]; then
63-
echo "❌ Error: all-files-coverage is not a valid number: $all_coverage"
95+
# Verify changed-files-coverage
96+
ACTUAL_CHANGED_FILES_COVERAGE="${{ steps.coverage.outputs.changed-files-coverage }}"
97+
if [ "$ACTUAL_CHANGED_FILES_COVERAGE" != "$EXPECTED_CHANGED_FILES_COVERAGE" ]; then
98+
echo "❌ Error: changed-files-coverage mismatch"
99+
echo " Expected: $EXPECTED_CHANGED_FILES_COVERAGE"
100+
echo " Actual: $ACTUAL_CHANGED_FILES_COVERAGE"
64101
exit 1
65102
fi
103+
echo "✓ changed-files-coverage: $ACTUAL_CHANGED_FILES_COVERAGE (matches expected)"
66104
67-
# Check if coverage is reasonable (0-100%)
68-
if (( $(echo "$all_coverage > 100" | bc -l) )); then
69-
echo "❌ Error: all-files-coverage exceeds 100%: $all_coverage"
105+
# Verify changed-files-lines-hit
106+
ACTUAL_CHANGED_FILES_LINES_HIT="${{ steps.coverage.outputs.changed-files-lines-hit }}"
107+
if [ "$ACTUAL_CHANGED_FILES_LINES_HIT" != "$EXPECTED_CHANGED_FILES_LINES_HIT" ]; then
108+
echo "❌ Error: changed-files-lines-hit mismatch"
109+
echo " Expected: $EXPECTED_CHANGED_FILES_LINES_HIT"
110+
echo " Actual: $ACTUAL_CHANGED_FILES_LINES_HIT"
70111
exit 1
71112
fi
113+
echo "✓ changed-files-lines-hit: $ACTUAL_CHANGED_FILES_LINES_HIT (matches expected)"
72114
73-
echo "✓ All coverage outputs are valid"
74-
echo "✓ PR Test Coverage action completed successfully"
115+
# Verify changed-files-lines-total
116+
ACTUAL_CHANGED_FILES_LINES_TOTAL="${{ steps.coverage.outputs.changed-files-lines-total }}"
117+
if [ "$ACTUAL_CHANGED_FILES_LINES_TOTAL" != "$EXPECTED_CHANGED_FILES_LINES_TOTAL" ]; then
118+
echo "❌ Error: changed-files-lines-total mismatch"
119+
echo " Expected: $EXPECTED_CHANGED_FILES_LINES_TOTAL"
120+
echo " Actual: $ACTUAL_CHANGED_FILES_LINES_TOTAL"
121+
exit 1
122+
fi
123+
echo "✓ changed-files-lines-total: $ACTUAL_CHANGED_FILES_LINES_TOTAL (matches expected)"
124+
125+
echo ""
126+
echo "✅ All coverage outputs match expected values!"
127+
echo "✅ PR Test Coverage action completed successfully"

README.md

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# PR Test Coverage
22

3-
A Github Action to report the test coverage of changed files in a pull request. All it needs is a clover.xml file. It provides a summary of the coverage for all files and changed files separately, and a detailed table with coverage metrics per changed file.
3+
A Github Action to report the test coverage of changed files in a pull request. It uses PHPUnit XML coverage format. It provides a summary of the coverage for all files and changed files separately, and a detailed table with coverage metrics per changed file.
44

55
<img width="924" height="761" alt="image" src="https://github.com/user-attachments/assets/d0e61fa6-46c6-40b1-b9ce-b3c71a10321b" />
66

77
## Features
88

9-
- 📊 Generates comprehensive coverage reports from Clover XML files
9+
- 📊 Generates comprehensive coverage reports from PHPUnit XML coverage format
1010
- 💬 Posts coverage summaries as PR comments
1111
- 🔄 Updates existing comments or creates new ones
1212
- 📈 Shows coverage for all files and changed files separately
@@ -37,13 +37,13 @@ jobs:
3737

3838
- name: Run tests and generate coverage
3939
run: |
40-
# Your test commands here that generate Clover XML report
41-
npm test -- --coverage --coverageReporters=clover
40+
# Your test commands here that generate PHPUnit XML coverage report
41+
vendor/bin/phpunit --coverage-xml coverage-xml
4242
4343
- name: PR Test Coverage
4444
uses: jbaczuk/pr-test-coverage@v1
4545
with:
46-
clover-file: coverage/clover.xml
46+
coverage-xml-dir: coverage-xml
4747
github-token: ${{ secrets.GITHUB_TOKEN }}
4848
```
4949
@@ -53,8 +53,8 @@ jobs:
5353
- name: PR Test Coverage
5454
uses: jbaczuk/pr-test-coverage@v1
5555
with:
56-
# Required: Path to Clover XML file
57-
clover-file: coverage/clover.xml
56+
# Required: Path to PHPUnit XML coverage directory
57+
coverage-xml-dir: coverage-xml
5858

5959
# Required: GitHub token for API access
6060
github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -79,7 +79,7 @@ jobs:
7979
8080
| Input | Description | Required | Default |
8181
|-------|-------------|----------|---------|
82-
| `clover-file` | Path to the Clover XML file (e.g., `coverage/clover.xml`) | ✅ | - |
82+
| `coverage-xml-dir` | Path to the PHPUnit XML coverage directory (e.g., `coverage-xml`) | ✅ | - |
8383
| `github-token` | GitHub token for API access and posting comments | ✅ | `${{ github.token }}` |
8484
| `working-directory` | Working directory to run the action from | ❌ | `''` (repository root) |
8585
| `all-files-minimum-coverage` | Minimum coverage percentage for all files (0-100) | ❌ | `0` |
@@ -107,7 +107,7 @@ The action provides the following outputs that can be used in subsequent workflo
107107
id: coverage
108108
uses: jbaczuk/pr-test-coverage@v1
109109
with:
110-
clover-file: coverage/clover.xml
110+
coverage-xml-dir: coverage-xml
111111
github-token: ${{ secrets.GITHUB_TOKEN }}
112112
113113
- name: Check coverage threshold
@@ -174,19 +174,19 @@ The action uses visual indicators to quickly show coverage status:
174174

175175
The action will fail if:
176176

177-
1. **Clover file not found** - The specified Clover XML file doesn't exist
177+
1. **Coverage XML directory not found** - The specified PHPUnit XML coverage directory doesn't exist
178178
2. **Not a pull request** - The action is not running in a PR context
179179
3. **Coverage below threshold** - When coverage falls below specified minimums:
180180
- All files coverage below `all-files-minimum-coverage`
181181
- Changed files coverage below `changed-files-minimum-coverage`
182182

183-
## Supported Clover Format
183+
## Supported PHPUnit XML Format
184184

185-
The action supports standard Clover XML format with the following metrics:
185+
The action supports PHPUnit XML coverage format (generated with `--coverage-xml`) with the following metrics:
186186

187-
- **Lines**: `statements` (total lines) and `coveredstatements` (lines hit)
188-
- **Functions**: `methods` (total methods) and `coveredmethods` (methods hit)
189-
- **Branches**: `conditionals` (total branches) and `coveredconditionals` (branches hit)
187+
- **Lines**: `executable` (total lines) and `executed` (lines hit)
188+
- **Methods**: `count` (total methods) and `tested` (methods hit)
189+
- **Functions**: `count` (total functions) and `tested` (functions hit)
190190

191191
## Common Integration Examples
192192

@@ -202,10 +202,12 @@ The action supports standard Clover XML format with the following metrics:
202202
- name: PR Test Coverage
203203
uses: jbaczuk/pr-test-coverage@v1
204204
with:
205-
clover-file: coverage/clover.xml
205+
coverage-xml-dir: coverage/clover.xml
206206
github-token: ${{ secrets.GITHUB_TOKEN }}
207207
```
208208

209+
Note: Jest generates Clover format, not PHPUnit XML. This action now primarily supports PHPUnit XML format. For Jest, you may need to convert the format or use a different action.
210+
209211
### Python with pytest-cov
210212

211213
```yaml
@@ -219,21 +221,23 @@ The action supports standard Clover XML format with the following metrics:
219221
- name: PR Test Coverage
220222
uses: jbaczuk/pr-test-coverage@v1
221223
with:
222-
clover-file: coverage.xml
224+
coverage-xml-dir: coverage.xml
223225
github-token: ${{ secrets.GITHUB_TOKEN }}
224226
```
225227

228+
Note: pytest-cov generates Cobertura XML format, not PHPUnit XML. This action now primarily supports PHPUnit XML format.
229+
226230
### PHP with PHPUnit
227231

228232
```yaml
229233
- name: Run tests with coverage
230234
run: |
231-
vendor/bin/phpunit --coverage-clover coverage/clover.xml
235+
vendor/bin/phpunit --coverage-xml coverage-xml
232236
233237
- name: PR Test Coverage
234238
uses: jbaczuk/pr-test-coverage@v1
235239
with:
236-
clover-file: coverage/clover.xml
240+
coverage-xml-dir: coverage-xml
237241
github-token: ${{ secrets.GITHUB_TOKEN }}
238242
```
239243

action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ branding:
66
color: 'green'
77

88
inputs:
9-
clover-file:
10-
description: 'Path to the Clover XML file (e.g., coverage/clover.xml)'
9+
coverage-xml-dir:
10+
description: 'Path to the PHPUnit XML coverage directory (e.g., coverage-xml)'
1111
required: true
1212
github-token:
1313
description: 'GitHub token for accessing API and posting comments'

dist/PhpUnitXmlParser.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { CoverageData } from './types';
2+
export declare class PhpUnitXmlParser {
3+
parse(coverageXmlDir: string): Promise<CoverageData>;
4+
/**
5+
* Extracts the source file path from a PHPUnit XML file
6+
* This reads the individual file XML to get the path attribute and combines it with the project source prefix
7+
*/
8+
private extractSourcePath;
9+
}

dist/PhpUnitXmlParser.d.ts.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/PrTestCoverageAction.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export declare class PrTestCoverageAction {
55
private readonly inputs;
66
private readonly context;
77
private readonly githubService;
8-
private readonly cloverParser;
8+
private readonly phpunitXmlParser;
99
private readonly coverageReporter;
1010
constructor(inputs: ActionInputs, context: Context);
1111
execute(): Promise<void>;

dist/PrTestCoverageAction.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)