1
0
Fork 0

Add initial logic for command wrapper and some basic unit tests

pull/1562/head
Dusan Trickovic 2023-09-01 12:42:38 +02:00
parent b4ff0922c9
commit 2a75b5e2b3
2 changed files with 176 additions and 0 deletions

View File

@ -0,0 +1,53 @@
import {Command} from '../src/exec-command-wrapper'
import * as io from '@actions/io'
const IS_LINUX = process.platform === 'linux'
describe('Command', () => {
it('creates a command object', async () => {
if (IS_LINUX) {
const toolpath = await io.which('echo', true)
const command = new Command(`"${toolpath}"`, ['hello'])
expect(command).toBeDefined()
expect(command).toBeInstanceOf(Command)
}
})
it('runs a command with non-zero exit code', async () => {
if (IS_LINUX) {
const nonExistentDir = 'non-existent-dir'
const toolpath = await io.which('ls', true)
const args = ['-l', nonExistentDir]
const command = new Command(`"${toolpath}"`, args)
let failed = false
await command.execute().catch(err => {
failed = true
expect(err.message).toContain(
`The process '${toolpath}' failed with exit code `
)
})
expect(failed).toBe(true)
}
})
it('runs a command with zero exit code', async () => {
if (IS_LINUX) {
const toolpath = await io.which('echo', true)
const command = new Command(`"${toolpath}"`, ['hello'])
const result = await command.execute()
expect(result).toEqual('hello')
}
})
it('runs a command with empty output', async () => {
if (IS_LINUX) {
const toolpath = await io.which('echo', true)
const command = new Command(`"${toolpath}"`, [''])
const result = await command.execute()
expect(result).toEqual('')
}
})
})

View File

@ -0,0 +1,123 @@
import * as core from '@actions/core'
import * as exec from '@actions/exec'
export class Command {
private readonly commandText: string
private readonly args: string[]
private readonly options: exec.ExecOptions | undefined
private failOnError = false
private throwOnError = false
private failOnEmptyOutput = false
private throwOnEmptyOutput = false
constructor(
commandText: string,
args: string[],
options: exec.ExecOptions | undefined = undefined
) {
this.commandText = commandText
this.args = args
this.options = options
}
get failOn(): {error: () => Command; empty: () => Command} {
return {
error: this.setFailOnError,
empty: this.setFailOnEmptyOutput
}
}
get throwOn(): {error: () => Command; empty: () => Command} {
return {
error: this.setThrowOnError,
empty: this.setThrowOnEmptyOutput
}
}
private setFailOnError = (): Command => {
this.failOnError = true
return this
}
private setThrowOnError = (): Command => {
this.throwOnError = true
return this
}
private setFailOnEmptyOutput = (): Command => {
this.failOnEmptyOutput = true
return this
}
private setThrowOnEmptyOutput = (): Command => {
this.throwOnEmptyOutput = true
return this
}
private setFailedOnNonZeroExitCode(
command: string,
exitCode: number,
error: string
): void {
if (exitCode !== 0) {
error = !error.trim()
? `The '${command}' command failed with exit code: ${exitCode}`
: error
core.setFailed(error)
}
return
}
private throwErrorOnNonZeroExitCode(
command: string,
exitCode: number,
error: string
): void {
if (exitCode !== 0) {
error = !error.trim()
? `The '${command}' command failed with exit code: ${exitCode}`
: error
throw new Error(error)
}
return
}
async execute(): Promise<string> {
const {stdout, stderr, exitCode} = await exec.getExecOutput(
this.commandText,
this.args,
this.options
)
if (this.failOnError) {
this.setFailedOnNonZeroExitCode(this.commandText, exitCode, stderr)
return stdout.trim()
}
if (this.throwOnError) {
this.throwErrorOnNonZeroExitCode(this.commandText, exitCode, stderr)
return stdout.trim()
}
if (this.failOnEmptyOutput && !stdout.trim()) {
core.setFailed(
`The '${this.commandText}' command failed with empty output`
)
return stdout.trim()
}
if (this.throwOnEmptyOutput && !stdout.trim()) {
throw new Error(
`The '${this.commandText}' command failed with empty output`
)
}
return stdout.trim()
}
}
// new Command('echo', ['hello', 'world'])
// .failOn.error()
// .execute()