Skip to content

Commit

Permalink
Release v1.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
GaelGirodon committed May 22, 2024
1 parent 9958a9a commit 69b5c64
Show file tree
Hide file tree
Showing 23 changed files with 351 additions and 305 deletions.
9 changes: 0 additions & 9 deletions .eslintrc.yml

This file was deleted.

9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

All notable changes to this project will be documented in this file.

## 1.4.0 - 2024-05-22

- Improve JUnit reports loading
- Refine file patterns
- Load all reports instead of only the first one
- Read only top-level `<testsuite>` tags
- Improve documentation
- Update dependencies

## 1.3.0 - 2024-04-27

- Improve JUnit report format support
Expand Down
32 changes: 19 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ Only matched report formats will get a file uploaded to the Gist.

### Go

Write the verbose test output (`>` or `tee`) with coverage enabled to a
Write the verbose test output (`>` or `tee`) with coverage enabled to a single
`test*.{out,txt}` file next to the `go.mod` file:

- `RUN`, `PASS` and `FAIL` flags will be used to count tests
Expand All @@ -100,21 +100,26 @@ sure the last percentage is the global coverage value.

### JUnit

Write the test report to a file matching:
Write test report(s) to file(s) matching:

- `**/TEST-*.xml`
- `**/report.xml`
- `**/*TEST*.xml`
- `**/*test*.xml`
- `**/*junit*.xml`

This is the default format and location with JUnit, but most test runners
support this format too, natively or using an additional reporter, e.g.:

- **Mocha**: `mocha --reporter mocha-junit-reporter`
- **Jest**: `jest --reporters="jest-junit"`
support this format too, natively or using an additional reporter:

- **Maven**: `mvn test` → `target/{surefire,failsafe}-reports/TEST-*.xml`
- **Gradle**: `gradle test` → `build/test-results/test/**/TEST-*.xml`
- **Node.js**: `node --test --test-reporter=junit --test-reporter-destination=report.xml`
- **Mocha**: `mocha --reporter mocha-junit-reporter` → `test-results.xml`
- **Jest**: `jest --reporters="jest-junit"` → `junit.xml`
- **Deno**: `deno test --junit-path=report.xml`
- **PHPUnit**: `phpunit --log-junit report.xml`

The number of tests and failures will be extracted from `<testsuite>` tags.
The number of tests and failures will be extracted from top-level `<testsuite>`
tags, from all matching and valid report files.

➡️ `{repo}-[{ref}-]junit-tests.json`

Expand All @@ -126,14 +131,14 @@ Write the coverage report to a file matching:
- `**/*coverage*.xml`

This is the default format and location with Cobertura, but most code coverage
tools support this format too, natively or using an additional reporter, e.g.:
tools support this format too, natively or using an additional reporter:

- **c8**: `c8 --reporter cobertura [...]`
- **nyc**: `nyc --reporter cobertura [...]`
- **c8**: `c8 --reporter cobertura [...]` → `coverage/cobertura-coverage.xml`
- **nyc**: `nyc --reporter cobertura [...]` → `coverage/cobertura-coverage.xml`
- **PHPUnit**: `phpunit --coverage-cobertura coverage.xml`

The coverage will be extracted from the `line-rate` attribute of the
`<coverage>` tag.
`<coverage>` tag, from the first matching and valid report file.

➡️ `{repo}-[{ref}-]cobertura-coverage.json`

Expand All @@ -147,7 +152,8 @@ Write the coverage report to a file matching:
This is the default format and location with JaCoCo, but some code coverage
tools may support this format too.

The coverage will be extracted from the last `<counter>` tag with type `LINE`.
The coverage will be extracted from the last `<counter>` tag with type `LINE`,
from the first matching and valid report file.

➡️ `{repo}-[{ref}-]jacoco-coverage.json`

Expand Down
82 changes: 60 additions & 22 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33442,17 +33442,31 @@ var glob = __nccwpck_require__(8090);


/**
* Returns files and directories matching the glob patterns,
* sorted by the nearest.
* Returns files matching the glob patterns, sorted by ascending depth
* and name, excluding some common unwanted directories from the search.
* @param {string[]} patterns Glob patterns
* @return {Promise<string[]>} Files sorted by the nearest.
* @return {Promise<string[]>} Files sorted by the nearest
*/
async function globNearest(patterns) {
const globber = await glob.create(patterns.join('\n'));
const safePatterns = [
...patterns,
'!**/.git/**',
'!**/.idea/**',
'!**/.vscode/**',
'!**/node_modules/**',
'!**/vendor/**'
];
const globber = await glob.create(safePatterns.join('\n'), {
followSymbolicLinks: false,
implicitDescendants: false,
matchDirectories: false
});
const files = await globber.glob();
return files.sort((a, b) => {
return (a.match(/[\\/]/g)?.length ?? 0) - (b.match(/[\\/]/g)?.length ?? 0);
})
const depthDiff = (a.match(/[\\/]/g)?.length ?? 0)
- (b.match(/[\\/]/g)?.length ?? 0);
return depthDiff !== 0 ? depthDiff : a.localeCompare(b);
});
}

;// CONCATENATED MODULE: ./src/reports/go.js
Expand Down Expand Up @@ -33487,7 +33501,7 @@ async function getReports(root) {
}
const passed = (report.match(/--- PASS/g) || []).length;
const failed = (report.match(/--- FAIL/g) || []).length;
badges.push({ type: 'tests', data: { passed, failed, tests } })
badges.push({ type: 'tests', data: { passed, failed, tests } });
const percentages = report.match(/(?<=\s)[0-9.]+(?=%)/g);
if (percentages && percentages.length >= 1) {
const coverage = parseFloat(percentages.slice(-1)[0]);
Expand All @@ -33513,33 +33527,57 @@ async function getReports(root) {
async function junit_getReports(root) {
core.info('Load JUnit tests report');
const patterns = [
(0,external_path_.join)(root, '**/TEST-*.xml'),
(0,external_path_.join)(root, '**/report.xml'),
(0,external_path_.join)(root, '**/*TEST*.xml'),
(0,external_path_.join)(root, '**/*test*.xml'),
(0,external_path_.join)(root, '**/*junit*.xml')
];
const reports = await globNearest(patterns);
const badges = [];
const data = { passed: 0, failed: 0, tests: 0 };
let count = 0;
for (const r of reports) {
core.info(`Load JUnit report '${r}'`);
const report = await external_fs_.promises.readFile(r, { encoding: 'utf8' });
const testSuites = report.match(/<testsuite[^s]([^>]+)>/g);
if (!testSuites) {
const testSuites = await getTestSuiteTags(r);
if (testSuites.length === 0) {
core.info('Report is not a valid JUnit report');
continue; // Invalid report file, trying the next one
}
const data = { passed: 0, failed: 0, tests: 0 };
for (const ts of testSuites) {
data.failed += parseInt(ts.match(/failures="([0-9]+)"/)?.[1] ?? "0");
data.failed += parseInt(ts.match(/errors="([0-9]+)"/)?.[1] ?? "0");
data.tests += parseInt(ts.match(/tests="([0-9]+)"/)?.[1] ?? "0");
data.failed += parseInt(ts.match(/failures="([0-9]+)"/)?.[1] ?? '0');
data.failed += parseInt(ts.match(/errors="([0-9]+)"/)?.[1] ?? '0');
data.tests += parseInt(ts.match(/tests="([0-9]+)"/)?.[1] ?? '0');
}
data.passed = data.tests - data.failed;
badges.push({ type: 'tests', data })
break; // Successfully loaded a report file, can return now
count++;
}
core.info(`Loaded ${badges.length} JUnit report(s)`);
return badges;
data.passed = data.tests - data.failed;
core.info(`Loaded ${count} JUnit report(s)`);
return [{ type: 'tests', data }];
}

/**
* Extract top-level `<testsuite>` opening tags from the given JUnit test
* report file. Some test runners output nested `<testsuite>` tags (e.g.
* Node.js test runner), these nested tags must be ignored as values are
* aggregated in top-level ones.
* @param {string} path Path to the JUnit test report file
* @returns {Promise<string[]>} Top-level `<testsuite>` opening tags
*/
async function getTestSuiteTags(path) {
const testSuites = [];
let depth = 0;
const report = await external_fs_.promises.readFile(path, { encoding: 'utf8' });
const tags = report.match(/<\/?testsuite(?:[^s>][^>]+|\s*)>/g) ?? [];
for (const tag of tags) {
if (tag.startsWith('</')) {
depth--;
} else {
if (depth === 0) {
testSuites.push(tag);
}
depth++;
}
}
return testSuites;
}

;// CONCATENATED MODULE: ./src/reports/cobertura.js
Expand Down Expand Up @@ -33651,7 +33689,7 @@ async function reports_getReports() {
core.warning(`Skipping ${id} report format: ${error}`);
}
}
core.info(`Loaded ${all.length} reports`);
core.info(`Loaded ${all.length} report(s)`);
return all;
}

Expand Down
8 changes: 8 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import globals from 'globals';
import pluginJs from '@eslint/js';

export default [
{ languageOptions: { globals: globals.node } },
{ languageOptions: { globals: globals.mocha } },
pluginJs.configs.recommended
];
Loading

0 comments on commit 69b5c64

Please sign in to comment.