mirror of
https://git.mirrors.martin98.com/https://github.com/actions/toolkit
synced 2026-04-03 18:33:26 +08:00
Add getExecOutput function (#814)
* Add getExecOutput function * Add tests for exec output * Modify tests to not rely on buffer size, but only test larger output * Handle split multi-byte characters + PR feedback * Fix tests * Lint * Update how split byte are sent for tests
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import {ExecOptions} from './interfaces'
|
||||
import {StringDecoder} from 'string_decoder'
|
||||
import {ExecOptions, ExecOutput, ExecListeners} from './interfaces'
|
||||
import * as tr from './toolrunner'
|
||||
|
||||
export {ExecOptions}
|
||||
export {ExecOptions, ExecOutput, ExecListeners}
|
||||
|
||||
/**
|
||||
* Exec a command.
|
||||
@@ -28,3 +29,63 @@ export async function exec(
|
||||
const runner: tr.ToolRunner = new tr.ToolRunner(toolPath, args, options)
|
||||
return runner.exec()
|
||||
}
|
||||
|
||||
/**
|
||||
* Exec a command and get the output.
|
||||
* Output will be streamed to the live console.
|
||||
* Returns promise with the exit code and collected stdout and stderr
|
||||
*
|
||||
* @param commandLine command to execute (can include additional args). Must be correctly escaped.
|
||||
* @param args optional arguments for tool. Escaping is handled by the lib.
|
||||
* @param options optional exec options. See ExecOptions
|
||||
* @returns Promise<ExecOutput> exit code, stdout, and stderr
|
||||
*/
|
||||
|
||||
export async function getExecOutput(
|
||||
commandLine: string,
|
||||
args?: string[],
|
||||
options?: ExecOptions
|
||||
): Promise<ExecOutput> {
|
||||
let stdout = ''
|
||||
let stderr = ''
|
||||
|
||||
//Using string decoder covers the case where a mult-byte character is split
|
||||
const stdoutDecoder = new StringDecoder('utf8')
|
||||
const stderrDecoder = new StringDecoder('utf8')
|
||||
|
||||
const originalStdoutListener = options?.listeners?.stdout
|
||||
const originalStdErrListener = options?.listeners?.stderr
|
||||
|
||||
const stdErrListener = (data: Buffer): void => {
|
||||
stderr += stderrDecoder.write(data)
|
||||
if (originalStdErrListener) {
|
||||
originalStdErrListener(data)
|
||||
}
|
||||
}
|
||||
|
||||
const stdOutListener = (data: Buffer): void => {
|
||||
stdout += stdoutDecoder.write(data)
|
||||
if (originalStdoutListener) {
|
||||
originalStdoutListener(data)
|
||||
}
|
||||
}
|
||||
|
||||
const listeners: ExecListeners = {
|
||||
...options?.listeners,
|
||||
stdout: stdOutListener,
|
||||
stderr: stdErrListener
|
||||
}
|
||||
|
||||
const exitCode = await exec(commandLine, args, {...options, listeners})
|
||||
|
||||
//flush any remaining characters
|
||||
stdout += stdoutDecoder.end()
|
||||
stderr += stderrDecoder.end()
|
||||
|
||||
//return undefined for stdout/stderr if they are empty
|
||||
return {
|
||||
exitCode,
|
||||
stdout,
|
||||
stderr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,15 +34,39 @@ export interface ExecOptions {
|
||||
input?: Buffer
|
||||
|
||||
/** optional. Listeners for output. Callback functions that will be called on these events */
|
||||
listeners?: {
|
||||
stdout?: (data: Buffer) => void
|
||||
|
||||
stderr?: (data: Buffer) => void
|
||||
|
||||
stdline?: (data: string) => void
|
||||
|
||||
errline?: (data: string) => void
|
||||
|
||||
debug?: (data: string) => void
|
||||
}
|
||||
listeners?: ExecListeners
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for the output of getExecOutput()
|
||||
*/
|
||||
export interface ExecOutput {
|
||||
/**The exit code of the process */
|
||||
exitCode: number
|
||||
|
||||
/**The entire stdout of the process as a string */
|
||||
stdout: string
|
||||
|
||||
/**The entire stderr of the process as a string */
|
||||
stderr: string
|
||||
}
|
||||
|
||||
/**
|
||||
* The user defined listeners for an exec call
|
||||
*/
|
||||
export interface ExecListeners {
|
||||
/** A call back for each buffer of stdout */
|
||||
stdout?: (data: Buffer) => void
|
||||
|
||||
/** A call back for each buffer of stderr */
|
||||
stderr?: (data: Buffer) => void
|
||||
|
||||
/** A call back for each line of stdout */
|
||||
stdline?: (data: string) => void
|
||||
|
||||
/** A call back for each line of stderr */
|
||||
errline?: (data: string) => void
|
||||
|
||||
/** A call back for each debug log */
|
||||
debug?: (data: string) => void
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user