From b065676cadd21ee1bc6d84567ff539f87e6d04eb Mon Sep 17 00:00:00 2001 From: Jonas Lindenskov Nielsen Date: Mon, 1 Feb 2021 13:33:48 +0100 Subject: [PATCH 1/7] Remove demo tests from code coverage --- jest.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/jest.config.js b/jest.config.js index 332deff..7707037 100644 --- a/jest.config.js +++ b/jest.config.js @@ -10,4 +10,5 @@ module.exports = { testEnvironment: 'node', testRunner: 'jest-circus/runner', verbose: true, + testPathIgnorePatterns: ['/src/demo_tests/'], }; From 357a37c39fbdc8286e7e7622038e18b1aa420f36 Mon Sep 17 00:00:00 2001 From: Jonas Lindenskov Nielsen Date: Mon, 1 Feb 2021 13:41:10 +0100 Subject: [PATCH 2/7] update run to show output of jest in a group --- src/__tests__/run.spec.ts | 1 + src/run.ts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/__tests__/run.spec.ts b/src/__tests__/run.spec.ts index cce2b7d..5098d1f 100644 --- a/src/__tests__/run.spec.ts +++ b/src/__tests__/run.spec.ts @@ -28,6 +28,7 @@ describe.skip('runJest', () => { expect(exec).toBeCalledWith('yarn test', [], { cwd: './', + ignoreReturnCode: true, }); }); }); diff --git a/src/run.ts b/src/run.ts index 84e08db..2fe9c2c 100644 --- a/src/run.ts +++ b/src/run.ts @@ -2,6 +2,7 @@ import { readFileSync } from 'fs'; import { exec } from '@actions/exec'; import { context } from '@actions/github'; import type { FormattedTestResults } from '@jest/test-result/build/types'; +import { debug, endGroup, startGroup } from '@actions/core'; export type RunJestOptions = { coverageFilePath: string; @@ -24,7 +25,10 @@ export default async function runJest({ cwd, coverageFilePath, }: RunJestOptions): Promise { - await exec(cmd, [], { cwd, silent: true, ignoreReturnCode: true }); + startGroup('Jest output'); + const statusCode = await exec(cmd, [], { cwd, ignoreReturnCode: true }); + debug(`Jest exited with status code: ${statusCode}`); + endGroup(); const content = readFileSync(coverageFilePath, 'utf-8'); From f7bdaf6bc3c5ddec2d7ae94ae01b1d7f27d82e7d Mon Sep 17 00:00:00 2001 From: Jonas Lindenskov Nielsen Date: Mon, 1 Feb 2021 13:51:47 +0100 Subject: [PATCH 3/7] Only ignore code coverage instead of the entire test -_- --- jest.config.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jest.config.js b/jest.config.js index 7707037..61d0db0 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,10 +5,9 @@ module.exports = { transform: { '^.+\\.ts$': 'ts-jest', }, - collectCoverageFrom: ['src/**/*.ts'], + collectCoverageFrom: ['src/**/*.ts', '!src/demo_tests/*.ts'], clearMocks: true, testEnvironment: 'node', testRunner: 'jest-circus/runner', verbose: true, - testPathIgnorePatterns: ['/src/demo_tests/'], }; From 585a80b23fd2c1a143fef87044eef5cfaadc3a3c Mon Sep 17 00:00:00 2001 From: Jonas Lindenskov Nielsen Date: Mon, 1 Feb 2021 14:02:50 +0100 Subject: [PATCH 4/7] Action now fails if jest returns non-zero status code on exit --- src/__tests__/run.spec.ts | 4 +--- src/main.ts | 11 +++++++++-- src/run.ts | 14 ++++++++------ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/__tests__/run.spec.ts b/src/__tests__/run.spec.ts index 5098d1f..b3fbddf 100644 --- a/src/__tests__/run.spec.ts +++ b/src/__tests__/run.spec.ts @@ -17,13 +17,11 @@ jest.mock('@actions/github', () => ({ jest.mock('@actions/exec'); -// TODO: Reintroduce test and mock/test file system access -describe.skip('runJest', () => { +describe('runJest', () => { it('executes command', async () => { await runJest({ cmd: 'yarn test', cwd: './', - coverageFilePath: 'foo.json', }); expect(exec).toBeCalledWith('yarn test', [], { diff --git a/src/main.ts b/src/main.ts index f215dbf..73b1070 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,7 +3,7 @@ import * as core from '@actions/core'; import { getGithubToken, hasBooleanArg } from './args'; import { generateCommentBody } from './coverage'; import updateOrCreateComment from './comment'; -import runJest, { getJestCommand } from './run'; +import runJest, { getJestCommand, readTestResults } from './run'; import { reportTestResults } from './testResults'; async function main(): Promise { @@ -29,11 +29,18 @@ async function main(): Promise { core.info('Executing jest'); // execute jest - const results = await runJest({ cmd, cwd, coverageFilePath }); + const statusCode = await runJest({ cmd, cwd }); + const results = readTestResults(coverageFilePath); core.info('Reporting test results'); reportTestResults(results); + if (statusCode !== 0) { + throw new Error( + 'Jest returned non-zero exit code. Check annotations or debug output for more information.' + ); + } + // Return early if we should not post code coverage comment if (!shouldCommentCoverage) { core.info('Code coverage commenting is disabled. Skipping...'); diff --git a/src/run.ts b/src/run.ts index 2fe9c2c..8d7c8ba 100644 --- a/src/run.ts +++ b/src/run.ts @@ -5,7 +5,6 @@ import type { FormattedTestResults } from '@jest/test-result/build/types'; import { debug, endGroup, startGroup } from '@actions/core'; export type RunJestOptions = { - coverageFilePath: string; cmd: string; cwd: string; }; @@ -20,16 +19,19 @@ export type GetJestCommandArgs = MakeJestArgs & { baseCommand: string; }; -export default async function runJest({ - cmd, - cwd, - coverageFilePath, -}: RunJestOptions): Promise { +export default async function runJest({ cmd, cwd }: RunJestOptions): Promise { startGroup('Jest output'); + const statusCode = await exec(cmd, [], { cwd, ignoreReturnCode: true }); + debug(`Jest exited with status code: ${statusCode}`); + endGroup(); + return statusCode; +} + +export function readTestResults(coverageFilePath: string): FormattedTestResults { const content = readFileSync(coverageFilePath, 'utf-8'); const results = JSON.parse(content) as FormattedTestResults; From 8503978799383abc9ba20feec926f26611d09929 Mon Sep 17 00:00:00 2001 From: Jonas Lindenskov Nielsen Date: Mon, 1 Feb 2021 14:06:16 +0100 Subject: [PATCH 5/7] Bump From cd1a232083700bb24f127c7ea147507cceaf09b4 Mon Sep 17 00:00:00 2001 From: Jonas Lindenskov Nielsen Date: Mon, 1 Feb 2021 14:11:03 +0100 Subject: [PATCH 6/7] Add flag to ignore jest exit code fail --- .github/workflows/test.yml | 2 ++ action.yml | 4 ++++ src/args.ts | 2 +- src/main.ts | 15 ++++++++++----- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 662bf07..b5a622c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -65,3 +65,5 @@ jobs: test-command: yarn test:demo # Dont post code coverage for the demo tests coverage-comment: false + # Dont mark action as failed if jest returns non-zero exit code + fail-action-if-jest-fails: false diff --git a/action.yml b/action.yml index 97e57dc..57e3216 100644 --- a/action.yml +++ b/action.yml @@ -21,6 +21,10 @@ inputs: describe: 'If true, the content of the code coverage comment will be printed as debug output instead of actually submitting it.' required: false default: 'false' + fail-action-if-jest-fails: + describe: 'If true, the action is marked as failed, if jest returns a non-zero exit code.' + required: false + default: 'true' runs: using: 'node12' main: 'dist/index.js' diff --git a/src/args.ts b/src/args.ts index 7902557..e8acab1 100644 --- a/src/args.ts +++ b/src/args.ts @@ -1,6 +1,6 @@ import { getInput } from '@actions/core'; -export function hasBooleanArg(key: string, required = false): boolean { +export function getBooleanArg(key: string, required = false): boolean { return Boolean(JSON.parse(getInput(key, { required }))); } diff --git a/src/main.ts b/src/main.ts index 73b1070..5b4700a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,6 @@ import path, { sep } from 'path'; import * as core from '@actions/core'; -import { getGithubToken, hasBooleanArg } from './args'; +import { getGithubToken, getBooleanArg } from './args'; import { generateCommentBody } from './coverage'; import updateOrCreateComment from './comment'; import runJest, { getJestCommand, readTestResults } from './run'; @@ -10,9 +10,10 @@ async function main(): Promise { // Get args const baseCommand = core.getInput('test-command', { required: false }) ?? 'npm test'; const workingDirectory = core.getInput('working-directory', { required: false }); - const shouldCommentCoverage = hasBooleanArg('coverage-comment'); - const dryRun = hasBooleanArg('dry-run'); - const runOnlyChangedFiles = hasBooleanArg('changes-only'); + const shouldCommentCoverage = getBooleanArg('coverage-comment'); + const dryRun = getBooleanArg('dry-run'); + const runOnlyChangedFiles = getBooleanArg('changes-only'); + const exitOnJestFail = getBooleanArg('fail-action-if-jest-fails'); // Compute paths const cwd = workingDirectory ? path.resolve(workingDirectory) : process.cwd(); @@ -35,10 +36,14 @@ async function main(): Promise { core.info('Reporting test results'); reportTestResults(results); - if (statusCode !== 0) { + if (exitOnJestFail && statusCode !== 0) { throw new Error( 'Jest returned non-zero exit code. Check annotations or debug output for more information.' ); + } else if (!exitOnJestFail) { + core.info( + 'Continuing even though jest failed, since "fail-action-if-jest-fails" is false.' + ); } // Return early if we should not post code coverage comment From 0a071f4a278c75b6003fe4b3ce2cd1be6d502178 Mon Sep 17 00:00:00 2001 From: Jonas Lindenskov Nielsen Date: Mon, 1 Feb 2021 14:18:23 +0100 Subject: [PATCH 7/7] Bump version number to 1.0.0 --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ed75df..ee9973f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "github-action-jest", - "version": "0.0.1", + "version": "1.0.0", "private": true, "description": "A github action for running jest. With code coverage!", "main": "lib/main.js", @@ -17,6 +17,7 @@ }, "keywords": [ "actions", + "ci", "node", "jest", "code-coverage"