azure-pipelines-task-lib 4.4.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/mock-task.d.ts CHANGED
@@ -74,6 +74,7 @@ export declare function find(findPath: string): string[];
74
74
  export declare function rmRF(path: string): void;
75
75
  export declare function mv(source: string, dest: string, force: boolean, continueOnError?: boolean): boolean;
76
76
  export declare function exec(tool: string, args: any, options?: trm.IExecOptions): Q.Promise<number>;
77
+ export declare function execAsync(tool: string, args: any, options?: trm.IExecOptions): Promise<number>;
77
78
  export declare function execSync(tool: string, args: any, options?: trm.IExecSyncOptions): trm.IExecSyncResult;
78
79
  export declare function tool(tool: string): trm.ToolRunner;
79
80
  export interface MatchOptions {
package/mock-task.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getHttpCertConfiguration = exports.getHttpProxyConfiguration = exports.CodeCoverageEnabler = exports.CodeCoveragePublisher = exports.TestPublisher = exports.legacyFindFiles = exports.findMatch = exports.tool = exports.execSync = exports.exec = exports.mv = exports.rmRF = exports.find = exports.retry = exports.cp = exports.ls = exports.which = exports.resolve = exports.mkdirP = exports.checkPath = exports.popd = exports.pushd = exports.cd = exports.cwd = exports.getAgentMode = exports.getPlatform = exports.osType = exports.writeFile = exports.exist = exports.stats = exports.FsStats = exports.loc = exports.setResourcePath = exports.setAnswers = void 0;
3
+ exports.getHttpCertConfiguration = exports.getHttpProxyConfiguration = exports.CodeCoverageEnabler = exports.CodeCoveragePublisher = exports.TestPublisher = exports.legacyFindFiles = exports.findMatch = exports.tool = exports.execSync = exports.execAsync = exports.exec = exports.mv = exports.rmRF = exports.find = exports.retry = exports.cp = exports.ls = exports.which = exports.resolve = exports.mkdirP = exports.checkPath = exports.popd = exports.pushd = exports.cd = exports.cwd = exports.getAgentMode = exports.getPlatform = exports.osType = exports.writeFile = exports.exist = exports.stats = exports.FsStats = exports.loc = exports.setResourcePath = exports.setAnswers = void 0;
4
4
  var path = require("path");
5
5
  var task = require("./task");
6
6
  var tcm = require("./taskcommand");
@@ -299,6 +299,18 @@ function exec(tool, args, options) {
299
299
  return tr.exec(options);
300
300
  }
301
301
  exports.exec = exec;
302
+ //-----------------------------------------------------
303
+ // Exec convenience wrapper
304
+ //-----------------------------------------------------
305
+ function execAsync(tool, args, options) {
306
+ var toolPath = which(tool, true);
307
+ var tr = this.tool(toolPath);
308
+ if (args) {
309
+ tr.arg(args);
310
+ }
311
+ return tr.execAsync(options);
312
+ }
313
+ exports.execAsync = execAsync;
302
314
  function execSync(tool, args, options) {
303
315
  var toolPath = which(tool, true);
304
316
  var tr = this.tool(toolPath);
@@ -36,6 +36,12 @@ export declare class ToolRunner extends events.EventEmitter {
36
36
  line(val: string): ToolRunner;
37
37
  pipeExecOutputToTool(tool: ToolRunner): ToolRunner;
38
38
  private ignoreTempPath;
39
+ execAsync(options?: IExecOptions): Promise<number>;
40
+ /**
41
+ * Exec - use for long running tools where you need to stream live output as it runs
42
+ * @deprecated use `execAsync` instead
43
+ * @returns a promise with return code.
44
+ */
39
45
  exec(options?: IExecOptions): Q.Promise<number>;
40
46
  execSync(options?: IExecSyncOptions): IExecSyncResult;
41
47
  }
@@ -130,6 +130,99 @@ var ToolRunner = /** @class */ (function (_super) {
130
130
  // Exec - use for long running tools where you need to stream live output as it runs
131
131
  // returns a promise with return code.
132
132
  //
133
+ ToolRunner.prototype.execAsync = function (options) {
134
+ var _this = this;
135
+ this._debug('exec tool: ' + this.toolPath);
136
+ this._debug('Arguments:');
137
+ this.args.forEach(function (arg) {
138
+ _this._debug(' ' + arg);
139
+ });
140
+ var success = true;
141
+ options = options || {};
142
+ var ops = {
143
+ cwd: options.cwd || process.cwd(),
144
+ env: options.env || process.env,
145
+ silent: options.silent || false,
146
+ outStream: options.outStream || process.stdout,
147
+ errStream: options.errStream || process.stderr,
148
+ failOnStdErr: options.failOnStdErr || false,
149
+ ignoreReturnCode: options.ignoreReturnCode || false,
150
+ windowsVerbatimArguments: options.windowsVerbatimArguments
151
+ };
152
+ var argString = this.args.join(' ') || '';
153
+ var cmdString = this.toolPath;
154
+ if (argString) {
155
+ cmdString += (' ' + argString);
156
+ }
157
+ // Using split/join to replace the temp path
158
+ cmdString = this.ignoreTempPath(cmdString);
159
+ if (!ops.silent) {
160
+ if (this.pipeOutputToTool) {
161
+ var pipeToolArgString = this.pipeOutputToTool.args.join(' ') || '';
162
+ var pipeToolCmdString = this.ignoreTempPath(this.pipeOutputToTool.toolPath);
163
+ if (pipeToolArgString) {
164
+ pipeToolCmdString += (' ' + pipeToolArgString);
165
+ }
166
+ cmdString += ' | ' + pipeToolCmdString;
167
+ }
168
+ ops.outStream.write('[command]' + cmdString + os.EOL);
169
+ }
170
+ // TODO: filter process.env
171
+ var res = mock.getResponse('exec', cmdString, debug);
172
+ if (res.stdout) {
173
+ this.emit('stdout', res.stdout);
174
+ if (!ops.silent) {
175
+ ops.outStream.write(res.stdout + os.EOL);
176
+ }
177
+ var stdLineArray = res.stdout.split(os.EOL);
178
+ for (var _i = 0, _a = stdLineArray.slice(0, -1); _i < _a.length; _i++) {
179
+ var line = _a[_i];
180
+ this.emit('stdline', line);
181
+ }
182
+ if (stdLineArray.length > 0 && stdLineArray[stdLineArray.length - 1].length > 0) {
183
+ this.emit('stdline', stdLineArray[stdLineArray.length - 1]);
184
+ }
185
+ }
186
+ if (res.stderr) {
187
+ this.emit('stderr', res.stderr);
188
+ success = !ops.failOnStdErr;
189
+ if (!ops.silent) {
190
+ var s = ops.failOnStdErr ? ops.errStream : ops.outStream;
191
+ s.write(res.stderr + os.EOL);
192
+ }
193
+ var stdErrArray = res.stderr.split(os.EOL);
194
+ for (var _b = 0, _c = stdErrArray.slice(0, -1); _b < _c.length; _b++) {
195
+ var line = _c[_b];
196
+ this.emit('errline', line);
197
+ }
198
+ if (stdErrArray.length > 0 && stdErrArray[stdErrArray.length - 1].length > 0) {
199
+ this.emit('errline', stdErrArray[stdErrArray.length - 1]);
200
+ }
201
+ }
202
+ var code = res.code;
203
+ if (!ops.silent) {
204
+ ops.outStream.write('rc:' + res.code + os.EOL);
205
+ }
206
+ if (code != 0 && !ops.ignoreReturnCode) {
207
+ success = false;
208
+ }
209
+ if (!ops.silent) {
210
+ ops.outStream.write('success:' + success + os.EOL);
211
+ }
212
+ return new Promise(function (resolve, reject) {
213
+ if (success) {
214
+ resolve(code);
215
+ }
216
+ else {
217
+ reject(new Error(_this.toolPath + ' failed with return code: ' + code));
218
+ }
219
+ });
220
+ };
221
+ /**
222
+ * Exec - use for long running tools where you need to stream live output as it runs
223
+ * @deprecated use `execAsync` instead
224
+ * @returns a promise with return code.
225
+ */
133
226
  ToolRunner.prototype.exec = function (options) {
134
227
  var _this = this;
135
228
  var defer = Q.defer();
@@ -224,7 +317,6 @@ var ToolRunner = /** @class */ (function (_super) {
224
317
  //
225
318
  ToolRunner.prototype.execSync = function (options) {
226
319
  var _this = this;
227
- var defer = Q.defer();
228
320
  this._debug('exec tool: ' + this.toolPath);
229
321
  this._debug('Arguments:');
230
322
  this.args.forEach(function (arg) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "azure-pipelines-task-lib",
3
- "version": "4.4.0",
3
+ "version": "4.5.0",
4
4
  "description": "Azure Pipelines Task SDK",
5
5
  "main": "./task.js",
6
6
  "typings": "./task.d.ts",
@@ -39,7 +39,7 @@
39
39
  "@types/minimatch": "3.0.3",
40
40
  "@types/mocha": "^9.1.1",
41
41
  "@types/mockery": "^1.4.29",
42
- "@types/node": "^16.11.39",
42
+ "@types/node": "^10.17.0",
43
43
  "@types/q": "^1.5.4",
44
44
  "@types/semver": "^7.3.4",
45
45
  "@types/shelljs": "^0.8.8",
package/task.d.ts CHANGED
@@ -58,7 +58,8 @@ export declare const setErrStream: typeof im._setErrStream;
58
58
  * from agent version 2.142.0 or higher (otherwise will no-op).
59
59
  * @returns void
60
60
  */
61
- export declare function setResult(result: TaskResult, message: string, done?: boolean): void;
61
+ export declare function setResult(result: TaskResult.Succeeded, message?: string, done?: boolean): void;
62
+ export declare function setResult(result: Exclude<TaskResult, 'Succeeded'>, message: string, done?: boolean): void;
62
63
  export declare const setResourcePath: typeof im._setResourcePath;
63
64
  export declare const loc: typeof im._loc;
64
65
  export declare const getVariable: typeof im._getVariable;
@@ -485,6 +486,18 @@ export declare function rmRF(inputPath: string): void;
485
486
  * @param options optional exec options. See IExecOptions
486
487
  * @returns number
487
488
  */
489
+ export declare function execAsync(tool: string, args: any, options?: trm.IExecOptions): Promise<number>;
490
+ /**
491
+ * Exec a tool. Convenience wrapper over ToolRunner to exec with args in one call.
492
+ * Output will be streamed to the live console.
493
+ * Returns promise with return code
494
+ *
495
+ * @deprecated Use the {@link execAsync} method that returns a native Javascript Promise instead
496
+ * @param tool path to tool to exec
497
+ * @param args an arg string or array of args
498
+ * @param options optional exec options. See IExecOptions
499
+ * @returns number
500
+ */
488
501
  export declare function exec(tool: string, args: any, options?: trm.IExecOptions): Q.Promise<number>;
489
502
  /**
490
503
  * Exec a tool synchronously. Convenience wrapper over ToolRunner to execSync with args in one call.
package/task.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.updateReleaseName = exports.addBuildTag = exports.updateBuildNumber = exports.uploadBuildLog = exports.associateArtifact = exports.uploadArtifact = exports.logIssue = exports.logDetail = exports.setProgress = exports.setEndpoint = exports.addAttachment = exports.uploadSummary = exports.prependPath = exports.uploadFile = exports.CodeCoverageEnabler = exports.CodeCoveragePublisher = exports.TestPublisher = exports.getHttpCertConfiguration = exports.getHttpProxyConfiguration = exports.findMatch = exports.filter = exports.match = exports.tool = exports.execSync = exports.exec = exports.rmRF = exports.legacyFindFiles = exports.find = exports.retry = exports.mv = exports.cp = exports.ls = exports.which = exports.resolve = exports.mkdirP = exports.popd = exports.pushd = exports.cd = exports.checkPath = exports.cwd = exports.getAgentMode = exports.getPlatform = exports.osType = exports.writeFile = exports.exist = exports.stats = exports.debug = exports.error = exports.warning = exports.command = exports.setTaskVariable = exports.getTaskVariable = exports.getSecureFileTicket = exports.getSecureFileName = exports.getEndpointAuthorization = exports.getEndpointAuthorizationParameterRequired = exports.getEndpointAuthorizationParameter = exports.getEndpointAuthorizationSchemeRequired = exports.getEndpointAuthorizationScheme = exports.getEndpointDataParameterRequired = exports.getEndpointDataParameter = exports.getEndpointUrlRequired = exports.getEndpointUrl = exports.getPathInputRequired = exports.getPathInput = exports.filePathSupplied = exports.getDelimitedInput = exports.getBoolFeatureFlag = exports.getBoolInput = exports.getInputRequired = exports.getInput = exports.setSecret = exports.setVariable = exports.getVariables = exports.assertAgent = exports.getVariable = exports.loc = exports.setResourcePath = exports.setResult = exports.setErrStream = exports.setStdStream = exports.AgentHostedMode = exports.Platform = exports.FieldType = exports.ArtifactType = exports.IssueType = exports.TaskState = exports.TaskResult = void 0;
3
+ exports.updateReleaseName = exports.addBuildTag = exports.updateBuildNumber = exports.uploadBuildLog = exports.associateArtifact = exports.uploadArtifact = exports.logIssue = exports.logDetail = exports.setProgress = exports.setEndpoint = exports.addAttachment = exports.uploadSummary = exports.prependPath = exports.uploadFile = exports.CodeCoverageEnabler = exports.CodeCoveragePublisher = exports.TestPublisher = exports.getHttpCertConfiguration = exports.getHttpProxyConfiguration = exports.findMatch = exports.filter = exports.match = exports.tool = exports.execSync = exports.exec = exports.execAsync = exports.rmRF = exports.legacyFindFiles = exports.find = exports.retry = exports.mv = exports.cp = exports.ls = exports.which = exports.resolve = exports.mkdirP = exports.popd = exports.pushd = exports.cd = exports.checkPath = exports.cwd = exports.getAgentMode = exports.getPlatform = exports.osType = exports.writeFile = exports.exist = exports.stats = exports.debug = exports.error = exports.warning = exports.command = exports.setTaskVariable = exports.getTaskVariable = exports.getSecureFileTicket = exports.getSecureFileName = exports.getEndpointAuthorization = exports.getEndpointAuthorizationParameterRequired = exports.getEndpointAuthorizationParameter = exports.getEndpointAuthorizationSchemeRequired = exports.getEndpointAuthorizationScheme = exports.getEndpointDataParameterRequired = exports.getEndpointDataParameter = exports.getEndpointUrlRequired = exports.getEndpointUrl = exports.getPathInputRequired = exports.getPathInput = exports.filePathSupplied = exports.getDelimitedInput = exports.getBoolFeatureFlag = exports.getBoolInput = exports.getInputRequired = exports.getInput = exports.setSecret = exports.setVariable = exports.getVariables = exports.assertAgent = exports.getVariable = exports.loc = exports.setResourcePath = exports.setResult = exports.setErrStream = exports.setStdStream = exports.AgentHostedMode = exports.Platform = exports.FieldType = exports.ArtifactType = exports.IssueType = exports.TaskState = exports.TaskResult = void 0;
4
4
  var shell = require("shelljs");
5
5
  var childProcess = require("child_process");
6
6
  var fs = require("fs");
@@ -63,22 +63,6 @@ var AgentHostedMode;
63
63
  //-----------------------------------------------------
64
64
  exports.setStdStream = im._setStdStream;
65
65
  exports.setErrStream = im._setErrStream;
66
- //-----------------------------------------------------
67
- // Results
68
- //-----------------------------------------------------
69
- /**
70
- * Sets the result of the task.
71
- * Execution will continue.
72
- * If not set, task will be Succeeded.
73
- * If multiple calls are made to setResult the most pessimistic call wins (Failed) regardless of the order of calls.
74
- *
75
- * @param result TaskResult enum of Succeeded, SucceededWithIssues, Failed, Cancelled or Skipped.
76
- * @param message A message which will be logged as an error issue if the result is Failed.
77
- * @param done Optional. Instructs the agent the task is done. This is helpful when child processes
78
- * may still be running and prevent node from fully exiting. This argument is supported
79
- * from agent version 2.142.0 or higher (otherwise will no-op).
80
- * @returns void
81
- */
82
66
  function setResult(result, message, done) {
83
67
  exports.debug('task result: ' + TaskResult[result]);
84
68
  // add an error issue
@@ -1280,6 +1264,33 @@ exports.rmRF = rmRF;
1280
1264
  * @param options optional exec options. See IExecOptions
1281
1265
  * @returns number
1282
1266
  */
1267
+ function execAsync(tool, args, options) {
1268
+ var tr = this.tool(tool);
1269
+ tr.on('debug', function (data) {
1270
+ exports.debug(data);
1271
+ });
1272
+ if (args) {
1273
+ if (args instanceof Array) {
1274
+ tr.arg(args);
1275
+ }
1276
+ else if (typeof (args) === 'string') {
1277
+ tr.line(args);
1278
+ }
1279
+ }
1280
+ return tr.execAsync(options);
1281
+ }
1282
+ exports.execAsync = execAsync;
1283
+ /**
1284
+ * Exec a tool. Convenience wrapper over ToolRunner to exec with args in one call.
1285
+ * Output will be streamed to the live console.
1286
+ * Returns promise with return code
1287
+ *
1288
+ * @deprecated Use the {@link execAsync} method that returns a native Javascript Promise instead
1289
+ * @param tool path to tool to exec
1290
+ * @param args an arg string or array of args
1291
+ * @param options optional exec options. See IExecOptions
1292
+ * @returns number
1293
+ */
1283
1294
  function exec(tool, args, options) {
1284
1295
  var tr = this.tool(tool);
1285
1296
  tr.on('debug', function (data) {
package/toolrunner.d.ts CHANGED
@@ -94,6 +94,7 @@ export declare class ToolRunner extends events.EventEmitter {
94
94
  private _cloneExecOptions;
95
95
  private _getSpawnOptions;
96
96
  private _getSpawnSyncOptions;
97
+ private execWithPipingAsync;
97
98
  private execWithPiping;
98
99
  /**
99
100
  * Add argument
@@ -139,6 +140,17 @@ export declare class ToolRunner extends events.EventEmitter {
139
140
  * @param options optional exec options. See IExecOptions
140
141
  * @returns number
141
142
  */
143
+ execAsync(options?: IExecOptions): Promise<number>;
144
+ /**
145
+ * Exec a tool.
146
+ * Output will be streamed to the live console.
147
+ * Returns promise with return code
148
+ *
149
+ * @deprecated Use the `execAsync` method that returns a native Javascript promise instead
150
+ * @param tool path to tool to exec
151
+ * @param options optional exec options. See IExecOptions
152
+ * @returns number
153
+ */
142
154
  exec(options?: IExecOptions): Q.Promise<number>;
143
155
  /**
144
156
  * Exec a tool synchronously.
package/toolrunner.js CHANGED
@@ -516,6 +516,184 @@ var ToolRunner = /** @class */ (function (_super) {
516
516
  result['windowsVerbatimArguments'] = options.windowsVerbatimArguments || this._isCmdFile();
517
517
  return result;
518
518
  };
519
+ ToolRunner.prototype.execWithPipingAsync = function (pipeOutputToTool, options) {
520
+ var _this = this;
521
+ this._debug('exec tool: ' + this.toolPath);
522
+ this._debug('arguments:');
523
+ this.args.forEach(function (arg) {
524
+ _this._debug(' ' + arg);
525
+ });
526
+ var success = true;
527
+ var optionsNonNull = this._cloneExecOptions(options);
528
+ if (!optionsNonNull.silent) {
529
+ optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);
530
+ }
531
+ var cp;
532
+ var toolPath = pipeOutputToTool.toolPath;
533
+ var toolPathFirst;
534
+ var successFirst = true;
535
+ var returnCodeFirst;
536
+ var fileStream;
537
+ var waitingEvents = 0; // number of process or stream events we are waiting on to complete
538
+ var returnCode = 0;
539
+ var error;
540
+ toolPathFirst = this.toolPath;
541
+ // Following node documentation example from this link on how to pipe output of one process to another
542
+ // https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
543
+ //start the child process for both tools
544
+ waitingEvents++;
545
+ var cpFirst = child.spawn(this._getSpawnFileName(optionsNonNull), this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(optionsNonNull));
546
+ waitingEvents++;
547
+ cp = child.spawn(pipeOutputToTool._getSpawnFileName(optionsNonNull), pipeOutputToTool._getSpawnArgs(optionsNonNull), pipeOutputToTool._getSpawnOptions(optionsNonNull));
548
+ fileStream = this.pipeOutputToFile ? fs.createWriteStream(this.pipeOutputToFile) : null;
549
+ return new Promise(function (resolve, reject) {
550
+ var _a, _b, _c, _d;
551
+ if (fileStream) {
552
+ waitingEvents++;
553
+ fileStream.on('finish', function () {
554
+ waitingEvents--; //file write is complete
555
+ fileStream = null;
556
+ if (waitingEvents == 0) {
557
+ if (error) {
558
+ reject(error);
559
+ }
560
+ else {
561
+ resolve(returnCode);
562
+ }
563
+ }
564
+ });
565
+ fileStream.on('error', function (err) {
566
+ waitingEvents--; //there were errors writing to the file, write is done
567
+ _this._debug("Failed to pipe output of " + toolPathFirst + " to file " + _this.pipeOutputToFile + ". Error = " + err);
568
+ fileStream = null;
569
+ if (waitingEvents == 0) {
570
+ if (error) {
571
+ reject(error);
572
+ }
573
+ else {
574
+ resolve(returnCode);
575
+ }
576
+ }
577
+ });
578
+ }
579
+ //pipe stdout of first tool to stdin of second tool
580
+ (_a = cpFirst.stdout) === null || _a === void 0 ? void 0 : _a.on('data', function (data) {
581
+ var _a;
582
+ try {
583
+ if (fileStream) {
584
+ fileStream.write(data);
585
+ }
586
+ (_a = cp.stdin) === null || _a === void 0 ? void 0 : _a.write(data);
587
+ }
588
+ catch (err) {
589
+ _this._debug('Failed to pipe output of ' + toolPathFirst + ' to ' + toolPath);
590
+ _this._debug(toolPath + ' might have exited due to errors prematurely. Verify the arguments passed are valid.');
591
+ }
592
+ });
593
+ (_b = cpFirst.stderr) === null || _b === void 0 ? void 0 : _b.on('data', function (data) {
594
+ if (fileStream) {
595
+ fileStream.write(data);
596
+ }
597
+ successFirst = !optionsNonNull.failOnStdErr;
598
+ if (!optionsNonNull.silent) {
599
+ var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream;
600
+ s.write(data);
601
+ }
602
+ });
603
+ cpFirst.on('error', function (err) {
604
+ var _a;
605
+ waitingEvents--; //first process is complete with errors
606
+ if (fileStream) {
607
+ fileStream.end();
608
+ }
609
+ (_a = cp.stdin) === null || _a === void 0 ? void 0 : _a.end();
610
+ error = new Error(toolPathFirst + ' failed. ' + err.message);
611
+ if (waitingEvents == 0) {
612
+ reject(error);
613
+ }
614
+ });
615
+ cpFirst.on('close', function (code, signal) {
616
+ var _a;
617
+ waitingEvents--; //first process is complete
618
+ if (code != 0 && !optionsNonNull.ignoreReturnCode) {
619
+ successFirst = false;
620
+ returnCodeFirst = code;
621
+ returnCode = returnCodeFirst;
622
+ }
623
+ _this._debug('success of first tool:' + successFirst);
624
+ if (fileStream) {
625
+ fileStream.end();
626
+ }
627
+ (_a = cp.stdin) === null || _a === void 0 ? void 0 : _a.end();
628
+ if (waitingEvents == 0) {
629
+ if (error) {
630
+ reject(error);
631
+ }
632
+ else {
633
+ resolve(returnCode);
634
+ }
635
+ }
636
+ });
637
+ var stdbuffer = '';
638
+ (_c = cp.stdout) === null || _c === void 0 ? void 0 : _c.on('data', function (data) {
639
+ _this.emit('stdout', data);
640
+ if (!optionsNonNull.silent) {
641
+ optionsNonNull.outStream.write(data);
642
+ }
643
+ _this._processLineBuffer(data, stdbuffer, function (line) {
644
+ _this.emit('stdline', line);
645
+ });
646
+ });
647
+ var errbuffer = '';
648
+ (_d = cp.stderr) === null || _d === void 0 ? void 0 : _d.on('data', function (data) {
649
+ _this.emit('stderr', data);
650
+ success = !optionsNonNull.failOnStdErr;
651
+ if (!optionsNonNull.silent) {
652
+ var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream;
653
+ s.write(data);
654
+ }
655
+ _this._processLineBuffer(data, errbuffer, function (line) {
656
+ _this.emit('errline', line);
657
+ });
658
+ });
659
+ cp.on('error', function (err) {
660
+ waitingEvents--; //process is done with errors
661
+ error = new Error(toolPath + ' failed. ' + err.message);
662
+ if (waitingEvents == 0) {
663
+ reject(error);
664
+ }
665
+ });
666
+ cp.on('close', function (code, signal) {
667
+ waitingEvents--; //process is complete
668
+ _this._debug('rc:' + code);
669
+ returnCode = code;
670
+ if (stdbuffer.length > 0) {
671
+ _this.emit('stdline', stdbuffer);
672
+ }
673
+ if (errbuffer.length > 0) {
674
+ _this.emit('errline', errbuffer);
675
+ }
676
+ if (code != 0 && !optionsNonNull.ignoreReturnCode) {
677
+ success = false;
678
+ }
679
+ _this._debug('success:' + success);
680
+ if (!successFirst) { //in the case output is piped to another tool, check exit code of both tools
681
+ error = new Error(toolPathFirst + ' failed with return code: ' + returnCodeFirst);
682
+ }
683
+ else if (!success) {
684
+ error = new Error(toolPath + ' failed with return code: ' + code);
685
+ }
686
+ if (waitingEvents == 0) {
687
+ if (error) {
688
+ reject(error);
689
+ }
690
+ else {
691
+ resolve(returnCode);
692
+ }
693
+ }
694
+ });
695
+ });
696
+ };
519
697
  ToolRunner.prototype.execWithPiping = function (pipeOutputToTool, options) {
520
698
  var _this = this;
521
699
  var _a, _b, _c, _d;
@@ -767,6 +945,104 @@ var ToolRunner = /** @class */ (function (_super) {
767
945
  * @param options optional exec options. See IExecOptions
768
946
  * @returns number
769
947
  */
948
+ ToolRunner.prototype.execAsync = function (options) {
949
+ var _this = this;
950
+ var _a, _b, _c;
951
+ if (this.pipeOutputToTool) {
952
+ return this.execWithPipingAsync(this.pipeOutputToTool, options);
953
+ }
954
+ this._debug('exec tool: ' + this.toolPath);
955
+ this._debug('arguments:');
956
+ this.args.forEach(function (arg) {
957
+ _this._debug(' ' + arg);
958
+ });
959
+ var optionsNonNull = this._cloneExecOptions(options);
960
+ if (!optionsNonNull.silent) {
961
+ optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);
962
+ }
963
+ var state = new ExecState(optionsNonNull, this.toolPath);
964
+ state.on('debug', function (message) {
965
+ _this._debug(message);
966
+ });
967
+ var cp = child.spawn(this._getSpawnFileName(options), this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(options));
968
+ this.childProcess = cp;
969
+ // it is possible for the child process to end its last line without a new line.
970
+ // because stdout is buffered, this causes the last line to not get sent to the parent
971
+ // stream. Adding this event forces a flush before the child streams are closed.
972
+ (_a = cp.stdout) === null || _a === void 0 ? void 0 : _a.on('finish', function () {
973
+ if (!optionsNonNull.silent) {
974
+ optionsNonNull.outStream.write(os.EOL);
975
+ }
976
+ });
977
+ var stdbuffer = '';
978
+ (_b = cp.stdout) === null || _b === void 0 ? void 0 : _b.on('data', function (data) {
979
+ _this.emit('stdout', data);
980
+ if (!optionsNonNull.silent) {
981
+ optionsNonNull.outStream.write(data);
982
+ }
983
+ _this._processLineBuffer(data, stdbuffer, function (line) {
984
+ _this.emit('stdline', line);
985
+ });
986
+ });
987
+ var errbuffer = '';
988
+ (_c = cp.stderr) === null || _c === void 0 ? void 0 : _c.on('data', function (data) {
989
+ state.processStderr = true;
990
+ _this.emit('stderr', data);
991
+ if (!optionsNonNull.silent) {
992
+ var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream;
993
+ s.write(data);
994
+ }
995
+ _this._processLineBuffer(data, errbuffer, function (line) {
996
+ _this.emit('errline', line);
997
+ });
998
+ });
999
+ cp.on('error', function (err) {
1000
+ state.processError = err.message;
1001
+ state.processExited = true;
1002
+ state.processClosed = true;
1003
+ state.CheckComplete();
1004
+ });
1005
+ cp.on('exit', function (code, signal) {
1006
+ state.processExitCode = code;
1007
+ state.processExited = true;
1008
+ _this._debug("Exit code " + code + " received from tool '" + _this.toolPath + "'");
1009
+ state.CheckComplete();
1010
+ });
1011
+ cp.on('close', function (code, signal) {
1012
+ state.processExitCode = code;
1013
+ state.processExited = true;
1014
+ state.processClosed = true;
1015
+ _this._debug("STDIO streams have closed for tool '" + _this.toolPath + "'");
1016
+ state.CheckComplete();
1017
+ });
1018
+ return new Promise(function (resolve, reject) {
1019
+ state.on('done', function (error, exitCode) {
1020
+ if (stdbuffer.length > 0) {
1021
+ _this.emit('stdline', stdbuffer);
1022
+ }
1023
+ if (errbuffer.length > 0) {
1024
+ _this.emit('errline', errbuffer);
1025
+ }
1026
+ cp.removeAllListeners();
1027
+ if (error) {
1028
+ reject(error);
1029
+ }
1030
+ else {
1031
+ resolve(exitCode);
1032
+ }
1033
+ });
1034
+ });
1035
+ };
1036
+ /**
1037
+ * Exec a tool.
1038
+ * Output will be streamed to the live console.
1039
+ * Returns promise with return code
1040
+ *
1041
+ * @deprecated Use the `execAsync` method that returns a native Javascript promise instead
1042
+ * @param tool path to tool to exec
1043
+ * @param options optional exec options. See IExecOptions
1044
+ * @returns number
1045
+ */
770
1046
  ToolRunner.prototype.exec = function (options) {
771
1047
  var _this = this;
772
1048
  var _a, _b, _c;