1
0
Fork 0

add support for using a shell to run commands

pull/285/head
Alex Kalyvitis 2020-01-06 14:41:57 +01:00
parent bfd29dcef8
commit 654dba3681
3 changed files with 81 additions and 60 deletions

View File

@ -153,6 +153,23 @@ describe('@actions/exec', () => {
expect(output.trim()).toBe(`hello`)
})
it('Runs exec successfully with shell wildcard substitution', async () => {
let tool: string
let args: string[]
let opts: im.ExecOptions
if (IS_WINDOWS) {
tool = 'cmd'
args = ['/c', 'echo', 'hello']
opts = {shell: process.env.ComSpec}
} else {
tool = 'ls'
args = ['-l', '*.md']
opts = {shell: '/bin/sh'}
}
const exitCode = await exec.exec(tool, args, opts)
expect(exitCode).toBe(0)
})
it('Exec fails with error on bad call', async () => {
const _testExecOptions = getExecOptions()
@ -286,7 +303,7 @@ describe('@actions/exec', () => {
expect(stderrCalled).toBeTruthy()
})
it('Handles child process holding streams open', async function() {
it('Handles child process holding streams open', async function () {
const semaphorePath = path.join(
getTestTemp(),
'child-process-semaphore.txt'
@ -332,7 +349,7 @@ describe('@actions/exec', () => {
fs.unlinkSync(semaphorePath)
}, 10000) // this was timing out on some slower hosted macOS runs at default 5s
it('Handles child process holding streams open and non-zero exit code', async function() {
it('Handles child process holding streams open and non-zero exit code', async function () {
const semaphorePath = path.join(
getTestTemp(),
'child-process-semaphore.txt'
@ -386,7 +403,7 @@ describe('@actions/exec', () => {
fs.unlinkSync(semaphorePath)
}, 10000) // this was timing out on some slower hosted macOS runs at default 5s
it('Handles child process holding streams open and stderr', async function() {
it('Handles child process holding streams open and stderr', async function () {
const semaphorePath = path.join(
getTestTemp(),
'child-process-semaphore.txt'
@ -654,16 +671,16 @@ describe('@actions/exec', () => {
expect(exitCode).toBe(0)
expect(outStream.getContents().split(os.EOL)[0]).toBe(
`[command]${exePath} /c echo` +
` helloworld` +
` "hello world"` +
` "hello:\\"world again\\""` +
` hello,world`
` helloworld` +
` "hello world"` +
` "hello:\\"world again\\""` +
` hello,world`
)
expect(output.trim()).toBe(
'helloworld' +
' "hello world"' +
' "hello:\\"world again\\""' +
' hello,world'
' "hello world"' +
' "hello:\\"world again\\""' +
' hello,world'
)
})
@ -752,7 +769,7 @@ describe('@actions/exec', () => {
)
expect(output.trim()).toBe(
'args[0]: "<quote>my arg 1<quote>"\r\n' +
'args[1]: "<quote>my arg 2<quote>"'
'args[1]: "<quote>my arg 2<quote>"'
)
})
@ -782,7 +799,7 @@ describe('@actions/exec', () => {
)
expect(output.trim()).toBe(
'args[0]: "<quote>my arg 1<quote>"\r\n' +
'args[1]: "<quote>my arg 2<quote>"'
'args[1]: "<quote>my arg 2<quote>"'
)
} catch (err) {
process.env['Path'] = originalPath
@ -838,57 +855,57 @@ describe('@actions/exec', () => {
expect(exitCode).toBe(0)
expect(outStream.getContents().split(os.EOL)[0]).toBe(
`[command]${process.env.ComSpec} /D /S /C ""${cmdPath}"` +
` helloworld` +
` "hello world"` +
` "hello\tworld"` +
` "hello&world"` +
` "hello(world"` +
` "hello)world"` +
` "hello[world"` +
` "hello]world"` +
` "hello{world"` +
` "hello}world"` +
` "hello^world"` +
` "hello=world"` +
` "hello;world"` +
` "hello!world"` +
` "hello'world"` +
` "hello+world"` +
` "hello,world"` +
` "hello\`world"` +
` "hello~world"` +
` "hello|world"` +
` "hello<world"` +
` "hello>world"` +
` "hello:""world again"""` +
` "hello world\\\\"` +
`"`
` helloworld` +
` "hello world"` +
` "hello\tworld"` +
` "hello&world"` +
` "hello(world"` +
` "hello)world"` +
` "hello[world"` +
` "hello]world"` +
` "hello{world"` +
` "hello}world"` +
` "hello^world"` +
` "hello=world"` +
` "hello;world"` +
` "hello!world"` +
` "hello'world"` +
` "hello+world"` +
` "hello,world"` +
` "hello\`world"` +
` "hello~world"` +
` "hello|world"` +
` "hello<world"` +
` "hello>world"` +
` "hello:""world again"""` +
` "hello world\\\\"` +
`"`
)
expect(output.trim()).toBe(
'args[0]: "helloworld"\r\n' +
'args[1]: "<quote>hello world<quote>"\r\n' +
'args[2]: "<quote>hello\tworld<quote>"\r\n' +
'args[3]: "<quote>hello&world<quote>"\r\n' +
'args[4]: "<quote>hello(world<quote>"\r\n' +
'args[5]: "<quote>hello)world<quote>"\r\n' +
'args[6]: "<quote>hello[world<quote>"\r\n' +
'args[7]: "<quote>hello]world<quote>"\r\n' +
'args[8]: "<quote>hello{world<quote>"\r\n' +
'args[9]: "<quote>hello}world<quote>"\r\n' +
'args[10]: "<quote>hello^world<quote>"\r\n' +
'args[11]: "<quote>hello=world<quote>"\r\n' +
'args[12]: "<quote>hello;world<quote>"\r\n' +
'args[13]: "<quote>hello!world<quote>"\r\n' +
'args[14]: "<quote>hello\'world<quote>"\r\n' +
'args[15]: "<quote>hello+world<quote>"\r\n' +
'args[16]: "<quote>hello,world<quote>"\r\n' +
'args[17]: "<quote>hello`world<quote>"\r\n' +
'args[18]: "<quote>hello~world<quote>"\r\n' +
'args[19]: "<quote>hello|world<quote>"\r\n' +
'args[20]: "<quote>hello<world<quote>"\r\n' +
'args[21]: "<quote>hello>world<quote>"\r\n' +
'args[22]: "<quote>hello:<quote><quote>world again<quote><quote><quote>"\r\n' +
'args[23]: "<quote>hello world\\\\<quote>"'
'args[1]: "<quote>hello world<quote>"\r\n' +
'args[2]: "<quote>hello\tworld<quote>"\r\n' +
'args[3]: "<quote>hello&world<quote>"\r\n' +
'args[4]: "<quote>hello(world<quote>"\r\n' +
'args[5]: "<quote>hello)world<quote>"\r\n' +
'args[6]: "<quote>hello[world<quote>"\r\n' +
'args[7]: "<quote>hello]world<quote>"\r\n' +
'args[8]: "<quote>hello{world<quote>"\r\n' +
'args[9]: "<quote>hello}world<quote>"\r\n' +
'args[10]: "<quote>hello^world<quote>"\r\n' +
'args[11]: "<quote>hello=world<quote>"\r\n' +
'args[12]: "<quote>hello;world<quote>"\r\n' +
'args[13]: "<quote>hello!world<quote>"\r\n' +
'args[14]: "<quote>hello\'world<quote>"\r\n' +
'args[15]: "<quote>hello+world<quote>"\r\n' +
'args[16]: "<quote>hello,world<quote>"\r\n' +
'args[17]: "<quote>hello`world<quote>"\r\n' +
'args[18]: "<quote>hello~world<quote>"\r\n' +
'args[19]: "<quote>hello|world<quote>"\r\n' +
'args[20]: "<quote>hello<world<quote>"\r\n' +
'args[21]: "<quote>hello>world<quote>"\r\n' +
'args[22]: "<quote>hello:<quote><quote>world again<quote><quote><quote>"\r\n' +
'args[23]: "<quote>hello world\\\\<quote>"'
)
})
}

View File

@ -12,6 +12,9 @@ export interface ExecOptions {
/** optional. defaults to false */
silent?: boolean
/** optional. Runs command inside of a shell. A different shell can be specified as a string. Defaults to false */
shell?: boolean | string
/** optional out stream to use. Defaults to process.stdout */
outStream?: stream.Writable

View File

@ -377,6 +377,7 @@ export class ToolRunner extends events.EventEmitter {
const result = <child.SpawnOptions>{}
result.cwd = options.cwd
result.env = options.env
result.shell = options.shell
result['windowsVerbatimArguments'] =
options.windowsVerbatimArguments || this._isCmdFile()
if (options.windowsVerbatimArguments) {