Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JenkinsQueueJobV2] Improved error handling #13242

2 changes: 1 addition & 1 deletion Tasks/JenkinsQueueJobV2/Tests/L0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ describe('JenkinsQueueJob L0 Suite', function () {
});

it('run JenkinsQueueJob with bogus url with parameters', (done) => {
const tp: string = path.join(__dirname, 'L0BogusUrlNoParameters.js');
const tp: string = path.join(__dirname, 'L0BogusUrlParameters.js');
const tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp);

try {
Expand Down
16 changes: 13 additions & 3 deletions Tasks/JenkinsQueueJobV2/jenkinsqueuejobtask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,19 @@ async function doWork() {
//store the job name in the output variable
tl.setVariable('JENKINS_JOB_ID', rootJob.ExecutableNumber.toString());
} catch (e) {
tl.debug(e.message);
process.stderr.write(e + os.EOL);
tl.setResult(tl.TaskResult.Failed, e.message);
let message: string;
if (e instanceof util.HttpError) {
message = e.message;
console.error(e.fullMessage);
console.error(e.body);
} else if (e instanceof Error) {
message = e.message;
console.error(e);
} else {
message = e;
console.error(e);
}
tl.setResult(tl.TaskResult.Failed, message);
}
}

Expand Down
2 changes: 1 addition & 1 deletion Tasks/JenkinsQueueJobV2/job.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,8 @@ export class Job {
thisJob.stopWork(thisJob.queue.TaskOptions.pollIntervalMillis, thisJob.State);
return;
} else if (httpResponse.statusCode !== 200) {
console.error(`Job was killed because of an response with unexpected status code from Jenkins - ${httpResponse.statusCode}`);
Util.failReturnCode(httpResponse, 'Job progress tracking failed to read job result');
tl.error(`Job was killed because of an response with unexpected status code from Jenkins - ${httpResponse.statusCode}`);
thisJob.stopWork(0, JobState.Killed);
} else {
const parsedBody: {result: string, timestamp: number} = JSON.parse(body);
Expand Down
2 changes: 1 addition & 1 deletion Tasks/JenkinsQueueJobV2/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"demands": [],
"version": {
"Major": 2,
"Minor": 171,
"Minor": 173,
"Patch": 0
},
"groups": [
Expand Down
2 changes: 1 addition & 1 deletion Tasks/JenkinsQueueJobV2/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"demands": [],
"version": {
"Major": 2,
"Minor": 171,
"Minor": 173,
"Patch": 0
},
"groups": [
Expand Down
25 changes: 17 additions & 8 deletions Tasks/JenkinsQueueJobV2/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ export function getFullErrorMessage(httpResponse, message: string): string {

export function failReturnCode(httpResponse, message: string): void {
const fullMessage = getFullErrorMessage(httpResponse, message);
tl.debug(message);
tl.error(fullMessage);
process.stderr.write(message + os.EOL);
console.error(fullMessage);
tl.setResult(tl.TaskResult.Failed, message);
}

Expand All @@ -40,6 +38,18 @@ export function fail(message: string): void {
export class FailTaskError extends Error {
}

export class HttpError extends Error {
egor-bryzgalov marked this conversation as resolved.
Show resolved Hide resolved
public body: string;
public fullMessage: string;

constructor(httpResponse: any, message: string) {
super();
this.fullMessage = getFullErrorMessage(httpResponse, message);
this.message = message;
this.body = httpResponse.body;
}
}

export function convertJobName(jobName: string): string {
return '/job/' + jobName.replace('/', '/job/');
}
Expand Down Expand Up @@ -135,7 +145,7 @@ function createRootJob(queueUri: string, jobQueue: JobQueue, taskOptions: TaskOp
defer.reject(error);
}
} else if (httpResponse.statusCode !== 200) {
defer.reject(getFullErrorMessage(httpResponse, 'Job progress tracking failed to read job queue'));
defer.reject(new HttpError(httpResponse, 'Job progress tracking failed to read job queue'));
} else {
const parsedBody: any = JSON.parse(body);
tl.debug(`parsedBody for: ${queueUri} : ${JSON.stringify(parsedBody)}`);
Expand Down Expand Up @@ -256,14 +266,14 @@ function submitJob(taskOptions: TaskOptions): Q.Promise<string> {
defer.reject(err);
}
} else if (httpResponse.statusCode !== 201) {
defer.reject(getFullErrorMessage(httpResponse, 'Job creation failed.'));
defer.reject(new HttpError(httpResponse, 'Job creation failed.'));
} else {
const queueUri: string = addUrlSegment(httpResponse.headers.location, 'api/json');
defer.resolve(queueUri);
}
}).auth(taskOptions.username, taskOptions.password, true);
} else if (httpResponse.statusCode !== 201) {
defer.reject(getFullErrorMessage(httpResponse, 'Job creation failed.'));
defer.reject(new HttpError(httpResponse, 'Job creation failed.'));
} else {
taskOptions.teamBuildPluginAvailable = true;
const jsonBody: any = JSON.parse(body);
Expand Down Expand Up @@ -293,8 +303,7 @@ function getCrumb(taskOptions: TaskOptions): Q.Promise<string> {
taskOptions.crumb = taskOptions.NO_CRUMB;
defer.resolve(taskOptions.NO_CRUMB);
} else if (httpResponse.statusCode !== 200) {
failReturnCode(httpResponse, 'crumb request failed.');
defer.reject(getFullErrorMessage(httpResponse, 'Crumb request failed.'));
defer.reject(new HttpError(httpResponse, 'Crumb request failed.'));
} else {
taskOptions.crumb = body;
tl.debug('crumb: ' + taskOptions.crumb);
Expand Down