Use core.setOutput to set output

df1bc16 · Jonathan Clem · 2020-08-05 14:52

2 files +1479 -798

Files changed

modified dist/index.js
+1477 −796
@@ -19,13 +19,7 @@ module.exports =
19 19 /******/ };
20 20 /******/
21 21 /******/ // Execute the module function
22 /******/ var threw = true;
23 /******/ try {
24 /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
25 /******/ threw = false;
26 /******/ } finally {
27 /******/ if(threw) delete installedModules[moduleId];
28 /******/ }
22 +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
29 23 /******/
30 24 /******/ // Flag the module as loaded
31 25 /******/ module.l = true;
@@ -53,578 +47,605 @@ module.exports =
53 47 /***/ (function(__unusedmodule, exports, __webpack_require__) {
54 48
55 49 "use strict";
56
57 var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
58 return new (P || (P = Promise))(function (resolve, reject) {
59 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
60 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
61 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
62 step((generator = generator.apply(thisArg, _arguments || [])).next());
63 });
64 };
65 Object.defineProperty(exports, "__esModule", { value: true });
66 const os = __webpack_require__(87);
67 const events = __webpack_require__(614);
68 const child = __webpack_require__(129);
69 /* eslint-disable @typescript-eslint/unbound-method */
70 const IS_WINDOWS = process.platform === 'win32';
71 /*
72 * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way.
73 */
74 class ToolRunner extends events.EventEmitter {
75 constructor(toolPath, args, options) {
76 super();
77 if (!toolPath) {
78 throw new Error("Parameter 'toolPath' cannot be null or empty.");
79 }
80 this.toolPath = toolPath;
81 this.args = args || [];
82 this.options = options || {};
83 }
84 _debug(message) {
85 if (this.options.listeners && this.options.listeners.debug) {
86 this.options.listeners.debug(message);
87 }
88 }
89 _getCommandString(options, noPrefix) {
90 const toolPath = this._getSpawnFileName();
91 const args = this._getSpawnArgs(options);
92 let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool
93 if (IS_WINDOWS) {
94 // Windows + cmd file
95 if (this._isCmdFile()) {
96 cmd += toolPath;
97 for (const a of args) {
98 cmd += ` ${a}`;
99 }
100 }
101 // Windows + verbatim
102 else if (options.windowsVerbatimArguments) {
103 cmd += `"${toolPath}"`;
104 for (const a of args) {
105 cmd += ` ${a}`;
106 }
107 }
108 // Windows (regular)
109 else {
110 cmd += this._windowsQuoteCmdArg(toolPath);
111 for (const a of args) {
112 cmd += ` ${this._windowsQuoteCmdArg(a)}`;
113 }
114 }
115 }
116 else {
117 // OSX/Linux - this can likely be improved with some form of quoting.
118 // creating processes on Unix is fundamentally different than Windows.
119 // on Unix, execvp() takes an arg array.
120 cmd += toolPath;
121 for (const a of args) {
122 cmd += ` ${a}`;
123 }
124 }
125 return cmd;
126 }
127 _processLineBuffer(data, strBuffer, onLine) {
128 try {
129 let s = strBuffer + data.toString();
130 let n = s.indexOf(os.EOL);
131 while (n > -1) {
132 const line = s.substring(0, n);
133 onLine(line);
134 // the rest of the string ...
135 s = s.substring(n + os.EOL.length);
136 n = s.indexOf(os.EOL);
137 }
138 strBuffer = s;
139 }
140 catch (err) {
141 // streaming lines to console is best effort. Don't fail a build.
142 this._debug(`error processing line. Failed with error ${err}`);
143 }
144 }
145 _getSpawnFileName() {
146 if (IS_WINDOWS) {
147 if (this._isCmdFile()) {
148 return process.env['COMSPEC'] || 'cmd.exe';
149 }
150 }
151 return this.toolPath;
152 }
153 _getSpawnArgs(options) {
154 if (IS_WINDOWS) {
155 if (this._isCmdFile()) {
156 let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`;
157 for (const a of this.args) {
158 argline += ' ';
159 argline += options.windowsVerbatimArguments
160 ? a
161 : this._windowsQuoteCmdArg(a);
162 }
163 argline += '"';
164 return [argline];
165 }
166 }
167 return this.args;
168 }
169 _endsWith(str, end) {
170 return str.endsWith(end);
171 }
172 _isCmdFile() {
173 const upperToolPath = this.toolPath.toUpperCase();
174 return (this._endsWith(upperToolPath, '.CMD') ||
175 this._endsWith(upperToolPath, '.BAT'));
176 }
177 _windowsQuoteCmdArg(arg) {
178 // for .exe, apply the normal quoting rules that libuv applies
179 if (!this._isCmdFile()) {
180 return this._uvQuoteCmdArg(arg);
181 }
182 // otherwise apply quoting rules specific to the cmd.exe command line parser.
183 // the libuv rules are generic and are not designed specifically for cmd.exe
184 // command line parser.
185 //
186 // for a detailed description of the cmd.exe command line parser, refer to
187 // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912
188 // need quotes for empty arg
189 if (!arg) {
190 return '""';
191 }
192 // determine whether the arg needs to be quoted
193 const cmdSpecialChars = [
194 ' ',
195 '\t',
196 '&',
197 '(',
198 ')',
199 '[',
200 ']',
201 '{',
202 '}',
203 '^',
204 '=',
205 ';',
206 '!',
207 "'",
208 '+',
209 ',',
210 '`',
211 '~',
212 '|',
213 '<',
214 '>',
215 '"'
216 ];
217 let needsQuotes = false;
218 for (const char of arg) {
219 if (cmdSpecialChars.some(x => x === char)) {
220 needsQuotes = true;
221 break;
222 }
223 }
224 // short-circuit if quotes not needed
225 if (!needsQuotes) {
226 return arg;
227 }
228 // the following quoting rules are very similar to the rules that by libuv applies.
229 //
230 // 1) wrap the string in quotes
231 //
232 // 2) double-up quotes - i.e. " => ""
233 //
234 // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately
235 // doesn't work well with a cmd.exe command line.
236 //
237 // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app.
238 // for example, the command line:
239 // foo.exe "myarg:""my val"""
240 // is parsed by a .NET console app into an arg array:
241 // [ "myarg:\"my val\"" ]
242 // which is the same end result when applying libuv quoting rules. although the actual
243 // command line from libuv quoting rules would look like:
244 // foo.exe "myarg:\"my val\""
245 //
246 // 3) double-up slashes that preceed a quote,
247 // e.g. hello \world => "hello \world"
248 // hello\"world => "hello\\""world"
249 // hello\\"world => "hello\\\\""world"
250 // hello world\ => "hello world\\"
251 //
252 // technically this is not required for a cmd.exe command line, or the batch argument parser.
253 // the reasons for including this as a .cmd quoting rule are:
254 //
255 // a) this is optimized for the scenario where the argument is passed from the .cmd file to an
256 // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule.
257 //
258 // b) it's what we've been doing previously (by deferring to node default behavior) and we
259 // haven't heard any complaints about that aspect.
260 //
261 // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be
262 // escaped when used on the command line directly - even though within a .cmd file % can be escaped
263 // by using %%.
264 //
265 // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts
266 // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing.
267 //
268 // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would
269 // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the
270 // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args
271 // to an external program.
272 //
273 // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file.
274 // % can be escaped within a .cmd file.
275 let reverse = '"';
276 let quoteHit = true;
277 for (let i = arg.length; i > 0; i--) {
278 // walk the string in reverse
279 reverse += arg[i - 1];
280 if (quoteHit && arg[i - 1] === '\\') {
281 reverse += '\\'; // double the slash
282 }
283 else if (arg[i - 1] === '"') {
284 quoteHit = true;
285 reverse += '"'; // double the quote
286 }
287 else {
288 quoteHit = false;
289 }
290 }
291 reverse += '"';
292 return reverse
293 .split('')
294 .reverse()
295 .join('');
296 }
297 _uvQuoteCmdArg(arg) {
298 // Tool runner wraps child_process.spawn() and needs to apply the same quoting as
299 // Node in certain cases where the undocumented spawn option windowsVerbatimArguments
300 // is used.
301 //
302 // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV,
303 // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details),
304 // pasting copyright notice from Node within this function:
305 //
306 // Copyright Joyent, Inc. and other Node contributors. All rights reserved.
307 //
308 // Permission is hereby granted, free of charge, to any person obtaining a copy
309 // of this software and associated documentation files (the "Software"), to
310 // deal in the Software without restriction, including without limitation the
311 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
312 // sell copies of the Software, and to permit persons to whom the Software is
313 // furnished to do so, subject to the following conditions:
314 //
315 // The above copyright notice and this permission notice shall be included in
316 // all copies or substantial portions of the Software.
317 //
318 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
319 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
320 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
321 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
322 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
323 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
324 // IN THE SOFTWARE.
325 if (!arg) {
326 // Need double quotation for empty argument
327 return '""';
328 }
329 if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) {
330 // No quotation needed
331 return arg;
332 }
333 if (!arg.includes('"') && !arg.includes('\\')) {
334 // No embedded double quotes or backslashes, so I can just wrap
335 // quote marks around the whole thing.
336 return `"${arg}"`;
337 }
338 // Expected input/output:
339 // input : hello"world
340 // output: "hello\"world"
341 // input : hello""world
342 // output: "hello\"\"world"
343 // input : hello\world
344 // output: hello\world
345 // input : hello\\world
346 // output: hello\\world
347 // input : hello\"world
348 // output: "hello\\\"world"
349 // input : hello\\"world
350 // output: "hello\\\\\"world"
351 // input : hello world\
352 // output: "hello world\\" - note the comment in libuv actually reads "hello world\"
353 // but it appears the comment is wrong, it should be "hello world\\"
354 let reverse = '"';
355 let quoteHit = true;
356 for (let i = arg.length; i > 0; i--) {
357 // walk the string in reverse
358 reverse += arg[i - 1];
359 if (quoteHit && arg[i - 1] === '\\') {
360 reverse += '\\';
361 }
362 else if (arg[i - 1] === '"') {
363 quoteHit = true;
364 reverse += '\\';
365 }
366 else {
367 quoteHit = false;
368 }
369 }
370 reverse += '"';
371 return reverse
372 .split('')
373 .reverse()
374 .join('');
375 }
376 _cloneExecOptions(options) {
377 options = options || {};
378 const result = {
379 cwd: options.cwd || process.cwd(),
380 env: options.env || process.env,
381 silent: options.silent || false,
382 windowsVerbatimArguments: options.windowsVerbatimArguments || false,
383 failOnStdErr: options.failOnStdErr || false,
384 ignoreReturnCode: options.ignoreReturnCode || false,
385 delay: options.delay || 10000
386 };
387 result.outStream = options.outStream || process.stdout;
388 result.errStream = options.errStream || process.stderr;
389 return result;
390 }
391 _getSpawnOptions(options, toolPath) {
392 options = options || {};
393 const result = {};
394 result.cwd = options.cwd;
395 result.env = options.env;
396 result['windowsVerbatimArguments'] =
397 options.windowsVerbatimArguments || this._isCmdFile();
398 if (options.windowsVerbatimArguments) {
399 result.argv0 = `"${toolPath}"`;
400 }
401 return result;
402 }
403 /**
404 * Exec a tool.
405 * Output will be streamed to the live console.
406 * Returns promise with return code
407 *
408 * @param tool path to tool to exec
409 * @param options optional exec options. See ExecOptions
410 * @returns number
411 */
412 exec() {
413 return __awaiter(this, void 0, void 0, function* () {
414 return new Promise((resolve, reject) => {
415 this._debug(`exec tool: ${this.toolPath}`);
416 this._debug('arguments:');
417 for (const arg of this.args) {
418 this._debug(` ${arg}`);
419 }
420 const optionsNonNull = this._cloneExecOptions(this.options);
421 if (!optionsNonNull.silent && optionsNonNull.outStream) {
422 optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);
423 }
424 const state = new ExecState(optionsNonNull, this.toolPath);
425 state.on('debug', (message) => {
426 this._debug(message);
427 });
428 const fileName = this._getSpawnFileName();
429 const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName));
430 const stdbuffer = '';
431 if (cp.stdout) {
432 cp.stdout.on('data', (data) => {
433 if (this.options.listeners && this.options.listeners.stdout) {
434 this.options.listeners.stdout(data);
435 }
436 if (!optionsNonNull.silent && optionsNonNull.outStream) {
437 optionsNonNull.outStream.write(data);
438 }
439 this._processLineBuffer(data, stdbuffer, (line) => {
440 if (this.options.listeners && this.options.listeners.stdline) {
441 this.options.listeners.stdline(line);
442 }
443 });
444 });
445 }
446 const errbuffer = '';
447 if (cp.stderr) {
448 cp.stderr.on('data', (data) => {
449 state.processStderr = true;
450 if (this.options.listeners && this.options.listeners.stderr) {
451 this.options.listeners.stderr(data);
452 }
453 if (!optionsNonNull.silent &&
454 optionsNonNull.errStream &&
455 optionsNonNull.outStream) {
456 const s = optionsNonNull.failOnStdErr
457 ? optionsNonNull.errStream
458 : optionsNonNull.outStream;
459 s.write(data);
460 }
461 this._processLineBuffer(data, errbuffer, (line) => {
462 if (this.options.listeners && this.options.listeners.errline) {
463 this.options.listeners.errline(line);
464 }
465 });
466 });
467 }
468 cp.on('error', (err) => {
469 state.processError = err.message;
470 state.processExited = true;
471 state.processClosed = true;
472 state.CheckComplete();
473 });
474 cp.on('exit', (code) => {
475 state.processExitCode = code;
476 state.processExited = true;
477 this._debug(`Exit code ${code} received from tool '${this.toolPath}'`);
478 state.CheckComplete();
479 });
480 cp.on('close', (code) => {
481 state.processExitCode = code;
482 state.processExited = true;
483 state.processClosed = true;
484 this._debug(`STDIO streams have closed for tool '${this.toolPath}'`);
485 state.CheckComplete();
486 });
487 state.on('done', (error, exitCode) => {
488 if (stdbuffer.length > 0) {
489 this.emit('stdline', stdbuffer);
490 }
491 if (errbuffer.length > 0) {
492 this.emit('errline', errbuffer);
493 }
494 cp.removeAllListeners();
495 if (error) {
496 reject(error);
497 }
498 else {
499 resolve(exitCode);
500 }
501 });
502 });
503 });
504 }
505 }
506 exports.ToolRunner = ToolRunner;
507 /**
508 * Convert an arg string to an array of args. Handles escaping
509 *
510 * @param argString string of arguments
511 * @returns string[] array of arguments
512 */
513 function argStringToArray(argString) {
514 const args = [];
515 let inQuotes = false;
516 let escaped = false;
517 let arg = '';
518 function append(c) {
519 // we only escape double quotes.
520 if (escaped && c !== '"') {
521 arg += '\\';
522 }
523 arg += c;
524 escaped = false;
525 }
526 for (let i = 0; i < argString.length; i++) {
527 const c = argString.charAt(i);
528 if (c === '"') {
529 if (!escaped) {
530 inQuotes = !inQuotes;
531 }
532 else {
533 append(c);
534 }
535 continue;
536 }
537 if (c === '\\' && escaped) {
538 append(c);
539 continue;
540 }
541 if (c === '\\' && inQuotes) {
542 escaped = true;
543 continue;
544 }
545 if (c === ' ' && !inQuotes) {
546 if (arg.length > 0) {
547 args.push(arg);
548 arg = '';
549 }
550 continue;
551 }
552 append(c);
553 }
554 if (arg.length > 0) {
555 args.push(arg.trim());
556 }
557 return args;
558 }
559 exports.argStringToArray = argStringToArray;
560 class ExecState extends events.EventEmitter {
561 constructor(options, toolPath) {
562 super();
563 this.processClosed = false; // tracks whether the process has exited and stdio is closed
564 this.processError = '';
565 this.processExitCode = 0;
566 this.processExited = false; // tracks whether the process has exited
567 this.processStderr = false; // tracks whether stderr was written to
568 this.delay = 10000; // 10 seconds
569 this.done = false;
570 this.timeout = null;
571 if (!toolPath) {
572 throw new Error('toolPath must not be empty');
573 }
574 this.options = options;
575 this.toolPath = toolPath;
576 if (options.delay) {
577 this.delay = options.delay;
578 }
579 }
580 CheckComplete() {
581 if (this.done) {
582 return;
583 }
584 if (this.processClosed) {
585 this._setResult();
586 }
587 else if (this.processExited) {
588 this.timeout = setTimeout(ExecState.HandleTimeout, this.delay, this);
589 }
590 }
591 _debug(message) {
592 this.emit('debug', message);
593 }
594 _setResult() {
595 // determine whether there is an error
596 let error;
597 if (this.processExited) {
598 if (this.processError) {
599 error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`);
600 }
601 else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) {
602 error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`);
603 }
604 else if (this.processStderr && this.options.failOnStdErr) {
605 error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`);
606 }
607 }
608 // clear the timeout
609 if (this.timeout) {
610 clearTimeout(this.timeout);
611 this.timeout = null;
612 }
613 this.done = true;
614 this.emit('done', error, this.processExitCode);
615 }
616 static HandleTimeout(state) {
617 if (state.done) {
618 return;
619 }
620 if (!state.processClosed && state.processExited) {
621 const message = `The STDIO streams did not close within ${state.delay /
622 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`;
623 state._debug(message);
624 }
625 state._setResult();
626 }
627 }
50 +
51 +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
52 + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
53 + return new (P || (P = Promise))(function (resolve, reject) {
54 + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
55 + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
56 + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
57 + step((generator = generator.apply(thisArg, _arguments || [])).next());
58 + });
59 +};
60 +var __importStar = (this && this.__importStar) || function (mod) {
61 + if (mod && mod.__esModule) return mod;
62 + var result = {};
63 + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
64 + result["default"] = mod;
65 + return result;
66 +};
67 +Object.defineProperty(exports, "__esModule", { value: true });
68 +const os = __importStar(__webpack_require__(87));
69 +const events = __importStar(__webpack_require__(614));
70 +const child = __importStar(__webpack_require__(129));
71 +const path = __importStar(__webpack_require__(622));
72 +const io = __importStar(__webpack_require__(194));
73 +const ioUtil = __importStar(__webpack_require__(408));
74 +/* eslint-disable @typescript-eslint/unbound-method */
75 +const IS_WINDOWS = process.platform === 'win32';
76 +/*
77 + * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way.
78 + */
79 +class ToolRunner extends events.EventEmitter {
80 + constructor(toolPath, args, options) {
81 + super();
82 + if (!toolPath) {
83 + throw new Error("Parameter 'toolPath' cannot be null or empty.");
84 + }
85 + this.toolPath = toolPath;
86 + this.args = args || [];
87 + this.options = options || {};
88 + }
89 + _debug(message) {
90 + if (this.options.listeners && this.options.listeners.debug) {
91 + this.options.listeners.debug(message);
92 + }
93 + }
94 + _getCommandString(options, noPrefix) {
95 + const toolPath = this._getSpawnFileName();
96 + const args = this._getSpawnArgs(options);
97 + let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool
98 + if (IS_WINDOWS) {
99 + // Windows + cmd file
100 + if (this._isCmdFile()) {
101 + cmd += toolPath;
102 + for (const a of args) {
103 + cmd += ` ${a}`;
104 + }
105 + }
106 + // Windows + verbatim
107 + else if (options.windowsVerbatimArguments) {
108 + cmd += `"${toolPath}"`;
109 + for (const a of args) {
110 + cmd += ` ${a}`;
111 + }
112 + }
113 + // Windows (regular)
114 + else {
115 + cmd += this._windowsQuoteCmdArg(toolPath);
116 + for (const a of args) {
117 + cmd += ` ${this._windowsQuoteCmdArg(a)}`;
118 + }
119 + }
120 + }
121 + else {
122 + // OSX/Linux - this can likely be improved with some form of quoting.
123 + // creating processes on Unix is fundamentally different than Windows.
124 + // on Unix, execvp() takes an arg array.
125 + cmd += toolPath;
126 + for (const a of args) {
127 + cmd += ` ${a}`;
128 + }
129 + }
130 + return cmd;
131 + }
132 + _processLineBuffer(data, strBuffer, onLine) {
133 + try {
134 + let s = strBuffer + data.toString();
135 + let n = s.indexOf(os.EOL);
136 + while (n > -1) {
137 + const line = s.substring(0, n);
138 + onLine(line);
139 + // the rest of the string ...
140 + s = s.substring(n + os.EOL.length);
141 + n = s.indexOf(os.EOL);
142 + }
143 + strBuffer = s;
144 + }
145 + catch (err) {
146 + // streaming lines to console is best effort. Don't fail a build.
147 + this._debug(`error processing line. Failed with error ${err}`);
148 + }
149 + }
150 + _getSpawnFileName() {
151 + if (IS_WINDOWS) {
152 + if (this._isCmdFile()) {
153 + return process.env['COMSPEC'] || 'cmd.exe';
154 + }
155 + }
156 + return this.toolPath;
157 + }
158 + _getSpawnArgs(options) {
159 + if (IS_WINDOWS) {
160 + if (this._isCmdFile()) {
161 + let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`;
162 + for (const a of this.args) {
163 + argline += ' ';
164 + argline += options.windowsVerbatimArguments
165 + ? a
166 + : this._windowsQuoteCmdArg(a);
167 + }
168 + argline += '"';
169 + return [argline];
170 + }
171 + }
172 + return this.args;
173 + }
174 + _endsWith(str, end) {
175 + return str.endsWith(end);
176 + }
177 + _isCmdFile() {
178 + const upperToolPath = this.toolPath.toUpperCase();
179 + return (this._endsWith(upperToolPath, '.CMD') ||
180 + this._endsWith(upperToolPath, '.BAT'));
181 + }
182 + _windowsQuoteCmdArg(arg) {
183 + // for .exe, apply the normal quoting rules that libuv applies
184 + if (!this._isCmdFile()) {
185 + return this._uvQuoteCmdArg(arg);
186 + }
187 + // otherwise apply quoting rules specific to the cmd.exe command line parser.
188 + // the libuv rules are generic and are not designed specifically for cmd.exe
189 + // command line parser.
190 + //
191 + // for a detailed description of the cmd.exe command line parser, refer to
192 + // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912
193 + // need quotes for empty arg
194 + if (!arg) {
195 + return '""';
196 + }
197 + // determine whether the arg needs to be quoted
198 + const cmdSpecialChars = [
199 + ' ',
200 + '\t',
201 + '&',
202 + '(',
203 + ')',
204 + '[',
205 + ']',
206 + '{',
207 + '}',
208 + '^',
209 + '=',
210 + ';',
211 + '!',
212 + "'",
213 + '+',
214 + ',',
215 + '`',
216 + '~',
217 + '|',
218 + '<',
219 + '>',
220 + '"'
221 + ];
222 + let needsQuotes = false;
223 + for (const char of arg) {
224 + if (cmdSpecialChars.some(x => x === char)) {
225 + needsQuotes = true;
226 + break;
227 + }
228 + }
229 + // short-circuit if quotes not needed
230 + if (!needsQuotes) {
231 + return arg;
232 + }
233 + // the following quoting rules are very similar to the rules that by libuv applies.
234 + //
235 + // 1) wrap the string in quotes
236 + //
237 + // 2) double-up quotes - i.e. " => ""
238 + //
239 + // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately
240 + // doesn't work well with a cmd.exe command line.
241 + //
242 + // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app.
243 + // for example, the command line:
244 + // foo.exe "myarg:""my val"""
245 + // is parsed by a .NET console app into an arg array:
246 + // [ "myarg:\"my val\"" ]
247 + // which is the same end result when applying libuv quoting rules. although the actual
248 + // command line from libuv quoting rules would look like:
249 + // foo.exe "myarg:\"my val\""
250 + //
251 + // 3) double-up slashes that precede a quote,
252 + // e.g. hello \world => "hello \world"
253 + // hello\"world => "hello\\""world"
254 + // hello\\"world => "hello\\\\""world"
255 + // hello world\ => "hello world\\"
256 + //
257 + // technically this is not required for a cmd.exe command line, or the batch argument parser.
258 + // the reasons for including this as a .cmd quoting rule are:
259 + //
260 + // a) this is optimized for the scenario where the argument is passed from the .cmd file to an
261 + // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule.
262 + //
263 + // b) it's what we've been doing previously (by deferring to node default behavior) and we
264 + // haven't heard any complaints about that aspect.
265 + //
266 + // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be
267 + // escaped when used on the command line directly - even though within a .cmd file % can be escaped
268 + // by using %%.
269 + //
270 + // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts
271 + // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing.
272 + //
273 + // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would
274 + // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the
275 + // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args
276 + // to an external program.
277 + //
278 + // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file.
279 + // % can be escaped within a .cmd file.
280 + let reverse = '"';
281 + let quoteHit = true;
282 + for (let i = arg.length; i > 0; i--) {
283 + // walk the string in reverse
284 + reverse += arg[i - 1];
285 + if (quoteHit && arg[i - 1] === '\\') {
286 + reverse += '\\'; // double the slash
287 + }
288 + else if (arg[i - 1] === '"') {
289 + quoteHit = true;
290 + reverse += '"'; // double the quote
291 + }
292 + else {
293 + quoteHit = false;
294 + }
295 + }
296 + reverse += '"';
297 + return reverse
298 + .split('')
299 + .reverse()
300 + .join('');
301 + }
302 + _uvQuoteCmdArg(arg) {
303 + // Tool runner wraps child_process.spawn() and needs to apply the same quoting as
304 + // Node in certain cases where the undocumented spawn option windowsVerbatimArguments
305 + // is used.
306 + //
307 + // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV,
308 + // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details),
309 + // pasting copyright notice from Node within this function:
310 + //
311 + // Copyright Joyent, Inc. and other Node contributors. All rights reserved.
312 + //
313 + // Permission is hereby granted, free of charge, to any person obtaining a copy
314 + // of this software and associated documentation files (the "Software"), to
315 + // deal in the Software without restriction, including without limitation the
316 + // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
317 + // sell copies of the Software, and to permit persons to whom the Software is
318 + // furnished to do so, subject to the following conditions:
319 + //
320 + // The above copyright notice and this permission notice shall be included in
321 + // all copies or substantial portions of the Software.
322 + //
323 + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
324 + // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
325 + // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
326 + // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
327 + // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
328 + // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
329 + // IN THE SOFTWARE.
330 + if (!arg) {
331 + // Need double quotation for empty argument
332 + return '""';
333 + }
334 + if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) {
335 + // No quotation needed
336 + return arg;
337 + }
338 + if (!arg.includes('"') && !arg.includes('\\')) {
339 + // No embedded double quotes or backslashes, so I can just wrap
340 + // quote marks around the whole thing.
341 + return `"${arg}"`;
342 + }
343 + // Expected input/output:
344 + // input : hello"world
345 + // output: "hello\"world"
346 + // input : hello""world
347 + // output: "hello\"\"world"
348 + // input : hello\world
349 + // output: hello\world
350 + // input : hello\\world
351 + // output: hello\\world
352 + // input : hello\"world
353 + // output: "hello\\\"world"
354 + // input : hello\\"world
355 + // output: "hello\\\\\"world"
356 + // input : hello world\
357 + // output: "hello world\\" - note the comment in libuv actually reads "hello world\"
358 + // but it appears the comment is wrong, it should be "hello world\\"
359 + let reverse = '"';
360 + let quoteHit = true;
361 + for (let i = arg.length; i > 0; i--) {
362 + // walk the string in reverse
363 + reverse += arg[i - 1];
364 + if (quoteHit && arg[i - 1] === '\\') {
365 + reverse += '\\';
366 + }
367 + else if (arg[i - 1] === '"') {
368 + quoteHit = true;
369 + reverse += '\\';
370 + }
371 + else {
372 + quoteHit = false;
373 + }
374 + }
375 + reverse += '"';
376 + return reverse
377 + .split('')
378 + .reverse()
379 + .join('');
380 + }
381 + _cloneExecOptions(options) {
382 + options = options || {};
383 + const result = {
384 + cwd: options.cwd || process.cwd(),
385 + env: options.env || process.env,
386 + silent: options.silent || false,
387 + windowsVerbatimArguments: options.windowsVerbatimArguments || false,
388 + failOnStdErr: options.failOnStdErr || false,
389 + ignoreReturnCode: options.ignoreReturnCode || false,
390 + delay: options.delay || 10000
391 + };
392 + result.outStream = options.outStream || process.stdout;
393 + result.errStream = options.errStream || process.stderr;
394 + return result;
395 + }
396 + _getSpawnOptions(options, toolPath) {
397 + options = options || {};
398 + const result = {};
399 + result.cwd = options.cwd;
400 + result.env = options.env;
401 + result['windowsVerbatimArguments'] =
402 + options.windowsVerbatimArguments || this._isCmdFile();
403 + if (options.windowsVerbatimArguments) {
404 + result.argv0 = `"${toolPath}"`;
405 + }
406 + return result;
407 + }
408 + /**
409 + * Exec a tool.
410 + * Output will be streamed to the live console.
411 + * Returns promise with return code
412 + *
413 + * @param tool path to tool to exec
414 + * @param options optional exec options. See ExecOptions
415 + * @returns number
416 + */
417 + exec() {
418 + return __awaiter(this, void 0, void 0, function* () {
419 + // root the tool path if it is unrooted and contains relative pathing
420 + if (!ioUtil.isRooted(this.toolPath) &&
421 + (this.toolPath.includes('/') ||
422 + (IS_WINDOWS && this.toolPath.includes('\\')))) {
423 + // prefer options.cwd if it is specified, however options.cwd may also need to be rooted
424 + this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath);
425 + }
426 + // if the tool is only a file name, then resolve it from the PATH
427 + // otherwise verify it exists (add extension on Windows if necessary)
428 + this.toolPath = yield io.which(this.toolPath, true);
429 + return new Promise((resolve, reject) => {
430 + this._debug(`exec tool: ${this.toolPath}`);
431 + this._debug('arguments:');
432 + for (const arg of this.args) {
433 + this._debug(` ${arg}`);
434 + }
435 + const optionsNonNull = this._cloneExecOptions(this.options);
436 + if (!optionsNonNull.silent && optionsNonNull.outStream) {
437 + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL);
438 + }
439 + const state = new ExecState(optionsNonNull, this.toolPath);
440 + state.on('debug', (message) => {
441 + this._debug(message);
442 + });
443 + const fileName = this._getSpawnFileName();
444 + const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName));
445 + const stdbuffer = '';
446 + if (cp.stdout) {
447 + cp.stdout.on('data', (data) => {
448 + if (this.options.listeners && this.options.listeners.stdout) {
449 + this.options.listeners.stdout(data);
450 + }
451 + if (!optionsNonNull.silent && optionsNonNull.outStream) {
452 + optionsNonNull.outStream.write(data);
453 + }
454 + this._processLineBuffer(data, stdbuffer, (line) => {
455 + if (this.options.listeners && this.options.listeners.stdline) {
456 + this.options.listeners.stdline(line);
457 + }
458 + });
459 + });
460 + }
461 + const errbuffer = '';
462 + if (cp.stderr) {
463 + cp.stderr.on('data', (data) => {
464 + state.processStderr = true;
465 + if (this.options.listeners && this.options.listeners.stderr) {
466 + this.options.listeners.stderr(data);
467 + }
468 + if (!optionsNonNull.silent &&
469 + optionsNonNull.errStream &&
470 + optionsNonNull.outStream) {
471 + const s = optionsNonNull.failOnStdErr
472 + ? optionsNonNull.errStream
473 + : optionsNonNull.outStream;
474 + s.write(data);
475 + }
476 + this._processLineBuffer(data, errbuffer, (line) => {
477 + if (this.options.listeners && this.options.listeners.errline) {
478 + this.options.listeners.errline(line);
479 + }
480 + });
481 + });
482 + }
483 + cp.on('error', (err) => {
484 + state.processError = err.message;
485 + state.processExited = true;
486 + state.processClosed = true;
487 + state.CheckComplete();
488 + });
489 + cp.on('exit', (code) => {
490 + state.processExitCode = code;
491 + state.processExited = true;
492 + this._debug(`Exit code ${code} received from tool '${this.toolPath}'`);
493 + state.CheckComplete();
494 + });
495 + cp.on('close', (code) => {
496 + state.processExitCode = code;
497 + state.processExited = true;
498 + state.processClosed = true;
499 + this._debug(`STDIO streams have closed for tool '${this.toolPath}'`);
500 + state.CheckComplete();
501 + });
502 + state.on('done', (error, exitCode) => {
503 + if (stdbuffer.length > 0) {
504 + this.emit('stdline', stdbuffer);
505 + }
506 + if (errbuffer.length > 0) {
507 + this.emit('errline', errbuffer);
508 + }
509 + cp.removeAllListeners();
510 + if (error) {
511 + reject(error);
512 + }
513 + else {
514 + resolve(exitCode);
515 + }
516 + });
517 + if (this.options.input) {
518 + if (!cp.stdin) {
519 + throw new Error('child process missing stdin');
520 + }
521 + cp.stdin.end(this.options.input);
522 + }
523 + });
524 + });
525 + }
526 +}
527 +exports.ToolRunner = ToolRunner;
528 +/**
529 + * Convert an arg string to an array of args. Handles escaping
530 + *
531 + * @param argString string of arguments
532 + * @returns string[] array of arguments
533 + */
534 +function argStringToArray(argString) {
535 + const args = [];
536 + let inQuotes = false;
537 + let escaped = false;
538 + let arg = '';
539 + function append(c) {
540 + // we only escape double quotes.
541 + if (escaped && c !== '"') {
542 + arg += '\\';
543 + }
544 + arg += c;
545 + escaped = false;
546 + }
547 + for (let i = 0; i < argString.length; i++) {
548 + const c = argString.charAt(i);
549 + if (c === '"') {
550 + if (!escaped) {
551 + inQuotes = !inQuotes;
552 + }
553 + else {
554 + append(c);
555 + }
556 + continue;
557 + }
558 + if (c === '\\' && escaped) {
559 + append(c);
560 + continue;
561 + }
562 + if (c === '\\' && inQuotes) {
563 + escaped = true;
564 + continue;
565 + }
566 + if (c === ' ' && !inQuotes) {
567 + if (arg.length > 0) {
568 + args.push(arg);
569 + arg = '';
570 + }
571 + continue;
572 + }
573 + append(c);
574 + }
575 + if (arg.length > 0) {
576 + args.push(arg.trim());
577 + }
578 + return args;
579 +}
580 +exports.argStringToArray = argStringToArray;
581 +class ExecState extends events.EventEmitter {
582 + constructor(options, toolPath) {
583 + super();
584 + this.processClosed = false; // tracks whether the process has exited and stdio is closed
585 + this.processError = '';
586 + this.processExitCode = 0;
587 + this.processExited = false; // tracks whether the process has exited
588 + this.processStderr = false; // tracks whether stderr was written to
589 + this.delay = 10000; // 10 seconds
590 + this.done = false;
591 + this.timeout = null;
592 + if (!toolPath) {
593 + throw new Error('toolPath must not be empty');
594 + }
595 + this.options = options;
596 + this.toolPath = toolPath;
597 + if (options.delay) {
598 + this.delay = options.delay;
599 + }
600 + }
601 + CheckComplete() {
602 + if (this.done) {
603 + return;
604 + }
605 + if (this.processClosed) {
606 + this._setResult();
607 + }
608 + else if (this.processExited) {
609 + this.timeout = setTimeout(ExecState.HandleTimeout, this.delay, this);
610 + }
611 + }
612 + _debug(message) {
613 + this.emit('debug', message);
614 + }
615 + _setResult() {
616 + // determine whether there is an error
617 + let error;
618 + if (this.processExited) {
619 + if (this.processError) {
620 + error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`);
621 + }
622 + else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) {
623 + error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`);
624 + }
625 + else if (this.processStderr && this.options.failOnStdErr) {
626 + error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`);
627 + }
628 + }
629 + // clear the timeout
630 + if (this.timeout) {
631 + clearTimeout(this.timeout);
632 + this.timeout = null;
633 + }
634 + this.done = true;
635 + this.emit('done', error, this.processExitCode);
636 + }
637 + static HandleTimeout(state) {
638 + if (state.done) {
639 + return;
640 + }
641 + if (!state.processClosed && state.processExited) {
642 + const message = `The STDIO streams did not close within ${state.delay /
643 + 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`;
644 + state._debug(message);
645 + }
646 + state._setResult();
647 + }
648 +}
628 649 //# sourceMappingURL=toolrunner.js.map
629 650
630 651 /***/ }),
@@ -643,6 +664,303 @@ module.exports = require("child_process");
643 664
644 665 /***/ }),
645 666
667 +/***/ 194:
668 +/***/ (function(__unusedmodule, exports, __webpack_require__) {
669 +
670 +"use strict";
671 +
672 +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
673 + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
674 + return new (P || (P = Promise))(function (resolve, reject) {
675 + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
676 + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
677 + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
678 + step((generator = generator.apply(thisArg, _arguments || [])).next());
679 + });
680 +};
681 +Object.defineProperty(exports, "__esModule", { value: true });
682 +const childProcess = __webpack_require__(129);
683 +const path = __webpack_require__(622);
684 +const util_1 = __webpack_require__(669);
685 +const ioUtil = __webpack_require__(408);
686 +const exec = util_1.promisify(childProcess.exec);
687 +/**
688 + * Copies a file or folder.
689 + * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js
690 + *
691 + * @param source source path
692 + * @param dest destination path
693 + * @param options optional. See CopyOptions.
694 + */
695 +function cp(source, dest, options = {}) {
696 + return __awaiter(this, void 0, void 0, function* () {
697 + const { force, recursive } = readCopyOptions(options);
698 + const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null;
699 + // Dest is an existing file, but not forcing
700 + if (destStat && destStat.isFile() && !force) {
701 + return;
702 + }
703 + // If dest is an existing directory, should copy inside.
704 + const newDest = destStat && destStat.isDirectory()
705 + ? path.join(dest, path.basename(source))
706 + : dest;
707 + if (!(yield ioUtil.exists(source))) {
708 + throw new Error(`no such file or directory: ${source}`);
709 + }
710 + const sourceStat = yield ioUtil.stat(source);
711 + if (sourceStat.isDirectory()) {
712 + if (!recursive) {
713 + throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`);
714 + }
715 + else {
716 + yield cpDirRecursive(source, newDest, 0, force);
717 + }
718 + }
719 + else {
720 + if (path.relative(source, newDest) === '') {
721 + // a file cannot be copied to itself
722 + throw new Error(`'${newDest}' and '${source}' are the same file`);
723 + }
724 + yield copyFile(source, newDest, force);
725 + }
726 + });
727 +}
728 +exports.cp = cp;
729 +/**
730 + * Moves a path.
731 + *
732 + * @param source source path
733 + * @param dest destination path
734 + * @param options optional. See MoveOptions.
735 + */
736 +function mv(source, dest, options = {}) {
737 + return __awaiter(this, void 0, void 0, function* () {
738 + if (yield ioUtil.exists(dest)) {
739 + let destExists = true;
740 + if (yield ioUtil.isDirectory(dest)) {
741 + // If dest is directory copy src into dest
742 + dest = path.join(dest, path.basename(source));
743 + destExists = yield ioUtil.exists(dest);
744 + }
745 + if (destExists) {
746 + if (options.force == null || options.force) {
747 + yield rmRF(dest);
748 + }
749 + else {
750 + throw new Error('Destination already exists');
751 + }
752 + }
753 + }
754 + yield mkdirP(path.dirname(dest));
755 + yield ioUtil.rename(source, dest);
756 + });
757 +}
758 +exports.mv = mv;
759 +/**
760 + * Remove a path recursively with force
761 + *
762 + * @param inputPath path to remove
763 + */
764 +function rmRF(inputPath) {
765 + return __awaiter(this, void 0, void 0, function* () {
766 + if (ioUtil.IS_WINDOWS) {
767 + // Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another
768 + // program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del.
769 + try {
770 + if (yield ioUtil.isDirectory(inputPath, true)) {
771 + yield exec(`rd /s /q "${inputPath}"`);
772 + }
773 + else {
774 + yield exec(`del /f /a "${inputPath}"`);
775 + }
776 + }
777 + catch (err) {
778 + // if you try to delete a file that doesn't exist, desired result is achieved
779 + // other errors are valid
780 + if (err.code !== 'ENOENT')
781 + throw err;
782 + }
783 + // Shelling out fails to remove a symlink folder with missing source, this unlink catches that
784 + try {
785 + yield ioUtil.unlink(inputPath);
786 + }
787 + catch (err) {
788 + // if you try to delete a file that doesn't exist, desired result is achieved
789 + // other errors are valid
790 + if (err.code !== 'ENOENT')
791 + throw err;
792 + }
793 + }
794 + else {
795 + let isDir = false;
796 + try {
797 + isDir = yield ioUtil.isDirectory(inputPath);
798 + }
799 + catch (err) {
800 + // if you try to delete a file that doesn't exist, desired result is achieved
801 + // other errors are valid
802 + if (err.code !== 'ENOENT')
803 + throw err;
804 + return;
805 + }
806 + if (isDir) {
807 + yield exec(`rm -rf "${inputPath}"`);
808 + }
809 + else {
810 + yield ioUtil.unlink(inputPath);
811 + }
812 + }
813 + });
814 +}
815 +exports.rmRF = rmRF;
816 +/**
817 + * Make a directory. Creates the full path with folders in between
818 + * Will throw if it fails
819 + *
820 + * @param fsPath path to create
821 + * @returns Promise<void>
822 + */
823 +function mkdirP(fsPath) {
824 + return __awaiter(this, void 0, void 0, function* () {
825 + yield ioUtil.mkdirP(fsPath);
826 + });
827 +}
828 +exports.mkdirP = mkdirP;
829 +/**
830 + * Returns path of a tool had the tool actually been invoked. Resolves via paths.
831 + * If you check and the tool does not exist, it will throw.
832 + *
833 + * @param tool name of the tool
834 + * @param check whether to check if tool exists
835 + * @returns Promise<string> path to tool
836 + */
837 +function which(tool, check) {
838 + return __awaiter(this, void 0, void 0, function* () {
839 + if (!tool) {
840 + throw new Error("parameter 'tool' is required");
841 + }
842 + // recursive when check=true
843 + if (check) {
844 + const result = yield which(tool, false);
845 + if (!result) {
846 + if (ioUtil.IS_WINDOWS) {
847 + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`);
848 + }
849 + else {
850 + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`);
851 + }
852 + }
853 + }
854 + try {
855 + // build the list of extensions to try
856 + const extensions = [];
857 + if (ioUtil.IS_WINDOWS && process.env.PATHEXT) {
858 + for (const extension of process.env.PATHEXT.split(path.delimiter)) {
859 + if (extension) {
860 + extensions.push(extension);
861 + }
862 + }
863 + }
864 + // if it's rooted, return it if exists. otherwise return empty.
865 + if (ioUtil.isRooted(tool)) {
866 + const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions);
867 + if (filePath) {
868 + return filePath;
869 + }
870 + return '';
871 + }
872 + // if any path separators, return empty
873 + if (tool.includes('/') || (ioUtil.IS_WINDOWS && tool.includes('\\'))) {
874 + return '';
875 + }
876 + // build the list of directories
877 + //
878 + // Note, technically "where" checks the current directory on Windows. From a toolkit perspective,
879 + // it feels like we should not do this. Checking the current directory seems like more of a use
880 + // case of a shell, and the which() function exposed by the toolkit should strive for consistency
881 + // across platforms.
882 + const directories = [];
883 + if (process.env.PATH) {
884 + for (const p of process.env.PATH.split(path.delimiter)) {
885 + if (p) {
886 + directories.push(p);
887 + }
888 + }
889 + }
890 + // return the first match
891 + for (const directory of directories) {
892 + const filePath = yield ioUtil.tryGetExecutablePath(directory + path.sep + tool, extensions);
893 + if (filePath) {
894 + return filePath;
895 + }
896 + }
897 + return '';
898 + }
899 + catch (err) {
900 + throw new Error(`which failed with message ${err.message}`);
901 + }
902 + });
903 +}
904 +exports.which = which;
905 +function readCopyOptions(options) {
906 + const force = options.force == null ? true : options.force;
907 + const recursive = Boolean(options.recursive);
908 + return { force, recursive };
909 +}
910 +function cpDirRecursive(sourceDir, destDir, currentDepth, force) {
911 + return __awaiter(this, void 0, void 0, function* () {
912 + // Ensure there is not a run away recursive copy
913 + if (currentDepth >= 255)
914 + return;
915 + currentDepth++;
916 + yield mkdirP(destDir);
917 + const files = yield ioUtil.readdir(sourceDir);
918 + for (const fileName of files) {
919 + const srcFile = `${sourceDir}/${fileName}`;
920 + const destFile = `${destDir}/${fileName}`;
921 + const srcFileStat = yield ioUtil.lstat(srcFile);
922 + if (srcFileStat.isDirectory()) {
923 + // Recurse
924 + yield cpDirRecursive(srcFile, destFile, currentDepth, force);
925 + }
926 + else {
927 + yield copyFile(srcFile, destFile, force);
928 + }
929 + }
930 + // Change the mode for the newly created directory
931 + yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode);
932 + });
933 +}
934 +// Buffered file copy
935 +function copyFile(srcFile, destFile, force) {
936 + return __awaiter(this, void 0, void 0, function* () {
937 + if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) {
938 + // unlink/re-link it
939 + try {
940 + yield ioUtil.lstat(destFile);
941 + yield ioUtil.unlink(destFile);
942 + }
943 + catch (e) {
944 + // Try to override file permission
945 + if (e.code === 'EPERM') {
946 + yield ioUtil.chmod(destFile, '0666');
947 + yield ioUtil.unlink(destFile);
948 + }
949 + // other errors = it doesn't exist, no work to do
950 + }
951 + // Copy over symlink
952 + const symlinkFull = yield ioUtil.readlink(srcFile);
953 + yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null);
954 + }
955 + else if (!(yield ioUtil.exists(destFile)) || force) {
956 + yield ioUtil.copyFile(srcFile, destFile);
957 + }
958 + });
959 +}
960 +//# sourceMappingURL=io.js.map
961 +
962 +/***/ }),
963 +
646 964 /***/ 211:
647 965 /***/ (function(module) {
648 966
@@ -2251,77 +2569,312 @@ function coerce (version, options) {
2251 2569 }
2252 2570
2253 2571
2572 +/***/ }),
2573 +
2574 +/***/ 357:
2575 +/***/ (function(module) {
2576 +
2577 +module.exports = require("assert");
2578 +
2579 +/***/ }),
2580 +
2581 +/***/ 408:
2582 +/***/ (function(__unusedmodule, exports, __webpack_require__) {
2583 +
2584 +"use strict";
2585 +
2586 +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2587 + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
2588 + return new (P || (P = Promise))(function (resolve, reject) {
2589 + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
2590 + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
2591 + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
2592 + step((generator = generator.apply(thisArg, _arguments || [])).next());
2593 + });
2594 +};
2595 +var _a;
2596 +Object.defineProperty(exports, "__esModule", { value: true });
2597 +const assert_1 = __webpack_require__(357);
2598 +const fs = __webpack_require__(747);
2599 +const path = __webpack_require__(622);
2600 +_a = fs.promises, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink;
2601 +exports.IS_WINDOWS = process.platform === 'win32';
2602 +function exists(fsPath) {
2603 + return __awaiter(this, void 0, void 0, function* () {
2604 + try {
2605 + yield exports.stat(fsPath);
2606 + }
2607 + catch (err) {
2608 + if (err.code === 'ENOENT') {
2609 + return false;
2610 + }
2611 + throw err;
2612 + }
2613 + return true;
2614 + });
2615 +}
2616 +exports.exists = exists;
2617 +function isDirectory(fsPath, useStat = false) {
2618 + return __awaiter(this, void 0, void 0, function* () {
2619 + const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath);
2620 + return stats.isDirectory();
2621 + });
2622 +}
2623 +exports.isDirectory = isDirectory;
2624 +/**
2625 + * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like:
2626 + * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases).
2627 + */
2628 +function isRooted(p) {
2629 + p = normalizeSeparators(p);
2630 + if (!p) {
2631 + throw new Error('isRooted() parameter "p" cannot be empty');
2632 + }
2633 + if (exports.IS_WINDOWS) {
2634 + return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello
2635 + ); // e.g. C: or C:\hello
2636 + }
2637 + return p.startsWith('/');
2638 +}
2639 +exports.isRooted = isRooted;
2640 +/**
2641 + * Recursively create a directory at `fsPath`.
2642 + *
2643 + * This implementation is optimistic, meaning it attempts to create the full
2644 + * path first, and backs up the path stack from there.
2645 + *
2646 + * @param fsPath The path to create
2647 + * @param maxDepth The maximum recursion depth
2648 + * @param depth The current recursion depth
2649 + */
2650 +function mkdirP(fsPath, maxDepth = 1000, depth = 1) {
2651 + return __awaiter(this, void 0, void 0, function* () {
2652 + assert_1.ok(fsPath, 'a path argument must be provided');
2653 + fsPath = path.resolve(fsPath);
2654 + if (depth >= maxDepth)
2655 + return exports.mkdir(fsPath);
2656 + try {
2657 + yield exports.mkdir(fsPath);
2658 + return;
2659 + }
2660 + catch (err) {
2661 + switch (err.code) {
2662 + case 'ENOENT': {
2663 + yield mkdirP(path.dirname(fsPath), maxDepth, depth + 1);
2664 + yield exports.mkdir(fsPath);
2665 + return;
2666 + }
2667 + default: {
2668 + let stats;
2669 + try {
2670 + stats = yield exports.stat(fsPath);
2671 + }
2672 + catch (err2) {
2673 + throw err;
2674 + }
2675 + if (!stats.isDirectory())
2676 + throw err;
2677 + }
2678 + }
2679 + }
2680 + });
2681 +}
2682 +exports.mkdirP = mkdirP;
2683 +/**
2684 + * Best effort attempt to determine whether a file exists and is executable.
2685 + * @param filePath file path to check
2686 + * @param extensions additional file extensions to try
2687 + * @return if file exists and is executable, returns the file path. otherwise empty string.
2688 + */
2689 +function tryGetExecutablePath(filePath, extensions) {
2690 + return __awaiter(this, void 0, void 0, function* () {
2691 + let stats = undefined;
2692 + try {
2693 + // test file exists
2694 + stats = yield exports.stat(filePath);
2695 + }
2696 + catch (err) {
2697 + if (err.code !== 'ENOENT') {
2698 + // eslint-disable-next-line no-console
2699 + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);
2700 + }
2701 + }
2702 + if (stats && stats.isFile()) {
2703 + if (exports.IS_WINDOWS) {
2704 + // on Windows, test for valid extension
2705 + const upperExt = path.extname(filePath).toUpperCase();
2706 + if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) {
2707 + return filePath;
2708 + }
2709 + }
2710 + else {
2711 + if (isUnixExecutable(stats)) {
2712 + return filePath;
2713 + }
2714 + }
2715 + }
2716 + // try each extension
2717 + const originalFilePath = filePath;
2718 + for (const extension of extensions) {
2719 + filePath = originalFilePath + extension;
2720 + stats = undefined;
2721 + try {
2722 + stats = yield exports.stat(filePath);
2723 + }
2724 + catch (err) {
2725 + if (err.code !== 'ENOENT') {
2726 + // eslint-disable-next-line no-console
2727 + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`);
2728 + }
2729 + }
2730 + if (stats && stats.isFile()) {
2731 + if (exports.IS_WINDOWS) {
2732 + // preserve the case of the actual file (since an extension was appended)
2733 + try {
2734 + const directory = path.dirname(filePath);
2735 + const upperName = path.basename(filePath).toUpperCase();
2736 + for (const actualName of yield exports.readdir(directory)) {
2737 + if (upperName === actualName.toUpperCase()) {
2738 + filePath = path.join(directory, actualName);
2739 + break;
2740 + }
2741 + }
2742 + }
2743 + catch (err) {
2744 + // eslint-disable-next-line no-console
2745 + console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`);
2746 + }
2747 + return filePath;
2748 + }
2749 + else {
2750 + if (isUnixExecutable(stats)) {
2751 + return filePath;
2752 + }
2753 + }
2754 + }
2755 + }
2756 + return '';
2757 + });
2758 +}
2759 +exports.tryGetExecutablePath = tryGetExecutablePath;
2760 +function normalizeSeparators(p) {
2761 + p = p || '';
2762 + if (exports.IS_WINDOWS) {
2763 + // convert slashes on Windows
2764 + p = p.replace(/\//g, '\\');
2765 + // remove redundant slashes
2766 + return p.replace(/\\\\+/g, '\\');
2767 + }
2768 + // remove redundant slashes
2769 + return p.replace(/\/\/+/g, '/');
2770 +}
2771 +// on Mac/Linux, test the execute bit
2772 +// R W X R W X R W X
2773 +// 256 128 64 32 16 8 4 2 1
2774 +function isUnixExecutable(stats) {
2775 + return ((stats.mode & 1) > 0 ||
2776 + ((stats.mode & 8) > 0 && stats.gid === process.getgid()) ||
2777 + ((stats.mode & 64) > 0 && stats.uid === process.getuid()));
2778 +}
2779 +//# sourceMappingURL=io-util.js.map
2780 +
2254 2781 /***/ }),
2255 2782
2256 2783 /***/ 431:
2257 2784 /***/ (function(__unusedmodule, exports, __webpack_require__) {
2258 2785
2259 2786 "use strict";
2260
2261 Object.defineProperty(exports, "__esModule", { value: true });
2262 const os = __webpack_require__(87);
2263 /**
2264 * Commands
2265 *
2266 * Command Format:
2267 * ##[name key=value;key=value]message
2268 *
2269 * Examples:
2270 * ##[warning]This is the user warning message
2271 * ##[set-secret name=mypassword]definatelyNotAPassword!
2272 */
2273 function issueCommand(command, properties, message) {
2274 const cmd = new Command(command, properties, message);
2275 process.stdout.write(cmd.toString() + os.EOL);
2276 }
2277 exports.issueCommand = issueCommand;
2278 function issue(name, message) {
2279 issueCommand(name, {}, message);
2280 }
2281 exports.issue = issue;
2282 const CMD_PREFIX = '##[';
2283 class Command {
2284 constructor(command, properties, message) {
2285 if (!command) {
2286 command = 'missing.command';
2287 }
2288 this.command = command;
2289 this.properties = properties;
2290 this.message = message;
2291 }
2292 toString() {
2293 let cmdStr = CMD_PREFIX + this.command;
2294 if (this.properties && Object.keys(this.properties).length > 0) {
2295 cmdStr += ' ';
2296 for (const key in this.properties) {
2297 if (this.properties.hasOwnProperty(key)) {
2298 const val = this.properties[key];
2299 if (val) {
2300 // safely append the val - avoid blowing up when attempting to
2301 // call .replace() if message is not a string for some reason
2302 cmdStr += `${key}=${escape(`${val || ''}`)};`;
2303 }
2304 }
2305 }
2306 }
2307 cmdStr += ']';
2308 // safely append the message - avoid blowing up when attempting to
2309 // call .replace() if message is not a string for some reason
2310 const message = `${this.message || ''}`;
2311 cmdStr += escapeData(message);
2312 return cmdStr;
2313 }
2314 }
2315 function escapeData(s) {
2316 return s.replace(/\r/g, '%0D').replace(/\n/g, '%0A');
2317 }
2318 function escape(s) {
2319 return s
2320 .replace(/\r/g, '%0D')
2321 .replace(/\n/g, '%0A')
2322 .replace(/]/g, '%5D')
2323 .replace(/;/g, '%3B');
2324 }
2787 +
2788 +var __importStar = (this && this.__importStar) || function (mod) {
2789 + if (mod && mod.__esModule) return mod;
2790 + var result = {};
2791 + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
2792 + result["default"] = mod;
2793 + return result;
2794 +};
2795 +Object.defineProperty(exports, "__esModule", { value: true });
2796 +const os = __importStar(__webpack_require__(87));
2797 +/**
2798 + * Commands
2799 + *
2800 + * Command Format:
2801 + * ::name key=value,key=value::message
2802 + *
2803 + * Examples:
2804 + * ::warning::This is the message
2805 + * ::set-env name=MY_VAR::some value
2806 + */
2807 +function issueCommand(command, properties, message) {
2808 + const cmd = new Command(command, properties, message);
2809 + process.stdout.write(cmd.toString() + os.EOL);
2810 +}
2811 +exports.issueCommand = issueCommand;
2812 +function issue(name, message = '') {
2813 + issueCommand(name, {}, message);
2814 +}
2815 +exports.issue = issue;
2816 +const CMD_STRING = '::';
2817 +class Command {
2818 + constructor(command, properties, message) {
2819 + if (!command) {
2820 + command = 'missing.command';
2821 + }
2822 + this.command = command;
2823 + this.properties = properties;
2824 + this.message = message;
2825 + }
2826 + toString() {
2827 + let cmdStr = CMD_STRING + this.command;
2828 + if (this.properties && Object.keys(this.properties).length > 0) {
2829 + cmdStr += ' ';
2830 + let first = true;
2831 + for (const key in this.properties) {
2832 + if (this.properties.hasOwnProperty(key)) {
2833 + const val = this.properties[key];
2834 + if (val) {
2835 + if (first) {
2836 + first = false;
2837 + }
2838 + else {
2839 + cmdStr += ',';
2840 + }
2841 + cmdStr += `${key}=${escapeProperty(val)}`;
2842 + }
2843 + }
2844 + }
2845 + }
2846 + cmdStr += `${CMD_STRING}${escapeData(this.message)}`;
2847 + return cmdStr;
2848 + }
2849 +}
2850 +/**
2851 + * Sanitizes an input into a string so it can be passed into issueCommand safely
2852 + * @param input input to sanitize into a string
2853 + */
2854 +function toCommandValue(input) {
2855 + if (input === null || input === undefined) {
2856 + return '';
2857 + }
2858 + else if (typeof input === 'string' || input instanceof String) {
2859 + return input;
2860 + }
2861 + return JSON.stringify(input);
2862 +}
2863 +exports.toCommandValue = toCommandValue;
2864 +function escapeData(s) {
2865 + return toCommandValue(s)
2866 + .replace(/%/g, '%25')
2867 + .replace(/\r/g, '%0D')
2868 + .replace(/\n/g, '%0A');
2869 +}
2870 +function escapeProperty(s) {
2871 + return toCommandValue(s)
2872 + .replace(/%/g, '%25')
2873 + .replace(/\r/g, '%0D')
2874 + .replace(/\n/g, '%0A')
2875 + .replace(/:/g, '%3A')
2876 + .replace(/,/g, '%2C');
2877 +}
2325 2878 //# sourceMappingURL=command.js.map
2326 2879
2327 2880 /***/ }),
@@ -2371,121 +2924,227 @@ async function installOTP(version) {
2371 2924 /***/ (function(__unusedmodule, exports, __webpack_require__) {
2372 2925
2373 2926 "use strict";
2374
2375 Object.defineProperty(exports, "__esModule", { value: true });
2376 const command_1 = __webpack_require__(431);
2377 const path = __webpack_require__(622);
2378 /**
2379 * The code to exit an action
2380 */
2381 var ExitCode;
2382 (function (ExitCode) {
2383 /**
2384 * A code indicating that the action was successful
2385 */
2386 ExitCode[ExitCode["Success"] = 0] = "Success";
2387 /**
2388 * A code indicating that the action was a failure
2389 */
2390 ExitCode[ExitCode["Failure"] = 1] = "Failure";
2391 })(ExitCode = exports.ExitCode || (exports.ExitCode = {}));
2392 //-----------------------------------------------------------------------
2393 // Variables
2394 //-----------------------------------------------------------------------
2395 /**
2396 * sets env variable for this action and future actions in the job
2397 * @param name the name of the variable to set
2398 * @param val the value of the variable
2399 */
2400 function exportVariable(name, val) {
2401 process.env[name] = val;
2402 command_1.issueCommand('set-env', { name }, val);
2403 }
2404 exports.exportVariable = exportVariable;
2405 /**
2406 * exports the variable and registers a secret which will get masked from logs
2407 * @param name the name of the variable to set
2408 * @param val value of the secret
2409 */
2410 function exportSecret(name, val) {
2411 exportVariable(name, val);
2412 command_1.issueCommand('set-secret', {}, val);
2413 }
2414 exports.exportSecret = exportSecret;
2415 /**
2416 * Prepends inputPath to the PATH (for this action and future actions)
2417 * @param inputPath
2418 */
2419 function addPath(inputPath) {
2420 command_1.issueCommand('add-path', {}, inputPath);
2421 process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;
2422 }
2423 exports.addPath = addPath;
2424 /**
2425 * Gets the value of an input. The value is also trimmed.
2426 *
2427 * @param name name of the input to get
2428 * @param options optional. See InputOptions.
2429 * @returns string
2430 */
2431 function getInput(name, options) {
2432 const val = process.env[`INPUT_${name.replace(' ', '_').toUpperCase()}`] || '';
2433 if (options && options.required && !val) {
2434 throw new Error(`Input required and not supplied: ${name}`);
2435 }
2436 return val.trim();
2437 }
2438 exports.getInput = getInput;
2439 /**
2440 * Sets the value of an output.
2441 *
2442 * @param name name of the output to set
2443 * @param value value to store
2444 */
2445 function setOutput(name, value) {
2446 command_1.issueCommand('set-output', { name }, value);
2447 }
2448 exports.setOutput = setOutput;
2449 //-----------------------------------------------------------------------
2450 // Results
2451 //-----------------------------------------------------------------------
2452 /**
2453 * Sets the action status to failed.
2454 * When the action exits it will be with an exit code of 1
2455 * @param message add error issue message
2456 */
2457 function setFailed(message) {
2458 process.exitCode = ExitCode.Failure;
2459 error(message);
2460 }
2461 exports.setFailed = setFailed;
2462 //-----------------------------------------------------------------------
2463 // Logging Commands
2464 //-----------------------------------------------------------------------
2465 /**
2466 * Writes debug message to user log
2467 * @param message debug message
2468 */
2469 function debug(message) {
2470 command_1.issueCommand('debug', {}, message);
2471 }
2472 exports.debug = debug;
2473 /**
2474 * Adds an error issue
2475 * @param message error issue message
2476 */
2477 function error(message) {
2478 command_1.issue('error', message);
2479 }
2480 exports.error = error;
2481 /**
2482 * Adds an warning issue
2483 * @param message warning issue message
2484 */
2485 function warning(message) {
2486 command_1.issue('warning', message);
2487 }
2488 exports.warning = warning;
2927 +
2928 +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2929 + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
2930 + return new (P || (P = Promise))(function (resolve, reject) {
2931 + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
2932 + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
2933 + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
2934 + step((generator = generator.apply(thisArg, _arguments || [])).next());
2935 + });
2936 +};
2937 +var __importStar = (this && this.__importStar) || function (mod) {
2938 + if (mod && mod.__esModule) return mod;
2939 + var result = {};
2940 + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
2941 + result["default"] = mod;
2942 + return result;
2943 +};
2944 +Object.defineProperty(exports, "__esModule", { value: true });
2945 +const command_1 = __webpack_require__(431);
2946 +const os = __importStar(__webpack_require__(87));
2947 +const path = __importStar(__webpack_require__(622));
2948 +/**
2949 + * The code to exit an action
2950 + */
2951 +var ExitCode;
2952 +(function (ExitCode) {
2953 + /**
2954 + * A code indicating that the action was successful
2955 + */
2956 + ExitCode[ExitCode["Success"] = 0] = "Success";
2957 + /**
2958 + * A code indicating that the action was a failure
2959 + */
2960 + ExitCode[ExitCode["Failure"] = 1] = "Failure";
2961 +})(ExitCode = exports.ExitCode || (exports.ExitCode = {}));
2962 +//-----------------------------------------------------------------------
2963 +// Variables
2964 +//-----------------------------------------------------------------------
2965 +/**
2966 + * Sets env variable for this action and future actions in the job
2967 + * @param name the name of the variable to set
2968 + * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify
2969 + */
2970 +// eslint-disable-next-line @typescript-eslint/no-explicit-any
2971 +function exportVariable(name, val) {
2972 + const convertedVal = command_1.toCommandValue(val);
2973 + process.env[name] = convertedVal;
2974 + command_1.issueCommand('set-env', { name }, convertedVal);
2975 +}
2976 +exports.exportVariable = exportVariable;
2977 +/**
2978 + * Registers a secret which will get masked from logs
2979 + * @param secret value of the secret
2980 + */
2981 +function setSecret(secret) {
2982 + command_1.issueCommand('add-mask', {}, secret);
2983 +}
2984 +exports.setSecret = setSecret;
2985 +/**
2986 + * Prepends inputPath to the PATH (for this action and future actions)
2987 + * @param inputPath
2988 + */
2989 +function addPath(inputPath) {
2990 + command_1.issueCommand('add-path', {}, inputPath);
2991 + process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;
2992 +}
2993 +exports.addPath = addPath;
2994 +/**
2995 + * Gets the value of an input. The value is also trimmed.
2996 + *
2997 + * @param name name of the input to get
2998 + * @param options optional. See InputOptions.
2999 + * @returns string
3000 + */
3001 +function getInput(name, options) {
3002 + const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '';
3003 + if (options && options.required && !val) {
3004 + throw new Error(`Input required and not supplied: ${name}`);
3005 + }
3006 + return val.trim();
3007 +}
3008 +exports.getInput = getInput;
3009 +/**
3010 + * Sets the value of an output.
3011 + *
3012 + * @param name name of the output to set
3013 + * @param value value to store. Non-string values will be converted to a string via JSON.stringify
3014 + */
3015 +// eslint-disable-next-line @typescript-eslint/no-explicit-any
3016 +function setOutput(name, value) {
3017 + command_1.issueCommand('set-output', { name }, value);
3018 +}
3019 +exports.setOutput = setOutput;
3020 +/**
3021 + * Enables or disables the echoing of commands into stdout for the rest of the step.
3022 + * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set.
3023 + *
3024 + */
3025 +function setCommandEcho(enabled) {
3026 + command_1.issue('echo', enabled ? 'on' : 'off');
3027 +}
3028 +exports.setCommandEcho = setCommandEcho;
3029 +//-----------------------------------------------------------------------
3030 +// Results
3031 +//-----------------------------------------------------------------------
3032 +/**
3033 + * Sets the action status to failed.
3034 + * When the action exits it will be with an exit code of 1
3035 + * @param message add error issue message
3036 + */
3037 +function setFailed(message) {
3038 + process.exitCode = ExitCode.Failure;
3039 + error(message);
3040 +}
3041 +exports.setFailed = setFailed;
3042 +//-----------------------------------------------------------------------
3043 +// Logging Commands
3044 +//-----------------------------------------------------------------------
3045 +/**
3046 + * Gets whether Actions Step Debug is on or not
3047 + */
3048 +function isDebug() {
3049 + return process.env['RUNNER_DEBUG'] === '1';
3050 +}
3051 +exports.isDebug = isDebug;
3052 +/**
3053 + * Writes debug message to user log
3054 + * @param message debug message
3055 + */
3056 +function debug(message) {
3057 + command_1.issueCommand('debug', {}, message);
3058 +}
3059 +exports.debug = debug;
3060 +/**
3061 + * Adds an error issue
3062 + * @param message error issue message. Errors will be converted to string via toString()
3063 + */
3064 +function error(message) {
3065 + command_1.issue('error', message instanceof Error ? message.toString() : message);
3066 +}
3067 +exports.error = error;
3068 +/**
3069 + * Adds an warning issue
3070 + * @param message warning issue message. Errors will be converted to string via toString()
3071 + */
3072 +function warning(message) {
3073 + command_1.issue('warning', message instanceof Error ? message.toString() : message);
3074 +}
3075 +exports.warning = warning;
3076 +/**
3077 + * Writes info to log with console.log.
3078 + * @param message info message
3079 + */
3080 +function info(message) {
3081 + process.stdout.write(message + os.EOL);
3082 +}
3083 +exports.info = info;
3084 +/**
3085 + * Begin an output group.
3086 + *
3087 + * Output until the next `groupEnd` will be foldable in this group
3088 + *
3089 + * @param name The name of the output group
3090 + */
3091 +function startGroup(name) {
3092 + command_1.issue('group', name);
3093 +}
3094 +exports.startGroup = startGroup;
3095 +/**
3096 + * End an output group.
3097 + */
3098 +function endGroup() {
3099 + command_1.issue('endgroup');
3100 +}
3101 +exports.endGroup = endGroup;
3102 +/**
3103 + * Wrap an asynchronous function call in a group.
3104 + *
3105 + * Returns the same type as the function itself.
3106 + *
3107 + * @param name The name of the group
3108 + * @param fn The function to wrap in the group
3109 + */
3110 +function group(name, fn) {
3111 + return __awaiter(this, void 0, void 0, function* () {
3112 + startGroup(name);
3113 + let result;
3114 + try {
3115 + result = yield fn();
3116 + }
3117 + finally {
3118 + endGroup();
3119 + }
3120 + return result;
3121 + });
3122 +}
3123 +exports.group = group;
3124 +//-----------------------------------------------------------------------
3125 +// Wrapper action state
3126 +//-----------------------------------------------------------------------
3127 +/**
3128 + * Saves state for current action, the state can only be retrieved by this action's post job execution.
3129 + *
3130 + * @param name name of the state to store
3131 + * @param value value to store. Non-string values will be converted to a string via JSON.stringify
3132 + */
3133 +// eslint-disable-next-line @typescript-eslint/no-explicit-any
3134 +function saveState(name, value) {
3135 + command_1.issueCommand('save-state', { name }, value);
3136 +}
3137 +exports.saveState = saveState;
3138 +/**
3139 + * Gets the value of an state set by this action's main execution.
3140 + *
3141 + * @param name name of the state to get
3142 + * @returns string
3143 + */
3144 +function getState(name) {
3145 + return process.env[`STATE_${name}`] || '';
3146 +}
3147 +exports.getState = getState;
2489 3148 //# sourceMappingURL=core.js.map
2490 3149
2491 3150 /***/ }),
@@ -2504,45 +3163,67 @@ module.exports = require("path");
2504 3163
2505 3164 /***/ }),
2506 3165
3166 +/***/ 669:
3167 +/***/ (function(module) {
3168 +
3169 +module.exports = require("util");
3170 +
3171 +/***/ }),
3172 +
3173 +/***/ 747:
3174 +/***/ (function(module) {
3175 +
3176 +module.exports = require("fs");
3177 +
3178 +/***/ }),
3179 +
2507 3180 /***/ 917:
2508 3181 /***/ (function(__unusedmodule, exports, __webpack_require__) {
2509 3182
2510 3183 "use strict";
2511
2512 var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2513 return new (P || (P = Promise))(function (resolve, reject) {
2514 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
2515 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
2516 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
2517 step((generator = generator.apply(thisArg, _arguments || [])).next());
2518 });
2519 };
2520 Object.defineProperty(exports, "__esModule", { value: true });
2521 const tr = __webpack_require__(9);
2522 /**
2523 * Exec a command.
2524 * Output will be streamed to the live console.
2525 * Returns promise with return code
2526 *
2527 * @param commandLine command to execute (can include additional args). Must be correctly escaped.
2528 * @param args optional arguments for tool. Escaping is handled by the lib.
2529 * @param options optional exec options. See ExecOptions
2530 * @returns Promise<number> exit code
2531 */
2532 function exec(commandLine, args, options) {
2533 return __awaiter(this, void 0, void 0, function* () {
2534 const commandArgs = tr.argStringToArray(commandLine);
2535 if (commandArgs.length === 0) {
2536 throw new Error(`Parameter 'commandLine' cannot be null or empty.`);
2537 }
2538 // Path to tool to execute should be first arg
2539 const toolPath = commandArgs[0];
2540 args = commandArgs.slice(1).concat(args || []);
2541 const runner = new tr.ToolRunner(toolPath, args, options);
2542 return runner.exec();
2543 });
2544 }
2545 exports.exec = exec;
3184 +
3185 +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3186 + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3187 + return new (P || (P = Promise))(function (resolve, reject) {
3188 + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
3189 + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
3190 + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
3191 + step((generator = generator.apply(thisArg, _arguments || [])).next());
3192 + });
3193 +};
3194 +var __importStar = (this && this.__importStar) || function (mod) {
3195 + if (mod && mod.__esModule) return mod;
3196 + var result = {};
3197 + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
3198 + result["default"] = mod;
3199 + return result;
3200 +};
3201 +Object.defineProperty(exports, "__esModule", { value: true });
3202 +const tr = __importStar(__webpack_require__(9));
3203 +/**
3204 + * Exec a command.
3205 + * Output will be streamed to the live console.
3206 + * Returns promise with return code
3207 + *
3208 + * @param commandLine command to execute (can include additional args). Must be correctly escaped.
3209 + * @param args optional arguments for tool. Escaping is handled by the lib.
3210 + * @param options optional exec options. See ExecOptions
3211 + * @returns Promise<number> exit code
3212 + */
3213 +function exec(commandLine, args, options) {
3214 + return __awaiter(this, void 0, void 0, function* () {
3215 + const commandArgs = tr.argStringToArray(commandLine);
3216 + if (commandArgs.length === 0) {
3217 + throw new Error(`Parameter 'commandLine' cannot be null or empty.`);
3218 + }
3219 + // Path to tool to execute should be first arg
3220 + const toolPath = commandArgs[0];
3221 + args = commandArgs.slice(1).concat(args || []);
3222 + const runner = new tr.ToolRunner(toolPath, args, options);
3223 + return runner.exec();
3224 + });
3225 +}
3226 +exports.exec = exec;
2546 3227 //# sourceMappingURL=exec.js.map
2547 3228
2548 3229 /***/ }),
@@ -2592,8 +3273,8 @@ async function main() {
2592 3273
2593 3274 const matchersPath = __webpack_require__.ab + ".github"
2594 3275 console.log(`##[add-matcher]${path.join(matchersPath, 'elixir.json')}`)
2595 console.log(`::set-output name=otp-version::${otpVersion}`)
2596 console.log(`::set-output name=elixir-version::${elixirVersion}`)
3276 + core.setOutput('otp-version', otpVersion)
3277 + core.setOutput('elixir-version', elixirVersion)
2597 3278 }
2598 3279
2599 3280 function checkPlatform() {
modified src/setup-elixir.js
+2 −2
@@ -40,8 +40,8 @@ async function main() {
40 40
41 41 const matchersPath = path.join(__dirname, '..', '.github')
42 42 console.log(`##[add-matcher]${path.join(matchersPath, 'elixir.json')}`)
43 console.log(`::set-output name=otp-version::${otpVersion}`)
44 console.log(`::set-output name=elixir-version::${elixirVersion}`)
43 + core.setOutput('otp-version', otpVersion)
44 + core.setOutput('elixir-version', elixirVersion)
45 45 }
46 46
47 47 function checkPlatform() {

Parents: 24f06ac