Skip to content

Commit

Permalink
Coverage drop comparison by overall coverage (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
mlafleur authored Sep 5, 2023
1 parent 08f140d commit 5b20877
Show file tree
Hide file tree
Showing 12 changed files with 2,907 additions and 2,338 deletions.
9 changes: 5 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,29 @@ on:
push:
branches:
- main

permissions: write-all
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 20.3.1
- run: npm ci
- run: npm run format:check >> "${GITHUB_STEP_SUMMARY}"
- run: npm run lint
- run: npm run test >> "${GITHUB_STEP_SUMMARY}"
- uses: ./
id: code_coverage_report_action
if: always()
with:
filename: 'coverage/clover.xml'
fail_on_negative_difference: true
artifact_download_workflow_names: 'ci,cron'
badge: true
- name: Add Coverage PR Comment
uses: marocchino/sticky-pull-request-comment@v2
if: steps.code_coverage_report_action.outputs.file != '' && github.event_name == 'pull_request' && (success() || failure())
with:
recreate: true
path: code-coverage-results.md
path: code-coverage-results.md
2 changes: 2 additions & 0 deletions .github/workflows/cron.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ jobs:
- uses: ./
id: code_coverage_report_action
with:
badge: true
filename: 'coverage/clover.xml'
retention_days: 1
10 changes: 9 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,13 @@
"coverage-gutters.showLineCoverage": true,
"coverage-gutters.showRulerCoverage": true,
"coverage-gutters.coverageBaseDir": "coverage/**",
"coverage-gutters.coverageFileNames": ["clover.xml"]
"coverage-gutters.coverageFileNames": [
"clover.xml"
],
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[github-actions-workflow]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
248 changes: 134 additions & 114 deletions __tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,114 +1,134 @@
import {
formatArtifactName,
checkFileExists,
createHash,
roundPercentage,
determineCommonBasePath,
escapeRegExp,
colorizePercentageByThreshold,
getInputs
} from '../src/utils'
import {
expect,
test,
beforeEach,
afterEach,
describe,
jest
} from '@jest/globals'

const env = process.env

beforeEach(() => {
jest.resetModules()
process.env = {...env}
})

afterEach(() => {
process.env = env
})

test('formats the artifact name', async () => {
process.env.INPUT_GITHUB_TOKEN = 'token'
process.env.INPUT_FILENAME = 'filename.xml'
process.env.INPUT_ARTIFACT_NAME = 'coverage-%name%'
const name = formatArtifactName('bar')
expect(name).toBe('coverage-bar')
})

test('files exists', async () => {
const ret = await checkFileExists(__filename)
expect(ret).toBeTruthy()

const ret1 = await checkFileExists(__filename + 'bar')
expect(ret1).toBeFalsy()
})

test('created hash', () => {
const hash = createHash('foo')
expect(hash).toBeDefined()
})

test('round percentage', () => {
const a = roundPercentage(45.51234565)
expect(a).toBe(45.51)

const b = roundPercentage(45.51634565)
expect(b).toBe(45.52)
})

test('determine common base path from list of paths', () => {
const path = determineCommonBasePath([
'/usr/src/app/foo.js',
'/usr/src/app/foo/bar.js'
])

expect(path).toBe('/usr/src/app')
})

test('escaping regular expression input', () => {
const output = escapeRegExp('\\^$.|?*+{}[]()')
expect(output).toBe('\\\\\\^\\$\\.\\|\\?\\*\\+\\{\\}\\[\\]\\(\\)')
})

test('colorize percentage by threshold', () => {
const shouldBeNA = colorizePercentageByThreshold(null)
expect(shouldBeNA).toBe('N/A')

const shouldBeGrey = colorizePercentageByThreshold(0)
expect(shouldBeGrey).toBe('⚪ 0%')

const shouldBeRed = colorizePercentageByThreshold(20, 50)
expect(shouldBeRed).toBe('🔴 20%')

const shouldBeGreen = colorizePercentageByThreshold(70, 50)
expect(shouldBeGreen).toBe('🟢 70%')

const shouldBeRedA = colorizePercentageByThreshold(20, 75, 30)
expect(shouldBeRedA).toBe('🔴 20%')

const shouldBeOrangeA = colorizePercentageByThreshold(40, 75, 30)
expect(shouldBeOrangeA).toBe('🟠 40%')

const shouldBeGreenA = colorizePercentageByThreshold(80, 75, 30)
expect(shouldBeGreenA).toBe('🟢 80%')
})

test('getInputs', () => {
process.env.INPUT_GITHUB_TOKEN = 'token'
process.env.INPUT_FILENAME = 'filename.xml'

const f = getInputs()
expect(f).toStrictEqual({
token: 'token',
filename: 'filename.xml',
badge: false,
overallCoverageFailThreshold: 0,
fileCoverageErrorMin: 50,
fileCoverageWarningMax: 75,
failOnNegativeDifference: false,
markdownFilename: 'code-coverage-results',
artifactDownloadWorkflowNames: null,
artifactName: 'coverage-%name%'
})
})
import {
formatArtifactName,
checkFileExists,
createHash,
roundPercentage,
determineCommonBasePath,
escapeRegExp,
colorizePercentageByThreshold,
getInputs,
parseXML,
parseCoverage
} from '../src/utils'
import {
expect,
test,
beforeEach,
afterEach,
describe,
jest
} from '@jest/globals'

const env = process.env

beforeEach(() => {
jest.resetModules()
process.env = {...env}
})

afterEach(() => {
process.env = env
})

test('formats the artifact name', async () => {
process.env.INPUT_GITHUB_TOKEN = 'token'
process.env.INPUT_FILENAME = 'filename.xml'
process.env.INPUT_ARTIFACT_NAME = 'coverage-%name%'
const name = formatArtifactName('bar')
expect(name).toBe('coverage-bar')
})

test('files exists', async () => {
const ret = await checkFileExists(__filename)
expect(ret).toBeTruthy()

const ret1 = await checkFileExists(__filename + 'bar')
expect(ret1).toBeFalsy()
})

test('created hash', () => {
const hash = createHash('foo')
expect(hash).toBeDefined()
})

test('round percentage', () => {
const a = roundPercentage(45.51234565)
expect(a).toBe(45.51)

const b = roundPercentage(45.51634565)
expect(b).toBe(45.52)
})

test('determine common base path from list of paths', () => {
const path = determineCommonBasePath([
'/usr/src/app/foo.js',
'/usr/src/app/foo/bar.js'
])

expect(path).toBe('/usr/src/app')
})

test('escaping regular expression input', () => {
const output = escapeRegExp('\\^$.|?*+{}[]()')
expect(output).toBe('\\\\\\^\\$\\.\\|\\?\\*\\+\\{\\}\\[\\]\\(\\)')
})

test('colorize percentage by threshold', () => {
const shouldBeZero = colorizePercentageByThreshold(null)
expect(shouldBeZero).toBe('⚪ 0%')

const shouldBeGrey = colorizePercentageByThreshold(0)
expect(shouldBeGrey).toBe('⚪ 0%')

const shouldBeRed = colorizePercentageByThreshold(20, 50)
expect(shouldBeRed).toBe('🔴 20%')

const shouldBeGreen = colorizePercentageByThreshold(70, 50)
expect(shouldBeGreen).toBe('🟢 70%')

const shouldBeRedA = colorizePercentageByThreshold(20, 75, 30)
expect(shouldBeRedA).toBe('🔴 20%')

const shouldBeOrangeA = colorizePercentageByThreshold(40, 75, 30)
expect(shouldBeOrangeA).toBe('🟠 40%')

const shouldBeGreenA = colorizePercentageByThreshold(80, 75, 30)
expect(shouldBeGreenA).toBe('🟢 80%')
})

test('parse xml', async () => {
const ret = await parseXML(__filename)
expect(ret).toBeTruthy()

const ret1 = await parseXML(__filename + 'bar')
expect(ret1).toBeFalsy()
})

test('parse coverage', async () => {
const ret = await parseCoverage(__filename)
expect(ret).not.toBeNull

const ret1 = await parseCoverage(__filename + 'bar')
expect(ret1).toBeNull
})

test('getInputs', () => {
process.env.INPUT_GITHUB_TOKEN = 'token'
process.env.INPUT_FILENAME = 'filename.xml'

const f = getInputs()
expect(f).toStrictEqual({
token: 'token',
filename: 'filename.xml',
badge: false,
overallCoverageFailThreshold: 0,
fileCoverageErrorMin: 50,
fileCoverageWarningMax: 75,
failOnNegativeDifference: false,
markdownFilename: 'code-coverage-results',
artifactDownloadWorkflowNames: null,
artifactName: 'coverage-%name%',
negativeDifferenceBy: 'package',
retention: undefined
})
})
15 changes: 14 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: 'Code Coverage Report Difference'
description: 'Provides code coverage reports with the ability to see differences in a pull requests utilizing markdown files.'
author: 'ClearlyIP'
branding:
icon: 'file-text'
icon: 'file-text'
color: 'blue'
inputs:
filename:
Expand Down Expand Up @@ -43,6 +43,19 @@ inputs:
description: 'Artifact name. Use %name% as a placeholder (must be included!)'
required: false
default: 'coverage-%name%'
negative_difference_by:
description: 'Determines how negative difference is evaluated. Possible values are "overall" and "package" (default)'
required: false
default: 'package'
negative_difference_threshold:
description: 'The percentage drop in coverage that should be allowed, in decimal form (0.05 == 5%). The default value is 0.'
required: false
default: '0'
retention_days:
description: 'The number of days to retain uploaded artifacts. When `null` (default), the default retention period for the repository is used.'
required: false
default: null

outputs:
file:
description: 'The generated markdown file path'
Expand Down
Loading

0 comments on commit 5b20877

Please sign in to comment.