azure-pipelines-task-lib 5.279.0 → 5.280.1
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/externaloutput.d.ts +72 -0
- package/externaloutput.js +297 -0
- package/mock-task.d.ts +6 -0
- package/mock-task.js +15 -1
- package/mock-toolrunner.d.ts +5 -2
- package/mock-toolrunner.js +25 -11
- package/package.json +2 -2
- package/task.d.ts +40 -0
- package/task.js +45 -1
- package/toolrunner.d.ts +10 -0
- package/toolrunner.js +186 -104
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
/// <reference types="node" />
|
|
4
|
+
import stream = require('stream');
|
|
5
|
+
/** Commands allowed by default once VSO commands are enabled for a path. */
|
|
6
|
+
export declare const defaultAllowedVsoCommands: readonly string[];
|
|
7
|
+
/**
|
|
8
|
+
* Where the external output originates. Used for documentation and telemetry only; it does
|
|
9
|
+
* NOT select an automatic allowlist. A task must explicitly enable VSO commands when needed.
|
|
10
|
+
*/
|
|
11
|
+
export type ExternalOutputSource = 'remote' | 'childProcess' | 'repository';
|
|
12
|
+
export interface ExternalOutputOptions {
|
|
13
|
+
/** Origin of the output. Documentation/telemetry only. */
|
|
14
|
+
source: ExternalOutputSource;
|
|
15
|
+
/**
|
|
16
|
+
* When false or omitted, every "##vso[" marker is blocked. When true, markers whose
|
|
17
|
+
* command name is in the effective allowlist pass through unchanged.
|
|
18
|
+
*/
|
|
19
|
+
enableVsoCommands?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* The allowlist of "area.event" command names to permit when enableVsoCommands is true.
|
|
22
|
+
* Replaces (does not extend) the default list. An explicit empty array allows nothing.
|
|
23
|
+
* Has no effect when enableVsoCommands is false.
|
|
24
|
+
*/
|
|
25
|
+
allowedVsoCommands?: readonly string[];
|
|
26
|
+
/** Destination for filtered output. Defaults to process.stdout. */
|
|
27
|
+
destination?: NodeJS.WritableStream;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Stateful, byte-level marker filter. Feed bytes with push() and finish with flush().
|
|
31
|
+
* Retains only the minimal bytes needed to resolve a marker that straddles a chunk
|
|
32
|
+
* boundary, so memory stays bounded regardless of input size.
|
|
33
|
+
*/
|
|
34
|
+
export declare class MarkerFilter {
|
|
35
|
+
private readonly enabled;
|
|
36
|
+
private readonly allowed;
|
|
37
|
+
private pending;
|
|
38
|
+
constructor(enabled: boolean, allowed: Set<string>);
|
|
39
|
+
push(chunk: Buffer): Buffer;
|
|
40
|
+
flush(): Buffer;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A Transform stream that neutralizes VSO command markers in external output. Pipe untrusted
|
|
44
|
+
* output into it; it writes filtered bytes to its readable side (and, via
|
|
45
|
+
* createExternalOutputStream, on to the destination).
|
|
46
|
+
*/
|
|
47
|
+
export declare class ExternalOutputStream extends stream.Transform {
|
|
48
|
+
private readonly markerFilter;
|
|
49
|
+
constructor(options: ExternalOutputOptions);
|
|
50
|
+
_transform(chunk: any, _encoding: string, callback: (error?: Error | null) => void): void;
|
|
51
|
+
_flush(callback: (error?: Error | null) => void): void;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Creates a filtering stream for external output and pipes it to the destination
|
|
55
|
+
* (default process.stdout). Pipe untrusted output into the returned stream, e.g.
|
|
56
|
+
* `jenkinsResponse.pipe(tl.createExternalOutputStream({ source: 'remote' }))`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function createExternalOutputStream(options: ExternalOutputOptions): ExternalOutputStream;
|
|
59
|
+
/**
|
|
60
|
+
* Filters a complete piece of external output and writes it to the destination
|
|
61
|
+
* (default process.stdout). Each call is self-contained; for output that arrives in
|
|
62
|
+
* chunks that may split a marker, use createExternalOutputStream instead.
|
|
63
|
+
*/
|
|
64
|
+
export declare function writeExternalOutput(data: string | Buffer, options: ExternalOutputOptions): void;
|
|
65
|
+
/** Filters one complete value and returns its bytes without writing them. */
|
|
66
|
+
export declare function filterExternalOutput(data: string | Buffer, options: ExternalOutputOptions): Buffer;
|
|
67
|
+
export interface FilteredWriter {
|
|
68
|
+
write(data: string | Buffer): void;
|
|
69
|
+
end(): void;
|
|
70
|
+
}
|
|
71
|
+
/** Creates a stateful writer that filters markers split across writes. */
|
|
72
|
+
export declare function createFilteredWriter(options: ExternalOutputOptions, destination: NodeJS.WritableStream): FilteredWriter;
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft. All rights reserved.
|
|
3
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
4
|
+
var __extends = (this && this.__extends) || (function () {
|
|
5
|
+
var extendStatics = function (d, b) {
|
|
6
|
+
extendStatics = Object.setPrototypeOf ||
|
|
7
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
8
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
9
|
+
return extendStatics(d, b);
|
|
10
|
+
};
|
|
11
|
+
return function (d, b) {
|
|
12
|
+
if (typeof b !== "function" && b !== null)
|
|
13
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
14
|
+
extendStatics(d, b);
|
|
15
|
+
function __() { this.constructor = d; }
|
|
16
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
17
|
+
};
|
|
18
|
+
})();
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.createFilteredWriter = exports.filterExternalOutput = exports.writeExternalOutput = exports.createExternalOutputStream = exports.ExternalOutputStream = exports.MarkerFilter = exports.defaultAllowedVsoCommands = void 0;
|
|
21
|
+
var stream = require("stream");
|
|
22
|
+
//
|
|
23
|
+
// External output filtering.
|
|
24
|
+
//
|
|
25
|
+
// Azure Pipelines treats a task's stdout both as log text and as a command channel:
|
|
26
|
+
// a line containing the marker "##vso[area.event ...]data" is parsed and executed by the
|
|
27
|
+
// agent. When a task echoes output that originates from an untrusted source (a remote
|
|
28
|
+
// server, a child process, a repository filename, compiler/test output, ...), that source
|
|
29
|
+
// can smuggle a "##vso[" marker and make the agent run a command on its behalf.
|
|
30
|
+
//
|
|
31
|
+
// This module neutralizes markers in such external output before it reaches the agent's
|
|
32
|
+
// command parser. By default every marker is blocked (rewritten "##vso[" -> "##_vso[").
|
|
33
|
+
// A task may opt a compatibility-sensitive path into a small, explicit allowlist of
|
|
34
|
+
// command names; unknown, malformed, or future commands stay blocked.
|
|
35
|
+
//
|
|
36
|
+
// The filter works on raw bytes (Buffer) so it never corrupts invalid UTF-8, binary
|
|
37
|
+
// output, or multibyte characters split across chunk boundaries. It matches the marker
|
|
38
|
+
// byte-for-byte, mirroring the agent's Ordinal comparison, so the two agree exactly on
|
|
39
|
+
// what a marker is.
|
|
40
|
+
//
|
|
41
|
+
/** The exact marker bytes the agent recognizes as the start of a command: "##vso[". */
|
|
42
|
+
var MARKER = Buffer.from('##vso[', 'ascii');
|
|
43
|
+
/** Neutralized form written in place of a blocked marker: "##_vso[". */
|
|
44
|
+
var NEUTRALIZED = Buffer.from('##_vso[', 'ascii');
|
|
45
|
+
var EMPTY = Buffer.alloc(0);
|
|
46
|
+
var SPACE = 0x20;
|
|
47
|
+
var RBRACKET = 0x5D; // ]
|
|
48
|
+
var CR = 0x0D;
|
|
49
|
+
var LF = 0x0A;
|
|
50
|
+
// Maximum command-name bytes retained while waiting for a terminator.
|
|
51
|
+
var MAX_HEADER = 256;
|
|
52
|
+
/** Commands allowed by default once VSO commands are enabled for a path. */
|
|
53
|
+
exports.defaultAllowedVsoCommands = Object.freeze(['task.debug', 'task.setprogress']);
|
|
54
|
+
function resolveAllowed(options) {
|
|
55
|
+
if (!options.enableVsoCommands) {
|
|
56
|
+
return new Set();
|
|
57
|
+
}
|
|
58
|
+
var list = options.allowedVsoCommands !== undefined
|
|
59
|
+
? options.allowedVsoCommands
|
|
60
|
+
: exports.defaultAllowedVsoCommands;
|
|
61
|
+
// Command-name comparison is case-insensitive to match the agent's command lookup.
|
|
62
|
+
return new Set(list.map(function (c) { return c.toLowerCase(); }));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Normalizes a raw command-name token to the agent's canonical "area.event" form, or null
|
|
66
|
+
* when it is not a valid command name. Mirrors the agent's Split('.', RemoveEmptyEntries)
|
|
67
|
+
* with a required length of exactly two non-empty segments.
|
|
68
|
+
*/
|
|
69
|
+
function canonicalCommandName(raw) {
|
|
70
|
+
var parts = raw.split('.').filter(function (p) { return p.length > 0; });
|
|
71
|
+
if (parts.length !== 2) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
return (parts[0] + '.' + parts[1]).toLowerCase();
|
|
75
|
+
}
|
|
76
|
+
/** Returns the longest suffix of buf that is a proper marker prefix. */
|
|
77
|
+
function partialMarkerSuffixLength(buf) {
|
|
78
|
+
var max = Math.min(MARKER.length - 1, buf.length);
|
|
79
|
+
for (var k = max; k >= 1; k--) {
|
|
80
|
+
if (buf.compare(MARKER, 0, k, buf.length - k, buf.length) === 0) {
|
|
81
|
+
return k;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return 0;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Locates the end of a command-name header that starts at `start` (the byte after a marker).
|
|
88
|
+
* The name ends at the first space or ']'. A CR or LF is also reported as a terminator with
|
|
89
|
+
* newline=true so the caller can fail closed. Scans at most MAX_HEADER bytes; term is -1 when
|
|
90
|
+
* no terminator is found within that bound (or before the buffer ends).
|
|
91
|
+
*/
|
|
92
|
+
function scanHeader(buf, start) {
|
|
93
|
+
var limit = Math.min(buf.length, start + MAX_HEADER);
|
|
94
|
+
for (var k = start; k < limit; k++) {
|
|
95
|
+
var b = buf[k];
|
|
96
|
+
if (b === SPACE || b === RBRACKET) {
|
|
97
|
+
return { term: k, newline: false };
|
|
98
|
+
}
|
|
99
|
+
if (b === CR || b === LF) {
|
|
100
|
+
return { term: k, newline: true };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return { term: -1, newline: false };
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Stateful, byte-level marker filter. Feed bytes with push() and finish with flush().
|
|
107
|
+
* Retains only the minimal bytes needed to resolve a marker that straddles a chunk
|
|
108
|
+
* boundary, so memory stays bounded regardless of input size.
|
|
109
|
+
*/
|
|
110
|
+
var MarkerFilter = /** @class */ (function () {
|
|
111
|
+
function MarkerFilter(enabled, allowed) {
|
|
112
|
+
this.enabled = enabled;
|
|
113
|
+
this.allowed = allowed;
|
|
114
|
+
this.pending = EMPTY;
|
|
115
|
+
}
|
|
116
|
+
MarkerFilter.prototype.push = function (chunk) {
|
|
117
|
+
var buf = this.pending.length ? Buffer.concat([this.pending, chunk]) : chunk;
|
|
118
|
+
this.pending = EMPTY;
|
|
119
|
+
var out = [];
|
|
120
|
+
var pos = 0;
|
|
121
|
+
while (pos < buf.length) {
|
|
122
|
+
var idx = buf.indexOf(MARKER, pos);
|
|
123
|
+
if (idx === -1) {
|
|
124
|
+
// No complete marker remains. Retain a possible partial marker at the tail so
|
|
125
|
+
// it can be completed by the next chunk; emit everything before it.
|
|
126
|
+
var keep = Math.min(partialMarkerSuffixLength(buf), buf.length - pos);
|
|
127
|
+
var emitEnd = buf.length - keep;
|
|
128
|
+
if (emitEnd > pos) {
|
|
129
|
+
out.push(pos === 0 && emitEnd === buf.length ? buf : buf.subarray(pos, emitEnd));
|
|
130
|
+
}
|
|
131
|
+
this.pending = keep ? buf.subarray(buf.length - keep) : EMPTY;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
if (idx > pos) {
|
|
135
|
+
out.push(buf.subarray(pos, idx));
|
|
136
|
+
}
|
|
137
|
+
var afterMarker = idx + MARKER.length;
|
|
138
|
+
if (!this.enabled) {
|
|
139
|
+
out.push(NEUTRALIZED);
|
|
140
|
+
pos = afterMarker;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
// Enabled: read the command name (up to the first space or ']') and allow the marker
|
|
144
|
+
// only when that name is allowlisted.
|
|
145
|
+
var _a = scanHeader(buf, afterMarker), term = _a.term, newline = _a.newline;
|
|
146
|
+
if (term === -1) {
|
|
147
|
+
if (buf.length - afterMarker >= MAX_HEADER) {
|
|
148
|
+
// No terminator within the bound: fail closed.
|
|
149
|
+
out.push(NEUTRALIZED);
|
|
150
|
+
pos = afterMarker;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
// Header may complete in a later chunk; retain from the marker start.
|
|
154
|
+
this.pending = buf.subarray(idx);
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
// A CR/LF before the terminator means the agent (which parses per line) would never
|
|
158
|
+
// treat this as a command, so we fail closed and neutralize.
|
|
159
|
+
if (newline) {
|
|
160
|
+
out.push(NEUTRALIZED);
|
|
161
|
+
pos = afterMarker;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
var name_1 = canonicalCommandName(buf.toString('utf8', afterMarker, term));
|
|
165
|
+
// Allowlisted markers pass unchanged; the header/data after them flow through as
|
|
166
|
+
// ordinary bytes and any later markers are evaluated independently.
|
|
167
|
+
out.push(name_1 && this.allowed.has(name_1) ? MARKER : NEUTRALIZED);
|
|
168
|
+
pos = afterMarker;
|
|
169
|
+
}
|
|
170
|
+
if (out.length === 0) {
|
|
171
|
+
return EMPTY;
|
|
172
|
+
}
|
|
173
|
+
if (out.length === 1) {
|
|
174
|
+
var only = out[0];
|
|
175
|
+
// Never expose module-level buffers that callers could mutate globally.
|
|
176
|
+
return only === NEUTRALIZED || only === MARKER ? Buffer.from(only) : only;
|
|
177
|
+
}
|
|
178
|
+
return Buffer.concat(out);
|
|
179
|
+
};
|
|
180
|
+
MarkerFilter.prototype.flush = function () {
|
|
181
|
+
var p = this.pending;
|
|
182
|
+
this.pending = EMPTY;
|
|
183
|
+
if (p.length === 0) {
|
|
184
|
+
return EMPTY;
|
|
185
|
+
}
|
|
186
|
+
// An incomplete command candidate that begins with the full marker is neutralized.
|
|
187
|
+
if (this.enabled && p.length >= MARKER.length && p.subarray(0, MARKER.length).equals(MARKER)) {
|
|
188
|
+
return Buffer.concat([NEUTRALIZED, p.subarray(MARKER.length)]);
|
|
189
|
+
}
|
|
190
|
+
// A partial marker (fewer than the full bytes) cannot be executed by the agent, so it
|
|
191
|
+
// is safe to emit unchanged.
|
|
192
|
+
return p;
|
|
193
|
+
};
|
|
194
|
+
return MarkerFilter;
|
|
195
|
+
}());
|
|
196
|
+
exports.MarkerFilter = MarkerFilter;
|
|
197
|
+
/**
|
|
198
|
+
* A Transform stream that neutralizes VSO command markers in external output. Pipe untrusted
|
|
199
|
+
* output into it; it writes filtered bytes to its readable side (and, via
|
|
200
|
+
* createExternalOutputStream, on to the destination).
|
|
201
|
+
*/
|
|
202
|
+
var ExternalOutputStream = /** @class */ (function (_super) {
|
|
203
|
+
__extends(ExternalOutputStream, _super);
|
|
204
|
+
function ExternalOutputStream(options) {
|
|
205
|
+
var _this = _super.call(this) || this;
|
|
206
|
+
_this.markerFilter = new MarkerFilter(!!options.enableVsoCommands, resolveAllowed(options));
|
|
207
|
+
return _this;
|
|
208
|
+
}
|
|
209
|
+
ExternalOutputStream.prototype._transform = function (chunk, _encoding, callback) {
|
|
210
|
+
try {
|
|
211
|
+
var buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk), 'utf8');
|
|
212
|
+
var out = this.markerFilter.push(buf);
|
|
213
|
+
if (out.length) {
|
|
214
|
+
this.push(out);
|
|
215
|
+
}
|
|
216
|
+
callback();
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
// Fail closed: never recover by emitting the original marker.
|
|
220
|
+
callback(err);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
ExternalOutputStream.prototype._flush = function (callback) {
|
|
224
|
+
try {
|
|
225
|
+
var out = this.markerFilter.flush();
|
|
226
|
+
if (out.length) {
|
|
227
|
+
this.push(out);
|
|
228
|
+
}
|
|
229
|
+
callback();
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
callback(err);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
return ExternalOutputStream;
|
|
236
|
+
}(stream.Transform));
|
|
237
|
+
exports.ExternalOutputStream = ExternalOutputStream;
|
|
238
|
+
/**
|
|
239
|
+
* Creates a filtering stream for external output and pipes it to the destination
|
|
240
|
+
* (default process.stdout). Pipe untrusted output into the returned stream, e.g.
|
|
241
|
+
* `jenkinsResponse.pipe(tl.createExternalOutputStream({ source: 'remote' }))`.
|
|
242
|
+
*/
|
|
243
|
+
function createExternalOutputStream(options) {
|
|
244
|
+
var filterStream = new ExternalOutputStream(options);
|
|
245
|
+
var destination = options.destination || process.stdout;
|
|
246
|
+
// Do not end the shared destination (e.g. process.stdout) when the source ends.
|
|
247
|
+
filterStream.pipe(destination, { end: false });
|
|
248
|
+
return filterStream;
|
|
249
|
+
}
|
|
250
|
+
exports.createExternalOutputStream = createExternalOutputStream;
|
|
251
|
+
/**
|
|
252
|
+
* Filters a complete piece of external output and writes it to the destination
|
|
253
|
+
* (default process.stdout). Each call is self-contained; for output that arrives in
|
|
254
|
+
* chunks that may split a marker, use createExternalOutputStream instead.
|
|
255
|
+
*/
|
|
256
|
+
function writeExternalOutput(data, options) {
|
|
257
|
+
var destination = options.destination || process.stdout;
|
|
258
|
+
destination.write(filterExternalOutput(data, options));
|
|
259
|
+
}
|
|
260
|
+
exports.writeExternalOutput = writeExternalOutput;
|
|
261
|
+
/** Filters one complete value and returns its bytes without writing them. */
|
|
262
|
+
function filterExternalOutput(data, options) {
|
|
263
|
+
var filter = new MarkerFilter(!!options.enableVsoCommands, resolveAllowed(options));
|
|
264
|
+
var buf = Buffer.isBuffer(data) ? data : Buffer.from(String(data), 'utf8');
|
|
265
|
+
var filtered = filter.push(buf);
|
|
266
|
+
var pending = filter.flush();
|
|
267
|
+
return pending.length ? Buffer.concat([filtered, pending]) : filtered;
|
|
268
|
+
}
|
|
269
|
+
exports.filterExternalOutput = filterExternalOutput;
|
|
270
|
+
/** Creates a stateful writer that filters markers split across writes. */
|
|
271
|
+
function createFilteredWriter(options, destination) {
|
|
272
|
+
var filter = new MarkerFilter(!!options.enableVsoCommands, resolveAllowed(options));
|
|
273
|
+
var ended = false;
|
|
274
|
+
return {
|
|
275
|
+
write: function (data) {
|
|
276
|
+
if (ended) {
|
|
277
|
+
throw new Error('Cannot write after end');
|
|
278
|
+
}
|
|
279
|
+
var buf = Buffer.isBuffer(data) ? data : Buffer.from(String(data), 'utf8');
|
|
280
|
+
var filtered = filter.push(buf);
|
|
281
|
+
if (filtered.length) {
|
|
282
|
+
destination.write(filtered);
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
end: function () {
|
|
286
|
+
if (ended) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
ended = true;
|
|
290
|
+
var pending = filter.flush();
|
|
291
|
+
if (pending.length) {
|
|
292
|
+
destination.write(pending);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
exports.createFilteredWriter = createFilteredWriter;
|
package/mock-task.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import Q = require('q');
|
|
|
4
4
|
import fs = require('fs');
|
|
5
5
|
import task = require('./task');
|
|
6
6
|
import trm = require('./mock-toolrunner');
|
|
7
|
+
import eom = require('./externaloutput');
|
|
7
8
|
import ma = require('./mock-answer');
|
|
8
9
|
export declare function setAnswers(answers: ma.TaskLibAnswers): void;
|
|
9
10
|
export declare function setResourcePath(path: string): void;
|
|
@@ -111,5 +112,10 @@ export declare class CodeCoverageEnabler {
|
|
|
111
112
|
[key: string]: string;
|
|
112
113
|
}): void;
|
|
113
114
|
}
|
|
115
|
+
export type ExternalOutputOptions = eom.ExternalOutputOptions;
|
|
116
|
+
export declare function createExternalOutputStream(options: eom.ExternalOutputOptions): eom.ExternalOutputStream;
|
|
117
|
+
export declare function writeExternalOutput(data: string | Buffer, options: eom.ExternalOutputOptions): void;
|
|
118
|
+
export declare function filterExternalOutput(data: string | Buffer, options: eom.ExternalOutputOptions): Buffer;
|
|
119
|
+
export declare const defaultAllowedVsoCommands: readonly string[];
|
|
114
120
|
export declare function getHttpProxyConfiguration(requestUrl?: string): task.ProxyConfiguration | null;
|
|
115
121
|
export declare function getHttpCertConfiguration(): task.CertConfiguration | null;
|
package/mock-task.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
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.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.getNodeMajorVersion = 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.defaultAllowedVsoCommands = exports.filterExternalOutput = exports.writeExternalOutput = exports.createExternalOutputStream = 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.getNodeMajorVersion = 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");
|
|
7
7
|
var trm = require("./mock-toolrunner");
|
|
8
|
+
var eom = require("./externaloutput");
|
|
8
9
|
var ma = require("./mock-answer");
|
|
9
10
|
var mock = new ma.MockAnswers();
|
|
10
11
|
function setAnswers(answers) {
|
|
@@ -455,6 +456,19 @@ exports.updateReleaseName = task.updateReleaseName;
|
|
|
455
456
|
exports.TaskCommand = tcm.TaskCommand;
|
|
456
457
|
exports.commandFromString = tcm.commandFromString;
|
|
457
458
|
exports.ToolRunner = trm.ToolRunner;
|
|
459
|
+
function createExternalOutputStream(options) {
|
|
460
|
+
return eom.createExternalOutputStream(options);
|
|
461
|
+
}
|
|
462
|
+
exports.createExternalOutputStream = createExternalOutputStream;
|
|
463
|
+
function writeExternalOutput(data, options) {
|
|
464
|
+
eom.writeExternalOutput(data, options);
|
|
465
|
+
}
|
|
466
|
+
exports.writeExternalOutput = writeExternalOutput;
|
|
467
|
+
function filterExternalOutput(data, options) {
|
|
468
|
+
return eom.filterExternalOutput(data, options);
|
|
469
|
+
}
|
|
470
|
+
exports.filterExternalOutput = filterExternalOutput;
|
|
471
|
+
exports.defaultAllowedVsoCommands = eom.defaultAllowedVsoCommands;
|
|
458
472
|
//-----------------------------------------------------
|
|
459
473
|
// Http Proxy Helper
|
|
460
474
|
//-----------------------------------------------------
|
package/mock-toolrunner.d.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import Q = require('q');
|
|
4
4
|
import events = require('events');
|
|
5
5
|
import ma = require('./mock-answer');
|
|
6
|
+
import eom = require('./externaloutput');
|
|
6
7
|
export declare function setAnswers(answers: ma.TaskLibAnswers): void;
|
|
7
8
|
export interface IExecOptions extends IExecSyncOptions {
|
|
8
9
|
failOnStdErr?: boolean;
|
|
@@ -14,9 +15,11 @@ export interface IExecSyncOptions {
|
|
|
14
15
|
[key: string]: string | undefined;
|
|
15
16
|
};
|
|
16
17
|
silent?: boolean;
|
|
17
|
-
outStream
|
|
18
|
-
errStream
|
|
18
|
+
outStream?: NodeJS.WritableStream;
|
|
19
|
+
errStream?: NodeJS.WritableStream;
|
|
19
20
|
windowsVerbatimArguments?: boolean;
|
|
21
|
+
shell?: boolean;
|
|
22
|
+
externalOutput?: eom.ExternalOutputOptions;
|
|
20
23
|
}
|
|
21
24
|
export interface IExecSyncResult {
|
|
22
25
|
stdout: string;
|
package/mock-toolrunner.js
CHANGED
|
@@ -20,6 +20,7 @@ var Q = require("q");
|
|
|
20
20
|
var os = require("os");
|
|
21
21
|
var events = require("events");
|
|
22
22
|
var ma = require("./mock-answer");
|
|
23
|
+
var eom = require("./externaloutput");
|
|
23
24
|
var mock = new ma.MockAnswers();
|
|
24
25
|
function setAnswers(answers) {
|
|
25
26
|
mock.initialize(answers);
|
|
@@ -149,7 +150,9 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
149
150
|
errStream: options.errStream || process.stderr,
|
|
150
151
|
failOnStdErr: options.failOnStdErr || false,
|
|
151
152
|
ignoreReturnCode: options.ignoreReturnCode || false,
|
|
152
|
-
windowsVerbatimArguments: options.windowsVerbatimArguments
|
|
153
|
+
windowsVerbatimArguments: options.windowsVerbatimArguments,
|
|
154
|
+
shell: options.shell,
|
|
155
|
+
externalOutput: options.externalOutput
|
|
153
156
|
};
|
|
154
157
|
var argString = this.args.join(' ') || '';
|
|
155
158
|
var cmdString = this.toolPath;
|
|
@@ -167,14 +170,16 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
167
170
|
}
|
|
168
171
|
cmdString += ' | ' + pipeToolCmdString;
|
|
169
172
|
}
|
|
170
|
-
|
|
173
|
+
var commandLine = '[command]' + cmdString + os.EOL;
|
|
174
|
+
ops.outStream.write(ops.externalOutput ? eom.filterExternalOutput(commandLine, ops.externalOutput) : commandLine);
|
|
171
175
|
}
|
|
172
176
|
// TODO: filter process.env
|
|
173
177
|
var res = mock.getResponse('exec', cmdString, debug);
|
|
174
178
|
if (res.stdout) {
|
|
175
179
|
this.emit('stdout', res.stdout);
|
|
176
180
|
if (!ops.silent) {
|
|
177
|
-
|
|
181
|
+
var stdout = res.stdout + os.EOL;
|
|
182
|
+
ops.outStream.write(ops.externalOutput ? eom.filterExternalOutput(stdout, ops.externalOutput) : stdout);
|
|
178
183
|
}
|
|
179
184
|
var stdLineArray = res.stdout.split(os.EOL);
|
|
180
185
|
for (var _i = 0, _a = stdLineArray.slice(0, -1); _i < _a.length; _i++) {
|
|
@@ -190,7 +195,8 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
190
195
|
success = !ops.failOnStdErr;
|
|
191
196
|
if (!ops.silent) {
|
|
192
197
|
var s = ops.failOnStdErr ? ops.errStream : ops.outStream;
|
|
193
|
-
|
|
198
|
+
var stderr = res.stderr + os.EOL;
|
|
199
|
+
s.write(ops.externalOutput ? eom.filterExternalOutput(stderr, ops.externalOutput) : stderr);
|
|
194
200
|
}
|
|
195
201
|
var stdErrArray = res.stderr.split(os.EOL);
|
|
196
202
|
for (var _b = 0, _c = stdErrArray.slice(0, -1); _b < _c.length; _b++) {
|
|
@@ -243,7 +249,9 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
243
249
|
errStream: options.errStream || process.stderr,
|
|
244
250
|
failOnStdErr: options.failOnStdErr || false,
|
|
245
251
|
ignoreReturnCode: options.ignoreReturnCode || false,
|
|
246
|
-
windowsVerbatimArguments: options.windowsVerbatimArguments
|
|
252
|
+
windowsVerbatimArguments: options.windowsVerbatimArguments,
|
|
253
|
+
shell: options.shell,
|
|
254
|
+
externalOutput: options.externalOutput
|
|
247
255
|
};
|
|
248
256
|
var argString = this.args.join(' ') || '';
|
|
249
257
|
var cmdString = this.toolPath;
|
|
@@ -261,14 +269,16 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
261
269
|
}
|
|
262
270
|
cmdString += ' | ' + pipeToolCmdString;
|
|
263
271
|
}
|
|
264
|
-
|
|
272
|
+
var commandLine = '[command]' + cmdString + os.EOL;
|
|
273
|
+
ops.outStream.write(ops.externalOutput ? eom.filterExternalOutput(commandLine, ops.externalOutput) : commandLine);
|
|
265
274
|
}
|
|
266
275
|
// TODO: filter process.env
|
|
267
276
|
var res = mock.getResponse('exec', cmdString, debug);
|
|
268
277
|
if (res.stdout) {
|
|
269
278
|
this.emit('stdout', res.stdout);
|
|
270
279
|
if (!ops.silent) {
|
|
271
|
-
|
|
280
|
+
var stdout = res.stdout + os.EOL;
|
|
281
|
+
ops.outStream.write(ops.externalOutput ? eom.filterExternalOutput(stdout, ops.externalOutput) : stdout);
|
|
272
282
|
}
|
|
273
283
|
var stdLineArray = res.stdout.split(os.EOL);
|
|
274
284
|
for (var _i = 0, _a = stdLineArray.slice(0, -1); _i < _a.length; _i++) {
|
|
@@ -284,7 +294,8 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
284
294
|
success = !ops.failOnStdErr;
|
|
285
295
|
if (!ops.silent) {
|
|
286
296
|
var s = ops.failOnStdErr ? ops.errStream : ops.outStream;
|
|
287
|
-
|
|
297
|
+
var stderr = res.stderr + os.EOL;
|
|
298
|
+
s.write(ops.externalOutput ? eom.filterExternalOutput(stderr, ops.externalOutput) : stderr);
|
|
288
299
|
}
|
|
289
300
|
var stdErrArray = res.stderr.split(os.EOL);
|
|
290
301
|
for (var _b = 0, _c = stdErrArray.slice(0, -1); _b < _c.length; _b++) {
|
|
@@ -333,6 +344,8 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
333
344
|
outStream: options.outStream || process.stdout,
|
|
334
345
|
errStream: options.errStream || process.stderr,
|
|
335
346
|
windowsVerbatimArguments: options.windowsVerbatimArguments,
|
|
347
|
+
shell: options.shell,
|
|
348
|
+
externalOutput: options.externalOutput
|
|
336
349
|
};
|
|
337
350
|
var argString = this.args.join(' ') || '';
|
|
338
351
|
var cmdString = this.toolPath;
|
|
@@ -342,14 +355,15 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
342
355
|
cmdString += (' ' + argString);
|
|
343
356
|
}
|
|
344
357
|
if (!ops.silent) {
|
|
345
|
-
|
|
358
|
+
var commandLine = '[command]' + cmdString + os.EOL;
|
|
359
|
+
ops.outStream.write(ops.externalOutput ? eom.filterExternalOutput(commandLine, ops.externalOutput) : commandLine);
|
|
346
360
|
}
|
|
347
361
|
var r = mock.getResponse('exec', cmdString, debug);
|
|
348
362
|
if (!ops.silent && r.stdout && r.stdout.length > 0) {
|
|
349
|
-
ops.outStream.write(r.stdout);
|
|
363
|
+
ops.outStream.write(ops.externalOutput ? eom.filterExternalOutput(r.stdout, ops.externalOutput) : r.stdout);
|
|
350
364
|
}
|
|
351
365
|
if (!ops.silent && r.stderr && r.stderr.length > 0) {
|
|
352
|
-
ops.errStream.write(r.stderr);
|
|
366
|
+
ops.errStream.write(ops.externalOutput ? eom.filterExternalOutput(r.stderr, ops.externalOutput) : r.stderr);
|
|
353
367
|
}
|
|
354
368
|
return {
|
|
355
369
|
code: r.code,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "azure-pipelines-task-lib",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.280.1",
|
|
4
4
|
"description": "Azure Pipelines Task SDK",
|
|
5
5
|
"main": "./task.js",
|
|
6
6
|
"typings": "./task.d.ts",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"overrides": {
|
|
48
48
|
"brace-expansion@1.x": { ".": "1.1.18" },
|
|
49
49
|
"brace-expansion@2.x": { ".": "2.1.4" },
|
|
50
|
-
"js-yaml": "4.3.
|
|
50
|
+
"js-yaml": "^4.3.2",
|
|
51
51
|
"serialize-javascript": "7.0.5"
|
|
52
52
|
}
|
|
53
53
|
}
|
package/task.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import Q = require('q');
|
|
|
4
4
|
import fs = require('fs');
|
|
5
5
|
import im = require('./internal');
|
|
6
6
|
import trm = require('./toolrunner');
|
|
7
|
+
import eom = require('./externaloutput');
|
|
7
8
|
type OptionCases<T extends string> = `-${Uppercase<T> | Lowercase<T>}`;
|
|
8
9
|
type OptionsPermutations<T extends string, U extends string = ''> = T extends `${infer First}${infer Rest}` ? OptionCases<`${U}${First}`> | OptionCases<`${First}${U}`> | OptionsPermutations<Rest, `${U}${First}`> | OptionCases<First> : OptionCases<U> | '';
|
|
9
10
|
export declare enum TaskResult {
|
|
@@ -833,4 +834,43 @@ export declare function addBuildTag(value: string): void;
|
|
|
833
834
|
* @returns void
|
|
834
835
|
*/
|
|
835
836
|
export declare function updateReleaseName(name: string): void;
|
|
837
|
+
/**
|
|
838
|
+
* Options controlling how external (untrusted) output is filtered before it is written to
|
|
839
|
+
* the log. See {@link eom.ExternalOutputOptions}.
|
|
840
|
+
*/
|
|
841
|
+
export type ExternalOutputOptions = eom.ExternalOutputOptions;
|
|
842
|
+
/**
|
|
843
|
+
* Creates a filtering stream for external output and pipes it to the destination
|
|
844
|
+
* (default process.stdout). Pipe untrusted output (a remote response, a child process's
|
|
845
|
+
* stdout, etc.) into the returned stream so that any "##vso[" command markers it contains
|
|
846
|
+
* are neutralized instead of executed by the agent.
|
|
847
|
+
*
|
|
848
|
+
* By default every marker is blocked. Set enableVsoCommands to true (optionally with an
|
|
849
|
+
* explicit allowedVsoCommands list) to permit a small set of command names on a
|
|
850
|
+
* compatibility-sensitive path.
|
|
851
|
+
*
|
|
852
|
+
* @param options External output options. See ExternalOutputOptions.
|
|
853
|
+
* @returns A writable/readable stream to pipe untrusted output into.
|
|
854
|
+
*/
|
|
855
|
+
export declare function createExternalOutputStream(options: eom.ExternalOutputOptions): eom.ExternalOutputStream;
|
|
856
|
+
/**
|
|
857
|
+
* Filters a complete piece of external output and writes it to the destination
|
|
858
|
+
* (default process.stdout). Use this for output already held in a string or Buffer; for
|
|
859
|
+
* output that streams in chunks that may split a marker, use createExternalOutputStream.
|
|
860
|
+
*
|
|
861
|
+
* @param data The external output to write.
|
|
862
|
+
* @param options External output options. See ExternalOutputOptions.
|
|
863
|
+
* @returns void
|
|
864
|
+
*/
|
|
865
|
+
export declare function writeExternalOutput(data: string | Buffer, options: eom.ExternalOutputOptions): void;
|
|
866
|
+
/**
|
|
867
|
+
* Filters a complete piece of external output and returns its bytes without writing them.
|
|
868
|
+
*
|
|
869
|
+
* @param data The external output to filter.
|
|
870
|
+
* @param options External output options. See ExternalOutputOptions.
|
|
871
|
+
* @returns The filtered output.
|
|
872
|
+
*/
|
|
873
|
+
export declare function filterExternalOutput(data: string | Buffer, options: eom.ExternalOutputOptions): Buffer;
|
|
874
|
+
/** Commands allowed when VSO commands are enabled without an explicit allowlist. */
|
|
875
|
+
export declare const defaultAllowedVsoCommands: readonly string[];
|
|
836
876
|
export {};
|
package/task.js
CHANGED
|
@@ -10,7 +10,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
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.getPipelineFeature = exports.getBoolFeatureFlag = exports.getBoolInput = exports.getInputRequired = exports.getInput = exports.setSecret = exports.setVariable = exports.getVariables = exports.assertAgent = exports.getVariable = exports.loc = exports.setResourcePath = exports.setSanitizedResult = exports.setResult = exports.setErrStream = exports.setStdStream = exports.AgentHostedMode = exports.Platform = exports.IssueSource = exports.FieldType = exports.ArtifactType = exports.IssueType = exports.TaskState = exports.TaskResult = void 0;
|
|
13
|
-
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.getSprint = exports.getAgentMode = exports.getNodeMajorVersion = void 0;
|
|
13
|
+
exports.defaultAllowedVsoCommands = exports.filterExternalOutput = exports.writeExternalOutput = exports.createExternalOutputStream = 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.getSprint = exports.getAgentMode = exports.getNodeMajorVersion = void 0;
|
|
14
14
|
var childProcess = require("child_process");
|
|
15
15
|
var fs = require("fs");
|
|
16
16
|
var path = require("path");
|
|
@@ -19,6 +19,7 @@ var minimatch = require("minimatch");
|
|
|
19
19
|
var im = require("./internal");
|
|
20
20
|
var tcm = require("./taskcommand");
|
|
21
21
|
var trm = require("./toolrunner");
|
|
22
|
+
var eom = require("./externaloutput");
|
|
22
23
|
var semver = require("semver");
|
|
23
24
|
var TaskResult;
|
|
24
25
|
(function (TaskResult) {
|
|
@@ -2414,6 +2415,49 @@ exports.updateReleaseName = updateReleaseName;
|
|
|
2414
2415
|
exports.TaskCommand = tcm.TaskCommand;
|
|
2415
2416
|
exports.commandFromString = tcm.commandFromString;
|
|
2416
2417
|
exports.ToolRunner = trm.ToolRunner;
|
|
2418
|
+
/**
|
|
2419
|
+
* Creates a filtering stream for external output and pipes it to the destination
|
|
2420
|
+
* (default process.stdout). Pipe untrusted output (a remote response, a child process's
|
|
2421
|
+
* stdout, etc.) into the returned stream so that any "##vso[" command markers it contains
|
|
2422
|
+
* are neutralized instead of executed by the agent.
|
|
2423
|
+
*
|
|
2424
|
+
* By default every marker is blocked. Set enableVsoCommands to true (optionally with an
|
|
2425
|
+
* explicit allowedVsoCommands list) to permit a small set of command names on a
|
|
2426
|
+
* compatibility-sensitive path.
|
|
2427
|
+
*
|
|
2428
|
+
* @param options External output options. See ExternalOutputOptions.
|
|
2429
|
+
* @returns A writable/readable stream to pipe untrusted output into.
|
|
2430
|
+
*/
|
|
2431
|
+
function createExternalOutputStream(options) {
|
|
2432
|
+
return eom.createExternalOutputStream(options);
|
|
2433
|
+
}
|
|
2434
|
+
exports.createExternalOutputStream = createExternalOutputStream;
|
|
2435
|
+
/**
|
|
2436
|
+
* Filters a complete piece of external output and writes it to the destination
|
|
2437
|
+
* (default process.stdout). Use this for output already held in a string or Buffer; for
|
|
2438
|
+
* output that streams in chunks that may split a marker, use createExternalOutputStream.
|
|
2439
|
+
*
|
|
2440
|
+
* @param data The external output to write.
|
|
2441
|
+
* @param options External output options. See ExternalOutputOptions.
|
|
2442
|
+
* @returns void
|
|
2443
|
+
*/
|
|
2444
|
+
function writeExternalOutput(data, options) {
|
|
2445
|
+
eom.writeExternalOutput(data, options);
|
|
2446
|
+
}
|
|
2447
|
+
exports.writeExternalOutput = writeExternalOutput;
|
|
2448
|
+
/**
|
|
2449
|
+
* Filters a complete piece of external output and returns its bytes without writing them.
|
|
2450
|
+
*
|
|
2451
|
+
* @param data The external output to filter.
|
|
2452
|
+
* @param options External output options. See ExternalOutputOptions.
|
|
2453
|
+
* @returns The filtered output.
|
|
2454
|
+
*/
|
|
2455
|
+
function filterExternalOutput(data, options) {
|
|
2456
|
+
return eom.filterExternalOutput(data, options);
|
|
2457
|
+
}
|
|
2458
|
+
exports.filterExternalOutput = filterExternalOutput;
|
|
2459
|
+
/** Commands allowed when VSO commands are enabled without an explicit allowlist. */
|
|
2460
|
+
exports.defaultAllowedVsoCommands = eom.defaultAllowedVsoCommands;
|
|
2417
2461
|
//-----------------------------------------------------
|
|
2418
2462
|
// Validation Checks
|
|
2419
2463
|
//-----------------------------------------------------
|
package/toolrunner.d.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
/// <reference types="node" />
|
|
4
4
|
import Q = require('q');
|
|
5
5
|
import events = require('events');
|
|
6
|
+
import eom = require('./externaloutput');
|
|
6
7
|
/**
|
|
7
8
|
* Interface for exec options
|
|
8
9
|
*/
|
|
@@ -32,6 +33,13 @@ export interface IExecSyncOptions {
|
|
|
32
33
|
windowsVerbatimArguments?: boolean;
|
|
33
34
|
/** optional. Run command inside of the shell. Defaults to false. */
|
|
34
35
|
shell?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Optional. When set, the tool's *displayed* output (the command line, stdout and stderr
|
|
38
|
+
* copies written to the log) is passed through the external-output marker filter so that
|
|
39
|
+
* "##vso[" commands emitted by the child process are neutralized. Raw stdout/stderr/stdline/
|
|
40
|
+
* errline events and bytes piped to another tool are NOT affected. See ExternalOutputOptions.
|
|
41
|
+
*/
|
|
42
|
+
externalOutput?: eom.ExternalOutputOptions;
|
|
35
43
|
}
|
|
36
44
|
/**
|
|
37
45
|
* Interface for exec results returned from synchronous exec functions
|
|
@@ -94,6 +102,8 @@ export declare class ToolRunner extends events.EventEmitter {
|
|
|
94
102
|
private _windowsQuoteCmdArg;
|
|
95
103
|
private _uv_quote_cmd_arg;
|
|
96
104
|
private _cloneExecOptions;
|
|
105
|
+
/** Builds one filtered writer per display destination. */
|
|
106
|
+
private _createDisplayFilter;
|
|
97
107
|
private _getSpawnOptions;
|
|
98
108
|
private _getSpawnSyncOptions;
|
|
99
109
|
private execWithPipingAsync;
|
package/toolrunner.js
CHANGED
|
@@ -22,6 +22,7 @@ var events = require("events");
|
|
|
22
22
|
var child = require("child_process");
|
|
23
23
|
var im = require("./internal");
|
|
24
24
|
var fs = require("fs");
|
|
25
|
+
var eom = require("./externaloutput");
|
|
25
26
|
var ToolRunner = /** @class */ (function (_super) {
|
|
26
27
|
__extends(ToolRunner, _super);
|
|
27
28
|
function ToolRunner(toolPath) {
|
|
@@ -494,12 +495,37 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
494
495
|
failOnStdErr: options.failOnStdErr || false,
|
|
495
496
|
ignoreReturnCode: options.ignoreReturnCode || false,
|
|
496
497
|
windowsVerbatimArguments: options.windowsVerbatimArguments || false,
|
|
497
|
-
shell: options.shell || false
|
|
498
|
+
shell: options.shell || false,
|
|
499
|
+
externalOutput: options.externalOutput
|
|
498
500
|
};
|
|
499
501
|
result.outStream = options.outStream || process.stdout;
|
|
500
502
|
result.errStream = options.errStream || process.stderr;
|
|
501
503
|
return result;
|
|
502
504
|
};
|
|
505
|
+
/** Builds one filtered writer per display destination. */
|
|
506
|
+
ToolRunner.prototype._createDisplayFilter = function (options) {
|
|
507
|
+
var ext = options.externalOutput;
|
|
508
|
+
if (!ext) {
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
511
|
+
var outStream = options.outStream;
|
|
512
|
+
var errDest = options.failOnStdErr ? options.errStream : options.outStream;
|
|
513
|
+
var stdoutWriter = eom.createFilteredWriter(ext, outStream);
|
|
514
|
+
var stderrWriter = errDest === outStream
|
|
515
|
+
? stdoutWriter
|
|
516
|
+
: eom.createFilteredWriter(ext, errDest);
|
|
517
|
+
return {
|
|
518
|
+
commandLine: function (text) { outStream.write(eom.filterExternalOutput(text, ext)); },
|
|
519
|
+
stdout: function (data) { return stdoutWriter.write(data); },
|
|
520
|
+
stderr: function (data) { return stderrWriter.write(data); },
|
|
521
|
+
finalize: function () {
|
|
522
|
+
stdoutWriter.end();
|
|
523
|
+
if (stderrWriter !== stdoutWriter) {
|
|
524
|
+
stderrWriter.end();
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
};
|
|
503
529
|
ToolRunner.prototype._getSpawnOptions = function (options) {
|
|
504
530
|
options = options || {};
|
|
505
531
|
var result = {};
|
|
@@ -527,8 +553,14 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
527
553
|
});
|
|
528
554
|
var success = true;
|
|
529
555
|
var optionsNonNull = this._cloneExecOptions(options);
|
|
556
|
+
var df = this._createDisplayFilter(optionsNonNull);
|
|
530
557
|
if (!optionsNonNull.silent) {
|
|
531
|
-
|
|
558
|
+
if (df) {
|
|
559
|
+
df.commandLine(this._getCommandString(optionsNonNull) + os.EOL);
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);
|
|
563
|
+
}
|
|
532
564
|
}
|
|
533
565
|
var cp;
|
|
534
566
|
var toolPath = pipeOutputToTool.toolPath;
|
|
@@ -550,32 +582,32 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
550
582
|
fileStream = this.pipeOutputToFile ? fs.createWriteStream(this.pipeOutputToFile) : null;
|
|
551
583
|
return new Promise(function (resolve, reject) {
|
|
552
584
|
var _a, _b, _c, _d;
|
|
585
|
+
var complete = function () {
|
|
586
|
+
if (waitingEvents != 0) {
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
if (df) {
|
|
590
|
+
df.finalize();
|
|
591
|
+
}
|
|
592
|
+
if (error) {
|
|
593
|
+
reject(error);
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
resolve(returnCode);
|
|
597
|
+
}
|
|
598
|
+
};
|
|
553
599
|
if (fileStream) {
|
|
554
600
|
waitingEvents++;
|
|
555
601
|
fileStream.on('finish', function () {
|
|
556
602
|
waitingEvents--; //file write is complete
|
|
557
603
|
fileStream = null;
|
|
558
|
-
|
|
559
|
-
if (error) {
|
|
560
|
-
reject(error);
|
|
561
|
-
}
|
|
562
|
-
else {
|
|
563
|
-
resolve(returnCode);
|
|
564
|
-
}
|
|
565
|
-
}
|
|
604
|
+
complete();
|
|
566
605
|
});
|
|
567
606
|
fileStream.on('error', function (err) {
|
|
568
607
|
waitingEvents--; //there were errors writing to the file, write is done
|
|
569
608
|
_this._debug("Failed to pipe output of ".concat(toolPathFirst, " to file ").concat(_this.pipeOutputToFile, ". Error = ").concat(err));
|
|
570
609
|
fileStream = null;
|
|
571
|
-
|
|
572
|
-
if (error) {
|
|
573
|
-
reject(error);
|
|
574
|
-
}
|
|
575
|
-
else {
|
|
576
|
-
resolve(returnCode);
|
|
577
|
-
}
|
|
578
|
-
}
|
|
610
|
+
complete();
|
|
579
611
|
});
|
|
580
612
|
}
|
|
581
613
|
//pipe stdout of first tool to stdin of second tool
|
|
@@ -600,8 +632,13 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
600
632
|
}
|
|
601
633
|
successFirst = !optionsNonNull.failOnStdErr;
|
|
602
634
|
if (!optionsNonNull.silent) {
|
|
603
|
-
|
|
604
|
-
|
|
635
|
+
if (df) {
|
|
636
|
+
df.stderr(data);
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream;
|
|
640
|
+
s.write(data);
|
|
641
|
+
}
|
|
605
642
|
}
|
|
606
643
|
});
|
|
607
644
|
cpFirst.on('error', function (err) {
|
|
@@ -612,9 +649,7 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
612
649
|
}
|
|
613
650
|
(_a = cp.stdin) === null || _a === void 0 ? void 0 : _a.end();
|
|
614
651
|
error = new Error(toolPathFirst + ' failed. ' + err.message);
|
|
615
|
-
|
|
616
|
-
reject(error);
|
|
617
|
-
}
|
|
652
|
+
complete();
|
|
618
653
|
});
|
|
619
654
|
cpFirst.on('close', function (code, signal) {
|
|
620
655
|
var _a;
|
|
@@ -629,20 +664,18 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
629
664
|
fileStream.end();
|
|
630
665
|
}
|
|
631
666
|
(_a = cp.stdin) === null || _a === void 0 ? void 0 : _a.end();
|
|
632
|
-
|
|
633
|
-
if (error) {
|
|
634
|
-
reject(error);
|
|
635
|
-
}
|
|
636
|
-
else {
|
|
637
|
-
resolve(returnCode);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
667
|
+
complete();
|
|
640
668
|
});
|
|
641
669
|
var stdLineBuffer = '';
|
|
642
670
|
(_c = cp.stdout) === null || _c === void 0 ? void 0 : _c.on('data', function (data) {
|
|
643
671
|
_this.emit('stdout', data);
|
|
644
672
|
if (!optionsNonNull.silent) {
|
|
645
|
-
|
|
673
|
+
if (df) {
|
|
674
|
+
df.stdout(data);
|
|
675
|
+
}
|
|
676
|
+
else {
|
|
677
|
+
optionsNonNull.outStream.write(data);
|
|
678
|
+
}
|
|
646
679
|
}
|
|
647
680
|
stdLineBuffer = _this._processLineBuffer(data, stdLineBuffer, function (line) {
|
|
648
681
|
_this.emit('stdline', line);
|
|
@@ -653,8 +686,13 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
653
686
|
_this.emit('stderr', data);
|
|
654
687
|
success = !optionsNonNull.failOnStdErr;
|
|
655
688
|
if (!optionsNonNull.silent) {
|
|
656
|
-
|
|
657
|
-
|
|
689
|
+
if (df) {
|
|
690
|
+
df.stderr(data);
|
|
691
|
+
}
|
|
692
|
+
else {
|
|
693
|
+
var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream;
|
|
694
|
+
s.write(data);
|
|
695
|
+
}
|
|
658
696
|
}
|
|
659
697
|
errLineBuffer = _this._processLineBuffer(data, errLineBuffer, function (line) {
|
|
660
698
|
_this.emit('errline', line);
|
|
@@ -663,9 +701,7 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
663
701
|
cp.on('error', function (err) {
|
|
664
702
|
waitingEvents--; //process is done with errors
|
|
665
703
|
error = new Error(toolPath + ' failed. ' + err.message);
|
|
666
|
-
|
|
667
|
-
reject(error);
|
|
668
|
-
}
|
|
704
|
+
complete();
|
|
669
705
|
});
|
|
670
706
|
cp.on('close', function (code, signal) {
|
|
671
707
|
waitingEvents--; //process is complete
|
|
@@ -687,14 +723,7 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
687
723
|
else if (!success) {
|
|
688
724
|
error = new Error(toolPath + ' failed with return code: ' + code);
|
|
689
725
|
}
|
|
690
|
-
|
|
691
|
-
if (error) {
|
|
692
|
-
reject(error);
|
|
693
|
-
}
|
|
694
|
-
else {
|
|
695
|
-
resolve(returnCode);
|
|
696
|
-
}
|
|
697
|
-
}
|
|
726
|
+
complete();
|
|
698
727
|
});
|
|
699
728
|
});
|
|
700
729
|
};
|
|
@@ -709,8 +738,14 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
709
738
|
});
|
|
710
739
|
var success = true;
|
|
711
740
|
var optionsNonNull = this._cloneExecOptions(options);
|
|
741
|
+
var df = this._createDisplayFilter(optionsNonNull);
|
|
712
742
|
if (!optionsNonNull.silent) {
|
|
713
|
-
|
|
743
|
+
if (df) {
|
|
744
|
+
df.commandLine(this._getCommandString(optionsNonNull) + os.EOL);
|
|
745
|
+
}
|
|
746
|
+
else {
|
|
747
|
+
optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);
|
|
748
|
+
}
|
|
714
749
|
}
|
|
715
750
|
var cp;
|
|
716
751
|
var toolPath = pipeOutputToTool.toolPath;
|
|
@@ -730,32 +765,32 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
730
765
|
waitingEvents++;
|
|
731
766
|
cp = child.spawn(pipeOutputToTool._getSpawnFileName(optionsNonNull), pipeOutputToTool._getSpawnArgs(optionsNonNull), pipeOutputToTool._getSpawnOptions(optionsNonNull));
|
|
732
767
|
fileStream = this.pipeOutputToFile ? fs.createWriteStream(this.pipeOutputToFile) : null;
|
|
768
|
+
var complete = function () {
|
|
769
|
+
if (waitingEvents != 0) {
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
if (df) {
|
|
773
|
+
df.finalize();
|
|
774
|
+
}
|
|
775
|
+
if (error) {
|
|
776
|
+
defer.reject(error);
|
|
777
|
+
}
|
|
778
|
+
else {
|
|
779
|
+
defer.resolve(returnCode);
|
|
780
|
+
}
|
|
781
|
+
};
|
|
733
782
|
if (fileStream) {
|
|
734
783
|
waitingEvents++;
|
|
735
784
|
fileStream.on('finish', function () {
|
|
736
785
|
waitingEvents--; //file write is complete
|
|
737
786
|
fileStream = null;
|
|
738
|
-
|
|
739
|
-
if (error) {
|
|
740
|
-
defer.reject(error);
|
|
741
|
-
}
|
|
742
|
-
else {
|
|
743
|
-
defer.resolve(returnCode);
|
|
744
|
-
}
|
|
745
|
-
}
|
|
787
|
+
complete();
|
|
746
788
|
});
|
|
747
789
|
fileStream.on('error', function (err) {
|
|
748
790
|
waitingEvents--; //there were errors writing to the file, write is done
|
|
749
791
|
_this._debug("Failed to pipe output of ".concat(toolPathFirst, " to file ").concat(_this.pipeOutputToFile, ". Error = ").concat(err));
|
|
750
792
|
fileStream = null;
|
|
751
|
-
|
|
752
|
-
if (error) {
|
|
753
|
-
defer.reject(error);
|
|
754
|
-
}
|
|
755
|
-
else {
|
|
756
|
-
defer.resolve(returnCode);
|
|
757
|
-
}
|
|
758
|
-
}
|
|
793
|
+
complete();
|
|
759
794
|
});
|
|
760
795
|
}
|
|
761
796
|
//pipe stdout of first tool to stdin of second tool
|
|
@@ -778,8 +813,13 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
778
813
|
}
|
|
779
814
|
successFirst = !optionsNonNull.failOnStdErr;
|
|
780
815
|
if (!optionsNonNull.silent) {
|
|
781
|
-
|
|
782
|
-
|
|
816
|
+
if (df) {
|
|
817
|
+
df.stderr(data);
|
|
818
|
+
}
|
|
819
|
+
else {
|
|
820
|
+
var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream;
|
|
821
|
+
s.write(data);
|
|
822
|
+
}
|
|
783
823
|
}
|
|
784
824
|
});
|
|
785
825
|
cpFirst.on('error', function (err) {
|
|
@@ -790,9 +830,7 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
790
830
|
}
|
|
791
831
|
(_a = cp.stdin) === null || _a === void 0 ? void 0 : _a.end();
|
|
792
832
|
error = new Error(toolPathFirst + ' failed. ' + err.message);
|
|
793
|
-
|
|
794
|
-
defer.reject(error);
|
|
795
|
-
}
|
|
833
|
+
complete();
|
|
796
834
|
});
|
|
797
835
|
cpFirst.on('close', function (code, signal) {
|
|
798
836
|
var _a;
|
|
@@ -807,20 +845,18 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
807
845
|
fileStream.end();
|
|
808
846
|
}
|
|
809
847
|
(_a = cp.stdin) === null || _a === void 0 ? void 0 : _a.end();
|
|
810
|
-
|
|
811
|
-
if (error) {
|
|
812
|
-
defer.reject(error);
|
|
813
|
-
}
|
|
814
|
-
else {
|
|
815
|
-
defer.resolve(returnCode);
|
|
816
|
-
}
|
|
817
|
-
}
|
|
848
|
+
complete();
|
|
818
849
|
});
|
|
819
850
|
var stdLineBuffer = '';
|
|
820
851
|
(_c = cp.stdout) === null || _c === void 0 ? void 0 : _c.on('data', function (data) {
|
|
821
852
|
_this.emit('stdout', data);
|
|
822
853
|
if (!optionsNonNull.silent) {
|
|
823
|
-
|
|
854
|
+
if (df) {
|
|
855
|
+
df.stdout(data);
|
|
856
|
+
}
|
|
857
|
+
else {
|
|
858
|
+
optionsNonNull.outStream.write(data);
|
|
859
|
+
}
|
|
824
860
|
}
|
|
825
861
|
stdLineBuffer = _this._processLineBuffer(data, stdLineBuffer, function (line) {
|
|
826
862
|
_this.emit('stdline', line);
|
|
@@ -831,8 +867,13 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
831
867
|
_this.emit('stderr', data);
|
|
832
868
|
success = !optionsNonNull.failOnStdErr;
|
|
833
869
|
if (!optionsNonNull.silent) {
|
|
834
|
-
|
|
835
|
-
|
|
870
|
+
if (df) {
|
|
871
|
+
df.stderr(data);
|
|
872
|
+
}
|
|
873
|
+
else {
|
|
874
|
+
var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream;
|
|
875
|
+
s.write(data);
|
|
876
|
+
}
|
|
836
877
|
}
|
|
837
878
|
errLineBuffer = _this._processLineBuffer(data, errLineBuffer, function (line) {
|
|
838
879
|
_this.emit('errline', line);
|
|
@@ -841,9 +882,7 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
841
882
|
cp.on('error', function (err) {
|
|
842
883
|
waitingEvents--; //process is done with errors
|
|
843
884
|
error = new Error(toolPath + ' failed. ' + err.message);
|
|
844
|
-
|
|
845
|
-
defer.reject(error);
|
|
846
|
-
}
|
|
885
|
+
complete();
|
|
847
886
|
});
|
|
848
887
|
cp.on('close', function (code, signal) {
|
|
849
888
|
waitingEvents--; //process is complete
|
|
@@ -865,14 +904,7 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
865
904
|
else if (!success) {
|
|
866
905
|
error = new Error(toolPath + ' failed with return code: ' + code);
|
|
867
906
|
}
|
|
868
|
-
|
|
869
|
-
if (error) {
|
|
870
|
-
defer.reject(error);
|
|
871
|
-
}
|
|
872
|
-
else {
|
|
873
|
-
defer.resolve(returnCode);
|
|
874
|
-
}
|
|
875
|
-
}
|
|
907
|
+
complete();
|
|
876
908
|
});
|
|
877
909
|
return defer.promise;
|
|
878
910
|
};
|
|
@@ -961,8 +993,14 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
961
993
|
_this._debug(' ' + arg);
|
|
962
994
|
});
|
|
963
995
|
var optionsNonNull = this._cloneExecOptions(options);
|
|
996
|
+
var df = this._createDisplayFilter(optionsNonNull);
|
|
964
997
|
if (!optionsNonNull.silent) {
|
|
965
|
-
|
|
998
|
+
if (df) {
|
|
999
|
+
df.commandLine(this._getCommandString(optionsNonNull) + os.EOL);
|
|
1000
|
+
}
|
|
1001
|
+
else {
|
|
1002
|
+
optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);
|
|
1003
|
+
}
|
|
966
1004
|
}
|
|
967
1005
|
var state = new ExecState(optionsNonNull, this.toolPath);
|
|
968
1006
|
state.on('debug', function (message) {
|
|
@@ -1007,15 +1045,25 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
1007
1045
|
// it is possible for the child process to end its last line without a new line.
|
|
1008
1046
|
// because stdout is buffered, this causes the last line to not get sent to the parent
|
|
1009
1047
|
// stream. Adding this event forces a flush before the child streams are closed.
|
|
1010
|
-
(_a = cp.stdout) === null || _a === void 0 ? void 0 : _a.on('
|
|
1048
|
+
(_a = cp.stdout) === null || _a === void 0 ? void 0 : _a.on('end', function () {
|
|
1011
1049
|
if (!optionsNonNull.silent) {
|
|
1012
|
-
|
|
1050
|
+
if (df) {
|
|
1051
|
+
df.stdout(Buffer.from(os.EOL));
|
|
1052
|
+
}
|
|
1053
|
+
else {
|
|
1054
|
+
optionsNonNull.outStream.write(os.EOL);
|
|
1055
|
+
}
|
|
1013
1056
|
}
|
|
1014
1057
|
});
|
|
1015
1058
|
(_b = cp.stdout) === null || _b === void 0 ? void 0 : _b.on('data', function (data) {
|
|
1016
1059
|
_this.emit('stdout', data);
|
|
1017
1060
|
if (!optionsNonNull.silent) {
|
|
1018
|
-
|
|
1061
|
+
if (df) {
|
|
1062
|
+
df.stdout(data);
|
|
1063
|
+
}
|
|
1064
|
+
else {
|
|
1065
|
+
optionsNonNull.outStream.write(data);
|
|
1066
|
+
}
|
|
1019
1067
|
}
|
|
1020
1068
|
stdLineBuffer = _this._processLineBuffer(data, stdLineBuffer, function (line) {
|
|
1021
1069
|
_this.emit('stdline', line);
|
|
@@ -1025,8 +1073,13 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
1025
1073
|
state.processStderr = true;
|
|
1026
1074
|
_this.emit('stderr', data);
|
|
1027
1075
|
if (!optionsNonNull.silent) {
|
|
1028
|
-
|
|
1029
|
-
|
|
1076
|
+
if (df) {
|
|
1077
|
+
df.stderr(data);
|
|
1078
|
+
}
|
|
1079
|
+
else {
|
|
1080
|
+
var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream;
|
|
1081
|
+
s.write(data);
|
|
1082
|
+
}
|
|
1030
1083
|
}
|
|
1031
1084
|
errLineBuffer = _this._processLineBuffer(data, errLineBuffer, function (line) {
|
|
1032
1085
|
_this.emit('errline', line);
|
|
@@ -1046,6 +1099,9 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
1046
1099
|
state.CheckComplete();
|
|
1047
1100
|
});
|
|
1048
1101
|
cp.on('close', function (code, signal) {
|
|
1102
|
+
if (df) {
|
|
1103
|
+
df.finalize();
|
|
1104
|
+
}
|
|
1049
1105
|
state.processCloseCode = code;
|
|
1050
1106
|
state.processCloseSignal = signal;
|
|
1051
1107
|
state.processClosed = true;
|
|
@@ -1077,8 +1133,14 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
1077
1133
|
_this._debug(' ' + arg);
|
|
1078
1134
|
});
|
|
1079
1135
|
var optionsNonNull = this._cloneExecOptions(options);
|
|
1136
|
+
var df = this._createDisplayFilter(optionsNonNull);
|
|
1080
1137
|
if (!optionsNonNull.silent) {
|
|
1081
|
-
|
|
1138
|
+
if (df) {
|
|
1139
|
+
df.commandLine(this._getCommandString(optionsNonNull) + os.EOL);
|
|
1140
|
+
}
|
|
1141
|
+
else {
|
|
1142
|
+
optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);
|
|
1143
|
+
}
|
|
1082
1144
|
}
|
|
1083
1145
|
var state = new ExecState(optionsNonNull, this.toolPath);
|
|
1084
1146
|
state.on('debug', function (message) {
|
|
@@ -1119,15 +1181,25 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
1119
1181
|
// it is possible for the child process to end its last line without a new line.
|
|
1120
1182
|
// because stdout is buffered, this causes the last line to not get sent to the parent
|
|
1121
1183
|
// stream. Adding this event forces a flush before the child streams are closed.
|
|
1122
|
-
(_a = cp.stdout) === null || _a === void 0 ? void 0 : _a.on('
|
|
1184
|
+
(_a = cp.stdout) === null || _a === void 0 ? void 0 : _a.on('end', function () {
|
|
1123
1185
|
if (!optionsNonNull.silent) {
|
|
1124
|
-
|
|
1186
|
+
if (df) {
|
|
1187
|
+
df.stdout(Buffer.from(os.EOL));
|
|
1188
|
+
}
|
|
1189
|
+
else {
|
|
1190
|
+
optionsNonNull.outStream.write(os.EOL);
|
|
1191
|
+
}
|
|
1125
1192
|
}
|
|
1126
1193
|
});
|
|
1127
1194
|
(_b = cp.stdout) === null || _b === void 0 ? void 0 : _b.on('data', function (data) {
|
|
1128
1195
|
_this.emit('stdout', data);
|
|
1129
1196
|
if (!optionsNonNull.silent) {
|
|
1130
|
-
|
|
1197
|
+
if (df) {
|
|
1198
|
+
df.stdout(data);
|
|
1199
|
+
}
|
|
1200
|
+
else {
|
|
1201
|
+
optionsNonNull.outStream.write(data);
|
|
1202
|
+
}
|
|
1131
1203
|
}
|
|
1132
1204
|
stdLineBuffer = _this._processLineBuffer(data, stdLineBuffer, function (line) {
|
|
1133
1205
|
_this.emit('stdline', line);
|
|
@@ -1137,8 +1209,13 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
1137
1209
|
state.processStderr = true;
|
|
1138
1210
|
_this.emit('stderr', data);
|
|
1139
1211
|
if (!optionsNonNull.silent) {
|
|
1140
|
-
|
|
1141
|
-
|
|
1212
|
+
if (df) {
|
|
1213
|
+
df.stderr(data);
|
|
1214
|
+
}
|
|
1215
|
+
else {
|
|
1216
|
+
var s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream;
|
|
1217
|
+
s.write(data);
|
|
1218
|
+
}
|
|
1142
1219
|
}
|
|
1143
1220
|
errLineBuffer = _this._processLineBuffer(data, errLineBuffer, function (line) {
|
|
1144
1221
|
_this.emit('errline', line);
|
|
@@ -1158,6 +1235,9 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
1158
1235
|
state.CheckComplete();
|
|
1159
1236
|
});
|
|
1160
1237
|
cp.on('close', function (code, signal) {
|
|
1238
|
+
if (df) {
|
|
1239
|
+
df.finalize();
|
|
1240
|
+
}
|
|
1161
1241
|
state.processCloseCode = code;
|
|
1162
1242
|
state.processCloseSignal = signal;
|
|
1163
1243
|
state.processClosed = true;
|
|
@@ -1185,15 +1265,17 @@ var ToolRunner = /** @class */ (function (_super) {
|
|
|
1185
1265
|
});
|
|
1186
1266
|
var success = true;
|
|
1187
1267
|
options = this._cloneExecOptions(options);
|
|
1268
|
+
var ext = options.externalOutput;
|
|
1188
1269
|
if (!options.silent) {
|
|
1189
|
-
|
|
1270
|
+
var cmdLine = this._getCommandString(options) + os.EOL;
|
|
1271
|
+
options.outStream.write(ext ? eom.filterExternalOutput(cmdLine, ext) : cmdLine);
|
|
1190
1272
|
}
|
|
1191
1273
|
var r = child.spawnSync(this._getSpawnFileName(options), this._getSpawnArgs(options), this._getSpawnSyncOptions(options));
|
|
1192
1274
|
if (!options.silent && r.stdout && r.stdout.length > 0) {
|
|
1193
|
-
options.outStream.write(r.stdout);
|
|
1275
|
+
options.outStream.write(ext ? eom.filterExternalOutput(r.stdout, ext) : r.stdout);
|
|
1194
1276
|
}
|
|
1195
1277
|
if (!options.silent && r.stderr && r.stderr.length > 0) {
|
|
1196
|
-
options.errStream.write(r.stderr);
|
|
1278
|
+
options.errStream.write(ext ? eom.filterExternalOutput(r.stderr, ext) : r.stderr);
|
|
1197
1279
|
}
|
|
1198
1280
|
var res = { code: r.status, error: r.error };
|
|
1199
1281
|
res.stdout = (r.stdout) ? r.stdout.toString() : '';
|