diff --git a/src/AzureDevopsTask/ReportGenerator/reportgenerator.ts b/src/AzureDevopsTask/ReportGenerator/reportgenerator.ts index 1f51682b..0ff4841e 100644 --- a/src/AzureDevopsTask/ReportGenerator/reportgenerator.ts +++ b/src/AzureDevopsTask/ReportGenerator/reportgenerator.ts @@ -29,12 +29,43 @@ async function executeReportGenerator(): Promise { 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; @@ -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(); \ No newline at end of file diff --git a/src/AzureDevopsTask/ReportGenerator/task.json b/src/AzureDevopsTask/ReportGenerator/task.json index cc0bb65b..4c8e75b8 100644 --- a/src/AzureDevopsTask/ReportGenerator/task.json +++ b/src/AzureDevopsTask/ReportGenerator/task.json @@ -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" } } diff --git a/src/AzureDevopsTaskTest/ReportGenerator/reportgenerator.ts b/src/AzureDevopsTaskTest/ReportGenerator/reportgenerator.ts index 1f51682b..0ff4841e 100644 --- a/src/AzureDevopsTaskTest/ReportGenerator/reportgenerator.ts +++ b/src/AzureDevopsTaskTest/ReportGenerator/reportgenerator.ts @@ -29,12 +29,43 @@ async function executeReportGenerator(): Promise { 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; @@ -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(); \ No newline at end of file diff --git a/src/AzureDevopsTaskTest/ReportGenerator/task.json b/src/AzureDevopsTaskTest/ReportGenerator/task.json index b761db14..4fb72e71 100644 --- a/src/AzureDevopsTaskTest/ReportGenerator/task.json +++ b/src/AzureDevopsTaskTest/ReportGenerator/task.json @@ -13,7 +13,7 @@ "version": { "Major": 5, "Minor": 2, - "Patch": 5 + "Patch": 4 }, "instanceNameFormat": "ReportGeneratorTest", "groups": [ @@ -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" } } diff --git a/src/AzureDevopsTaskTest/vss-extension.json b/src/AzureDevopsTaskTest/vss-extension.json index 6d8f637e..9ccc3e3a 100644 --- a/src/AzureDevopsTaskTest/vss-extension.json +++ b/src/AzureDevopsTaskTest/vss-extension.json @@ -2,7 +2,7 @@ "manifestVersion": 1, "id": "reportgeneratortest", "name": "ReportGeneratorTest", - "version": "5.2.5", + "version": "5.2.4", "publisher": "Palmmedia", "public": false, "targets": [