in Tasks/MavenV2/maventask.ts [123:295]
async function execBuild() {
// Maven task orchestration occurs as follows:
// 1. Check that Maven exists by executing it to retrieve its version.
// 2. Apply any goals for static code analysis tools selected by the user.
// 3. Run Maven. Compilation or test errors will cause this to fail.
// In case the build has failed, the analysis will still succeed but the report will have less data.
// 4. Attempt to collate and upload static code analysis build summaries and artifacts.
// 5. Always publish test results even if tests fail, causing this task to fail.
// 6. If #3 or #4 above failed, exit with an error code to mark the entire step as failed.
ccReportTask = await execEnableCodeCoverage();
var userRunFailed: boolean = false;
var codeAnalysisFailed: boolean = false;
// Setup tool runner that executes Maven only to retrieve its version
var mvnGetVersion = tl.tool(mvnExec);
mvnGetVersion.arg('-version');
configureMavenOpts();
// 1. Check that Maven exists by executing it to retrieve its version.
let settingsXmlFile: string = null;
await mvnGetVersion.exec()
.fail(function (err) {
console.error("Maven is not installed on the agent");
tl.setResult(tl.TaskResult.Failed, "Build failed."); // tl.exit sets the step result but does not stop execution
process.exit(1);
})
.then(function (code) {
// Setup tool runner to execute Maven goals
if (authenticateFeed) {
var mvnRun = tl.tool(mvnExec);
mvnRun.arg('-f');
mvnRun.arg(mavenPOMFile);
mvnRun.arg('help:effective-pom');
if(mavenOptions) {
mvnRun.line(mavenOptions);
}
return util.collectFeedRepositoriesFromEffectivePom(mvnRun.execSync()['stdout'])
.then(function (repositories) {
if (!repositories || !repositories.length) {
tl.debug('No built-in repositories were found in pom.xml');
util.publishMavenInfo(tl.loc('AuthenticationNotNecessary'));
return Q.resolve(true);
}
tl.debug('Repositories: ' + JSON.stringify(repositories));
let mavenFeedInfo:string = '';
for (let i = 0; i < repositories.length; ++i) {
if (repositories[i].id) {
mavenFeedInfo = mavenFeedInfo.concat(tl.loc('UsingAuthFeed')).concat(repositories[i].id + '\n');
}
}
util.publishMavenInfo(mavenFeedInfo);
settingsXmlFile = path.join(tl.getVariable('Agent.TempDirectory'), 'settings.xml');
tl.debug('checking to see if there are settings.xml in use');
let options: RegExpMatchArray = mavenOptions ? mavenOptions.match(/([^" ]*("([^"\\]*(\\.[^"\\]*)*)")[^" ]*)|[^" ]+/g) : undefined;
if (options) {
mavenOptions = '';
for (let i = 0; i < options.length; ++i) {
if ((options[i] === '--settings' || options[i] === '-s') && (i + 1) < options.length) {
i++; // increment to the file name
let suppliedSettingsXml: string = path.resolve(tl.cwd(), options[i]);
// Avoid copying settings file to itself
if (path.relative(suppliedSettingsXml, settingsXmlFile) !== '') {
tl.cp(suppliedSettingsXml, settingsXmlFile, '-f');
} else {
tl.debug('Settings file is already in the correct location. Copying skipped.');
}
tl.debug('using settings file: ' + settingsXmlFile);
} else {
if (mavenOptions) {
mavenOptions = mavenOptions.concat(' ');
}
mavenOptions = mavenOptions.concat(options[i]);
}
}
}
return util.mergeCredentialsIntoSettingsXml(settingsXmlFile, repositories);
})
.catch(function (err) {
return Q.reject(err);
});
} else {
tl.debug('Built-in Maven feed authentication is disabled');
return Q.resolve(true);
}
})
.fail(function (err) {
tl.error(err.message);
userRunFailed = true; // Record the error and continue
})
.then(function (code) {
// Setup tool runner to execute Maven goals
var mvnRun = tl.tool(mvnExec);
mvnRun.arg('-f');
mvnRun.arg(mavenPOMFile);
if (settingsXmlFile) {
mvnRun.arg('-s');
mvnRun.arg(settingsXmlFile);
}
mvnRun.line(mavenOptions);
if (isCodeCoverageOpted && mavenGoals.indexOf('clean') == -1) {
mvnRun.arg('clean');
}
mvnRun.arg(mavenGoals);
// 2. Apply any goals for static code analysis tools selected by the user.
mvnRun = applySonarQubeArgs(mvnRun, execFileJacoco);
mvnRun = codeAnalysisOrchestrator.configureBuild(mvnRun);
// Read Maven standard output
mvnRun.on('stdout', function (data) {
processMavenOutput(data);
});
// 3. Run Maven. Compilation or test errors will cause this to fail.
return mvnRun.exec(util.getExecOptions());
})
.fail(function (err) {
console.error(err.message);
userRunFailed = true; // Record the error and continue
})
.then(function (code: any) {
if (code && code['code'] != 0) {
userRunFailed = true;
}
// 4. Attempt to collate and upload static code analysis build summaries and artifacts.
// The files won't be created if the build failed, and the user should probably fix their build first.
if (userRunFailed) {
console.error('Could not retrieve code analysis results - Maven run failed.');
return;
}
// Otherwise, start uploading relevant build summaries.
tl.debug('Processing code analysis results');
return codeAnalysisOrchestrator.publishCodeAnalysisResults();
})
.fail(function (err) {
console.error(err.message);
// Looks like: "Code analysis failed."
console.error(tl.loc('codeAnalysis_ToolFailed', 'Code'));
codeAnalysisFailed = true;
})
.then(function () {
// 5. Always publish test results even if tests fail, causing this task to fail.
if (publishJUnitResults == 'true') {
publishJUnitTestResults(testResultsFiles);
}
publishCodeCoverage(isCodeCoverageOpted).then(function() {
tl.debug('publishCodeCoverage userRunFailed=' + userRunFailed);
// 6. If #3 or #4 above failed, exit with an error code to mark the entire step as failed.
if (userRunFailed || codeAnalysisFailed || codeCoverageFailed) {
tl.setResult(tl.TaskResult.Failed, "Build failed."); // Set task failure
}
else {
tl.setResult(tl.TaskResult.Succeeded, "Build Succeeded."); // Set task success
}
})
.fail(function (err) {
tl.setResult(tl.TaskResult.Failed, "Build failed."); // Set task failure
});
// Do not force an exit as publishing results is async and it won't have finished
})
.fail(function (err) {
// Set task failure if get exception at step 5
console.error(err.message);
tl.setResult(tl.TaskResult.Failed, "Build failed.");
});
}