Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions node/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@ Backported from ver.`3.4.0`:
## 4.4.0

- Add `getBoolFeatureFlag` [#936](https://github.com/microsoft/azure-pipelines-task-lib/pull/936)

## 4.5.0

- Added `execAsync` methods that return native promises. Marked `exec` methods that return promises from the Q library as deprecated [#905](https://github.com/microsoft/azure-pipelines-task-lib/pull/905)
13 changes: 12 additions & 1 deletion node/mock-task.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import Q = require('q');
import path = require('path');
import fs = require('fs');
Expand Down Expand Up @@ -335,6 +334,18 @@ export function exec(tool: string, args: any, options?: trm.IExecOptions): Q.Pro
return tr.exec(options);
}

//-----------------------------------------------------
// Exec convenience wrapper
//-----------------------------------------------------
export function execAsync(tool: string, args: any, options?: trm.IExecOptions): Promise<number> {
var toolPath = which(tool, true);
var tr: trm.ToolRunner = this.tool(toolPath);
if (args) {
tr.arg(args);
}
return tr.execAsync(options);
}

export function execSync(tool: string, args: any, options?: trm.IExecSyncOptions): trm.IExecSyncResult {
var toolPath = which(tool, true);
var tr: trm.ToolRunner = this.tool(toolPath);
Expand Down
110 changes: 107 additions & 3 deletions node/mock-toolrunner.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import Q = require('q');
import os = require('os');
import events = require('events');
Expand Down Expand Up @@ -162,6 +161,113 @@ export class ToolRunner extends events.EventEmitter {
// Exec - use for long running tools where you need to stream live output as it runs
// returns a promise with return code.
//
public execAsync(options?: IExecOptions): Promise<number> {
this._debug('exec tool: ' + this.toolPath);
this._debug('Arguments:');
this.args.forEach((arg) => {
this._debug(' ' + arg);
});

var success = true;
options = options || <IExecOptions>{};

var ops: IExecOptions = {
cwd: options.cwd || process.cwd(),
env: options.env || process.env,
silent: options.silent || false,
outStream: options.outStream || process.stdout,
errStream: options.errStream || process.stderr,
failOnStdErr: options.failOnStdErr || false,
ignoreReturnCode: options.ignoreReturnCode || false,
windowsVerbatimArguments: options.windowsVerbatimArguments
};

var argString = this.args.join(' ') || '';
var cmdString = this.toolPath;
if (argString) {
cmdString += (' ' + argString);
}

// Using split/join to replace the temp path
cmdString = this.ignoreTempPath(cmdString);

if (!ops.silent) {
if(this.pipeOutputToTool) {
var pipeToolArgString = this.pipeOutputToTool.args.join(' ') || '';
var pipeToolCmdString = this.ignoreTempPath(this.pipeOutputToTool.toolPath);
if(pipeToolArgString) {
pipeToolCmdString += (' ' + pipeToolArgString);
}

cmdString += ' | ' + pipeToolCmdString;
}

ops.outStream.write('[command]' + cmdString + os.EOL);
}

// TODO: filter process.env
var res = mock.getResponse('exec', cmdString, debug);
if (res.stdout) {
this.emit('stdout', res.stdout);
if (!ops.silent) {
ops.outStream.write(res.stdout + os.EOL);
}
const stdLineArray = res.stdout.split(os.EOL);
for (const line of stdLineArray.slice(0, -1)) {
this.emit('stdline', line);
}
if(stdLineArray.length > 0 && stdLineArray[stdLineArray.length - 1].length > 0) {
this.emit('stdline', stdLineArray[stdLineArray.length - 1]);
}
}

if (res.stderr) {
this.emit('stderr', res.stderr);

success = !ops.failOnStdErr;
if (!ops.silent) {
var s = ops.failOnStdErr ? ops.errStream : ops.outStream;
s.write(res.stderr + os.EOL);
}
const stdErrArray = res.stderr.split(os.EOL);
for (const line of stdErrArray.slice(0, -1)) {
this.emit('errline', line);
}
if (stdErrArray.length > 0 && stdErrArray[stdErrArray.length - 1].length > 0) {
this.emit('errline', stdErrArray[stdErrArray.length - 1]);
}
}


var code = res.code;

if (!ops.silent) {
ops.outStream.write('rc:' + res.code + os.EOL);
}

if (code != 0 && !ops.ignoreReturnCode) {
success = false;
}

if (!ops.silent) {
ops.outStream.write('success:' + success + os.EOL);
}

return new Promise((resolve, reject) => {
if (success) {
resolve(code);
}
else {
reject(new Error(this.toolPath + ' failed with return code: ' + code));
}
});
}

/**
* Exec - use for long running tools where you need to stream live output as it runs
* @deprecated use `execAsync` instead
* @returns a promise with return code.
*/
public exec(options?: IExecOptions): Q.Promise<number> {
var defer = Q.defer<number>();

Expand Down Expand Up @@ -270,8 +376,6 @@ export class ToolRunner extends events.EventEmitter {
// but also has limits. For example, no live output and limited to max buffer
//
public execSync(options?: IExecSyncOptions): IExecSyncResult {
var defer = Q.defer();

this._debug('exec tool: ' + this.toolPath);
this._debug('Arguments:');
this.args.forEach((arg) => {
Expand Down
10 changes: 5 additions & 5 deletions node/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions node/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "azure-pipelines-task-lib",
"version": "4.4.0",
"version": "4.5.0",
"description": "Azure Pipelines Task SDK",
"main": "./task.js",
"typings": "./task.d.ts",
Expand Down Expand Up @@ -39,7 +39,7 @@
"@types/minimatch": "3.0.3",
"@types/mocha": "^9.1.1",
"@types/mockery": "^1.4.29",
"@types/node": "^16.11.39",
"@types/node": "^10.17.0",
"@types/q": "^1.5.4",
"@types/semver": "^7.3.4",
"@types/shelljs": "^0.8.8",
Expand Down
28 changes: 28 additions & 0 deletions node/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1447,6 +1447,34 @@ export function rmRF(inputPath: string): void {
* @param options optional exec options. See IExecOptions
* @returns number
*/
export function execAsync(tool: string, args: any, options?: trm.IExecOptions): Promise<number> {
let tr: trm.ToolRunner = this.tool(tool);
tr.on('debug', (data: string) => {
debug(data);
});

if (args) {
if (args instanceof Array) {
tr.arg(args);
}
else if (typeof (args) === 'string') {
tr.line(args)
}
}
return tr.execAsync(options);
}

/**
* Exec a tool. Convenience wrapper over ToolRunner to exec with args in one call.
* Output will be streamed to the live console.
* Returns promise with return code
*
* @deprecated Use the {@link execAsync} method that returns a native Javascript Promise instead
* @param tool path to tool to exec
* @param args an arg string or array of args
* @param options optional exec options. See IExecOptions
* @returns number
*/
export function exec(tool: string, args: any, options?: trm.IExecOptions): Q.Promise<number> {
let tr: trm.ToolRunner = this.tool(tool);
tr.on('debug', (data: string) => {
Expand Down
Loading