Skip to content

Commit a5c5562

Browse files
committed
Changed how files are located
Switched to `glob` for file searching.
1 parent ef561d9 commit a5c5562

5 files changed

Lines changed: 115 additions & 38 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,24 +79,23 @@ The above command will generate an opencover report in ```TestResults/coverage.o
7979

8080

8181
You don't necessarily have to use the above example to generate the opencover report. If you have other means of doing this, then that should not cause any problems. You actually don't even need a .NET solution. As long as you can provide a path for the coverage file.
82+
The path is parsed using [Glob](https://www.npmjs.com/package/glob), and this enables you to use patterns to locate coverage files. Be aware, if more than one file is returned, only the first will be used.
8283

8384
## Inputs
8485
| Name | Required | Description |
8586
| ------------------- |:---------:| ----------------------------------------------------------------------------------------- |
8687
| label | Optional | The badge label. For example "Unit Test Coverage". Default value is "Test Coverage" |
8788
| color | Optional | The color of the badge. See https://shields.io/ for options. Default value is brightgreen |
88-
| path | Required | The path to the opencover.xml file or test results directory |
89-
| filename | Optional | The name of opencover.xml file. Optional if full path is provided in path |
90-
| discover-directory | Optional | Ff true, attempts to locate the most recent test run directory |
89+
| path | Required | The path or pattern to locate the opencover.xml file |
9190
| gist-filename | Optional | Filename of the Gist used for storing the badge data |
9291
| gist-id | Optional | ID if the Gist used for storing the badge data |
9392
| gist-auth-token | Optional | Auth token that alows to write to the given Gist |
9493

9594
## Outputs
96-
| Name | Description |
97-
| --------------- | ------------|
95+
| Name | Description |
96+
| --------------- | --------------------------------------------------------------------------|
9897
| percentage | The code coverage percentage extracted from the file in the provided path |
99-
| badge | The badge data as in json format as required by shields.io |
98+
| badge | The badge data as in json format as required by shields.io |
10099

101100
## Example Usage
102101
Below is a snippet of a typical .NET workflow that will restore dependencies, build solution and run unit tests. After those actions the .NET Code Coverage Badge will be generated and the ```percentage``` printet to the workflow log. If you copy-paste this, be sure to rename the ```<MyProject>``` and adjust tje ```gist-filename```, ```gist-id``` and ```gist-auth-token``` to your configuration.

action.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,6 @@ inputs:
1616
path:
1717
description: 'The path to the opencover.xml file or the test results directory'
1818
required: true
19-
filename:
20-
description: 'The name of opencover.xml file. Optional if full path is provided in path'
21-
required: false
22-
discover-directory:
23-
description: 'If true, attempts to locate the most recent test run directory'
24-
required: false
2519
gist-filename:
2620
description: 'Filename of the Gist used for storing the badge data'
2721
required: false

index.js

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,40 @@
11
const core = require('@actions/core');
22
const http = require('https');
33
const fs = require('fs');
4-
const path = require('path');
4+
const glob = require('glob');
55

66
try {
77
const label = core.getInput('label');
8-
const filepath = core.getInput('path');
9-
const filename = core.getInput('filename');
10-
const discoverDirectory = core.getInput('discover-directory');
8+
const path = core.getInput('path');
119
const color = core.getInput('color');
1210
const gistFilename = core.getInput('gist-filename');
1311
const gistId = core.getInput('gist-id');
1412
const gistAuthToken = core.getInput('gist-auth-token');
13+
14+
const filePath = getFilePath(path);
15+
const testReport = readFile(filePath);
16+
const coveragePercentage = extractSummaryFromOpencover(testReport);
17+
const badgeData = createBadgeData(label, coveragePercentage, color);
1518

16-
const dir = !!discoverDirectory ?
17-
path.join(filepath, getMostRecentDirectory(filepath).file, filename) :
18-
path.join(filepath, filename);
19-
20-
let testReport = readFile(dir);
21-
let coveragePercentage = extractSummaryFromOpencover(testReport);
22-
let badgeData = createBadgeData(label, coveragePercentage, color);
2319
publishBadge(badgeData, gistFilename, gistId, gistAuthToken);
2420

2521
core.setOutput("badge", badgeData);
2622
core.setOutput("percentage", coveragePercentage);
23+
2724
} catch (error) {
2825
core.setFailed(error);
2926
}
3027

28+
function getFilePath(filePath) {
29+
const files = glob.sync(filePath);
30+
31+
if (files.length === 0) throw `File not found at the location: ${filePath}`;
32+
if (files.length > 0)
33+
console.warn('Found multiple files matching critera. Coverage results may be inaccurate.', files);
34+
35+
return files[0]
36+
}
37+
3138
function publishBadge(badgeData, gistFilename, gistId, gistAuthToken) {
3239
if (gistFilename == null || gistId == null || gistAuthToken == null) { //TODO: Test for null or undefined?
3340
console.log("Could not publish badge. Gist filename, id and auth token are required to post shields.io data");
@@ -38,18 +45,6 @@ function publishBadge(badgeData, gistFilename, gistId, gistAuthToken) {
3845
}
3946
}
4047

41-
function getMostRecentDirectory(dir) {
42-
const files = orderMostRecentDirectories(dir);
43-
return files.length ? files[0] : undefined;
44-
}
45-
46-
function orderMostRecentDirectories(dir) {
47-
return fs.readdirSync(dir)
48-
.filter(file => fs.lstatSync(path.join(dir, file)).isDirectory())
49-
.map(file => ({ file, mtime: fs.lstatSync(path.join(dir, file)).mtime }))
50-
.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
51-
}
52-
5348
function postGist(badgeData, gistFilename, gistId, gistAuthToken) {
5449
const request = JSON.stringify({
5550
files: {[gistFilename]: {content: JSON.stringify(badgeData)}}
@@ -78,7 +73,7 @@ function postGist(badgeData, gistFilename, gistId, gistAuthToken) {
7873
}
7974

8075
function createBadgeData(label, coveragePercentage, color) {
81-
let badgeData = {
76+
const badgeData = {
8277
schemaVersion: 1,
8378
label: label,
8479
message: coveragePercentage + '%',
@@ -97,8 +92,8 @@ function readFile(path) {
9792
}
9893

9994
function extractSummaryFromOpencover(content) {
100-
let rx = /(?<=sequenceCoverage=")\d*\.*\d*(?=")/m;
101-
let arr = rx.exec(content);
95+
const rx = /(?<=sequenceCoverage=")\d*\.*\d*(?=")/m;
96+
const arr = rx.exec(content);
10297

10398
if (arr == null) {
10499
throw new Error('No code coverage percentage was found in the provided opencover report. Was looking for an xml elemet named Summary with the attribute sequenceCoverage');

package-lock.json

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

0 commit comments

Comments
 (0)