1
0
Fork 0

Make use of @actions/exit in @actions/toolkit

pull/1/head
Jonathan Clem 2019-04-20 10:54:42 -04:00
parent cca9523c73
commit b3e79eb868
No known key found for this signature in database
GPG Key ID: 48C5B22E9FD6E80F
4 changed files with 73 additions and 83 deletions

View File

@ -1,36 +1,37 @@
import * as exitPkg from '@actions/exit'
import {Signale} from 'signale' import {Signale} from 'signale'
import {Exit, ExitCode} from '../src/exit' import {Exit} from '../src/exit'
describe('Exit', () => { jest.mock('@actions/exit')
const tests: [keyof Exit, keyof Signale, ExitCode][] = [
['success', 'success', ExitCode.Success],
['neutral', 'info', ExitCode.Neutral],
['failure', 'fatal', ExitCode.Failure]
]
describe.each(tests)('%s', (method, log, code) => { const tests: [keyof Exit, keyof Signale][] = [
let logger: Signale ['success', 'success'],
let exit: Exit ['neutral', 'info'],
['failure', 'fatal']
]
beforeEach(() => { describe.each(tests)('%s', (method, log) => {
// Create a logger to mock let logger: Signale
logger = new Signale() let exit: Exit
logger.success = jest.fn()
logger.info = jest.fn()
logger.fatal = jest.fn()
process.exit = jest.fn<never, [number]>() beforeEach(() => {
exit = new Exit(logger) // Create a logger to mock
}) logger = new Signale()
logger.success = jest.fn()
logger.info = jest.fn()
logger.fatal = jest.fn()
it('exits with the expected code', () => { process.exit = jest.fn<never, [number]>()
exit[method]() exit = new Exit(logger)
expect(process.exit).toHaveBeenCalledWith(code) })
})
it('logs the expected message', () => { it('exits with the expected method', () => {
exit[method]('hello') exit[method]()
expect(logger[log]).toHaveBeenCalledWith('hello') expect(exitPkg[method]).toHaveBeenCalled()
}) })
it('logs the expected message', () => {
exit[method]('hello')
expect(logger[log]).toHaveBeenCalledWith('hello')
}) })
}) })

View File

@ -1,50 +1,50 @@
import * as exitPkg from '@actions/exit'
import {Signale} from 'signale' import {Signale} from 'signale'
import {ExitCode} from '../src/exit'
import {Toolkit} from '../src/toolkit' import {Toolkit} from '../src/toolkit'
describe('Toolkit', () => { jest.mock('@actions/exit')
describe('.run', () => {
it('runs a sync function', async () => {
const cb = jest.fn(() => true)
const value = await Toolkit.run(cb)
expect(cb).toHaveBeenCalledWith(expect.any(Toolkit))
expect(value).toBe(true)
})
it('runs an async function', async () => { describe('.run', () => {
const cb = jest.fn(async () => true) it('runs a sync function', async () => {
const value = await Toolkit.run(cb) const cb = jest.fn(() => true)
expect(cb).toHaveBeenCalledWith(expect.any(Toolkit)) const value = await Toolkit.run(cb)
expect(value).toBe(true) expect(cb).toHaveBeenCalledWith(expect.any(Toolkit))
}) expect(value).toBe(true)
it('logs and fails when an error occurs', async () => {
const err = new Error()
const exitFailure = jest.fn()
await Toolkit.run(async tk => {
tk.exit.failure = exitFailure
throw err
})
expect(exitFailure).toHaveBeenCalledWith(err)
})
}) })
it('asserts required keys are present', async () => { it('runs an async function', async () => {
const missingKey = '__DOES_NOT_EXIST__' const cb = jest.fn(async () => true)
const value = await Toolkit.run(cb)
expect(cb).toHaveBeenCalledWith(expect.any(Toolkit))
expect(value).toBe(true)
})
Reflect.deleteProperty(process.env, missingKey) it('logs and fails when an error occurs', async () => {
const err = new Error()
const exitFailure = jest.fn()
const logger = new Signale() await Toolkit.run(async tk => {
logger.fatal = jest.fn() tk.exit.failure = exitFailure
jest.spyOn(process, 'exit').mockImplementation() throw err
})
new Toolkit({logger, requiredEnv: [missingKey]}) expect(exitFailure).toHaveBeenCalledWith(err)
expect(process.exit).toHaveBeenCalledWith(ExitCode.Failure)
expect(logger.fatal)
.toHaveBeenCalledWith(`The following environment variables are required for this action to run:
- __DOES_NOT_EXIST__`)
}) })
}) })
it('asserts required keys are present', async () => {
const missingKey = '__DOES_NOT_EXIST__'
Reflect.deleteProperty(process.env, missingKey)
const logger = new Signale()
logger.fatal = jest.fn()
jest.spyOn(process, 'exit').mockImplementation()
new Toolkit({logger, requiredEnv: [missingKey]})
expect(exitPkg.failure).toHaveBeenCalled()
expect(logger.fatal)
.toHaveBeenCalledWith(`The following environment variables are required for this action to run:
- __DOES_NOT_EXIST__`)
})

View File

@ -31,8 +31,8 @@
"url": "https://github.com/actions/toolkit/issues" "url": "https://github.com/actions/toolkit/issues"
}, },
"dependencies": { "dependencies": {
"@actions/exit": "^0.0.0",
"@octokit/rest": "^16.25.0", "@octokit/rest": "^16.25.0",
"signale": "^1.4.0" "signale": "^1.4.0"
}, }
"devDependencies": {}
} }

View File

@ -1,17 +1,6 @@
import * as exit from '@actions/exit'
import {Signale} from 'signale' import {Signale} from 'signale'
/**
* The code to exit an action
*/
export enum ExitCode {
Success = 0,
Failure = 1,
Neutral = 78
}
// TODO: These exit codes may not behave as expected on the new runtime, due to
// complexities of async logging and sync exiting.
/** /**
* A class that wraps some basic methods of exiting from an action * A class that wraps some basic methods of exiting from an action
*/ */
@ -23,7 +12,7 @@ export class Exit {
*/ */
success(message?: string) { success(message?: string) {
if (message) this.logger.success(message) if (message) this.logger.success(message)
process.exit(ExitCode.Success) exit.success()
} }
/** /**
@ -31,7 +20,7 @@ export class Exit {
*/ */
neutral(message?: string) { neutral(message?: string) {
if (message) this.logger.info(message) if (message) this.logger.info(message)
process.exit(ExitCode.Neutral) exit.neutral()
} }
/** /**
@ -39,6 +28,6 @@ export class Exit {
*/ */
failure(message?: string) { failure(message?: string) {
if (message) this.logger.fatal(message) if (message) this.logger.fatal(message)
process.exit(ExitCode.Failure) exit.failure()
} }
} }