Skip to content

Commit

Permalink
#669 Support for relative paths when using "publishCodeCoverageResults "
Browse files Browse the repository at this point in the history
  • Loading branch information
danielpalme committed May 20, 2024
1 parent 5337051 commit 5e35c1b
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 82 deletions.
99 changes: 60 additions & 39 deletions src/AzureDevopsTask/ReportGenerator/reportgenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,43 @@ async function executeReportGenerator(): Promise<number> {
return await tool.execAsync();
}

async function run() {
const publishCodeCoverageResults = ((tl.getInput('publishCodeCoverageResults') || 'false') + '').toLowerCase() === 'true';
try {
tl.setResourcePath(path.join( __dirname, 'task.json'));

let code = await executeReportGenerator();
if (code != 0) {
tl.setResult(tl.TaskResult.Failed, tl.loc('FailedMsg'));
return;
}

if (!publishCodeCoverageResults) {
tl.setResult(tl.TaskResult.Succeeded, tl.loc('SucceedMsg'));
return;
}
}
catch (e) {
tl.debug(e.message);
tl.setResult(tl.TaskResult.Failed, e.message);
}

try {
publishCodeCoverageReport();
}
catch (e) {
tl.debug(e.message);
tl.setResult(tl.TaskResult.Failed, tl.loc('FailedToPublishReportMsg') + ': ' + e.message);
return;
}
}

function publishCodeCoverageReport() {
if (((tl.getInput('publishCodeCoverageResults') || 'false') + '').toLowerCase() !== 'true') {
return;
}

const targetdir = trimPathEnd((tl.getInput('targetdir') || ''));
const targetdir = resolvePathToSingleItem(tl.getInput('targetdir') || '');
const reporttypes = (tl.getInput('reporttypes') || '').toLowerCase().split(';');
const createSubdirectoryForAllReportTypes = (tl.getInput('customSettings') || '').toLowerCase().indexOf('createsubdirectoryforallreporttypes=true') > -1;

Expand Down Expand Up @@ -71,49 +102,39 @@ function publishCodeCoverageReport() {
tl.setResult(tl.TaskResult.Succeeded, tl.loc('SucceedMsg'));
}

async function run() {
const publishCodeCoverageResults = ((tl.getInput('publishCodeCoverageResults') || 'false') + '').toLowerCase() === 'true';
try {
tl.setResourcePath(path.join( __dirname, 'task.json'));
// Resolves the specified path to a single item based on whether it contains wildcards
function resolvePathToSingleItem(pathInput: string): string {
// Default to using the specific pathInput value
let resolvedPath: string = pathInput;

let code = await executeReportGenerator();
if (code != 0) {
tl.setResult(tl.TaskResult.Failed, tl.loc('FailedMsg'));
return;
if (pathInput) {
// Find match patterns won't work if the directory has a trailing slash
if (pathInput.endsWith('/') || pathInput.endsWith('\\')) {
pathInput = pathInput.slice(0, -1);
}

if (!publishCodeCoverageResults) {
tl.setResult(tl.TaskResult.Succeeded, tl.loc('SucceedMsg'));
return;
// Resolve matches of the pathInput pattern
const findOptions: tl.FindOptions = { allowBrokenSymbolicLinks: false, followSymbolicLinks: false, followSpecifiedSymbolicLink: false };
const pathMatches: string[] = tl.findMatch(
tl.getVariable('System.DefaultWorkingDirectory'),
pathInput,
findOptions);

// Were any matches found?
if (pathMatches.length === 0) {
resolvedPath = undefined;
} else {
// Select the path to be used from the matches
resolvedPath = pathMatches[0];

// If more than one path matches, use the first and issue a warning
if (pathMatches.length > 1) {
tl.warning(tl.loc('MultipleSummaryFilesFound', resolvedPath));
}
}
}
catch (e) {
tl.debug(e.message);
tl.setResult(tl.TaskResult.Failed, e.message);
}

try {
publishCodeCoverageReport();
}
catch (e) {
tl.debug(e.message);
tl.setResult(tl.TaskResult.Failed, tl.loc('FailedToPublishReportMsg') + ': ' + e.message);
return;
}
}

function trimPathEnd(input: string) {
if (!input || input.length === 0) {
return input;
}

let result = input;

while (result.length > 0 && (result.endsWith('/') || result.endsWith('\\'))) {
result = result.substring(0, result.length - 1);
}

return result;
// Return resolved path
return resolvedPath;
}

run();
6 changes: 5 additions & 1 deletion src/AzureDevopsTask/ReportGenerator/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@
},
"messages": {
"FailedMsg": "ReportGenerator failed",
"SucceedMsg": "Successfully executed ReportGenerator."
"FailedToPublishReportMsg": "Failed to publish report",
"SucceedMsg": "Successfully executed ReportGenerator.",
"PublishCodeCoverageResultsRequiresCobertura": "When using 'publishCodeCoverageResults: true' please add 'Cobertura' as a report type",
"PublishCodeCoverageResultsRequiresHtmlFormat": "When using 'publishCodeCoverageResults: true' please add one of the Html report types",
"MultipleSummaryFilesFound": "Multiple file or directory matches were found. Using the first match: %s"
}
}
99 changes: 60 additions & 39 deletions src/AzureDevopsTaskTest/ReportGenerator/reportgenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,43 @@ async function executeReportGenerator(): Promise<number> {
return await tool.execAsync();
}

async function run() {
const publishCodeCoverageResults = ((tl.getInput('publishCodeCoverageResults') || 'false') + '').toLowerCase() === 'true';
try {
tl.setResourcePath(path.join( __dirname, 'task.json'));

let code = await executeReportGenerator();
if (code != 0) {
tl.setResult(tl.TaskResult.Failed, tl.loc('FailedMsg'));
return;
}

if (!publishCodeCoverageResults) {
tl.setResult(tl.TaskResult.Succeeded, tl.loc('SucceedMsg'));
return;
}
}
catch (e) {
tl.debug(e.message);
tl.setResult(tl.TaskResult.Failed, e.message);
}

try {
publishCodeCoverageReport();
}
catch (e) {
tl.debug(e.message);
tl.setResult(tl.TaskResult.Failed, tl.loc('FailedToPublishReportMsg') + ': ' + e.message);
return;
}
}

function publishCodeCoverageReport() {
if (((tl.getInput('publishCodeCoverageResults') || 'false') + '').toLowerCase() !== 'true') {
return;
}

const targetdir = trimPathEnd((tl.getInput('targetdir') || ''));
const targetdir = resolvePathToSingleItem(tl.getInput('targetdir') || '');
const reporttypes = (tl.getInput('reporttypes') || '').toLowerCase().split(';');
const createSubdirectoryForAllReportTypes = (tl.getInput('customSettings') || '').toLowerCase().indexOf('createsubdirectoryforallreporttypes=true') > -1;

Expand Down Expand Up @@ -71,49 +102,39 @@ function publishCodeCoverageReport() {
tl.setResult(tl.TaskResult.Succeeded, tl.loc('SucceedMsg'));
}

async function run() {
const publishCodeCoverageResults = ((tl.getInput('publishCodeCoverageResults') || 'false') + '').toLowerCase() === 'true';
try {
tl.setResourcePath(path.join( __dirname, 'task.json'));
// Resolves the specified path to a single item based on whether it contains wildcards
function resolvePathToSingleItem(pathInput: string): string {
// Default to using the specific pathInput value
let resolvedPath: string = pathInput;

let code = await executeReportGenerator();
if (code != 0) {
tl.setResult(tl.TaskResult.Failed, tl.loc('FailedMsg'));
return;
if (pathInput) {
// Find match patterns won't work if the directory has a trailing slash
if (pathInput.endsWith('/') || pathInput.endsWith('\\')) {
pathInput = pathInput.slice(0, -1);
}

if (!publishCodeCoverageResults) {
tl.setResult(tl.TaskResult.Succeeded, tl.loc('SucceedMsg'));
return;
// Resolve matches of the pathInput pattern
const findOptions: tl.FindOptions = { allowBrokenSymbolicLinks: false, followSymbolicLinks: false, followSpecifiedSymbolicLink: false };
const pathMatches: string[] = tl.findMatch(
tl.getVariable('System.DefaultWorkingDirectory'),
pathInput,
findOptions);

// Were any matches found?
if (pathMatches.length === 0) {
resolvedPath = undefined;
} else {
// Select the path to be used from the matches
resolvedPath = pathMatches[0];

// If more than one path matches, use the first and issue a warning
if (pathMatches.length > 1) {
tl.warning(tl.loc('MultipleSummaryFilesFound', resolvedPath));
}
}
}
catch (e) {
tl.debug(e.message);
tl.setResult(tl.TaskResult.Failed, e.message);
}

try {
publishCodeCoverageReport();
}
catch (e) {
tl.debug(e.message);
tl.setResult(tl.TaskResult.Failed, tl.loc('FailedToPublishReportMsg') + ': ' + e.message);
return;
}
}

function trimPathEnd(input: string) {
if (!input || input.length === 0) {
return input;
}

let result = input;

while (result.length > 0 && (result.endsWith('/') || result.endsWith('\\'))) {
result = result.substring(0, result.length - 1);
}

return result;
// Return resolved path
return resolvedPath;
}

run();
5 changes: 3 additions & 2 deletions src/AzureDevopsTaskTest/ReportGenerator/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"version": {
"Major": 5,
"Minor": 2,
"Patch": 5
"Patch": 4
},
"instanceNameFormat": "ReportGeneratorTest",
"groups": [
Expand Down Expand Up @@ -162,6 +162,7 @@
"FailedToPublishReportMsg": "Failed to publish report",
"SucceedMsg": "Successfully executed ReportGenerator.",
"PublishCodeCoverageResultsRequiresCobertura": "When using 'publishCodeCoverageResults: true' please add 'Cobertura' as a report type",
"PublishCodeCoverageResultsRequiresHtmlFormat": "When using 'publishCodeCoverageResults: true' please add one of the Html report types"
"PublishCodeCoverageResultsRequiresHtmlFormat": "When using 'publishCodeCoverageResults: true' please add one of the Html report types",
"MultipleSummaryFilesFound": "Multiple file or directory matches were found. Using the first match: %s"
}
}
2 changes: 1 addition & 1 deletion src/AzureDevopsTaskTest/vss-extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"manifestVersion": 1,
"id": "reportgeneratortest",
"name": "ReportGeneratorTest",
"version": "5.2.5",
"version": "5.2.4",
"publisher": "Palmmedia",
"public": false,
"targets": [
Expand Down

0 comments on commit 5e35c1b

Please sign in to comment.