diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c21cdf..2f5b5d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,9 @@ jobs: node bin/check-coverage to/main2.js node bin/only-covered main1.js main2.js + - name: Check totals 🛡 + run: node bin/check-total --min 90 + - name: Semantic Release 🚀 uses: cycjimmy/semantic-release-action@v2 env: diff --git a/README.md b/README.md index 683f3a3..b77756a 100644 --- a/README.md +++ b/README.md @@ -20,5 +20,15 @@ only-covered --from examples/exclude-files/coverage/coverage-final.json main.js check-coverage --from examples/exclude-files/coverage/coverage-final.json main.js ``` +## check-total + +If you generate coverage report using reporter `json-summary`, you can check the total statements percentage + +```shell +check-total +# with default options +check-total --from coverage/coverage-summary.json --min 80 +``` + [ci image]: https://github.com/bahmutov/check-code-coverage/workflows/ci/badge.svg?branch=master [ci url]: https://github.com/bahmutov/check-code-coverage/actions diff --git a/bin/check-total.js b/bin/check-total.js new file mode 100644 index 0000000..e5a266f --- /dev/null +++ b/bin/check-total.js @@ -0,0 +1,39 @@ +#!/usr/bin/env node +// @ts-check +const { join, resolve } = require('path') +const arg = require('arg') + +const args = arg({ + '--from': String, // input json-summary filename, by default "coverage/coverage-summary.json" + '--min': Number +}) + +const minStatementPercentage = args['--min'] || 80 +const fromFilename = args['--from'] || join('coverage', 'coverage-summary.json') +const coverageFilename = resolve(fromFilename) + +const coverage = require(coverageFilename) +const total = coverage.total +if (!total) { + console.error('Could not find "total" object in %s', fromFilename) + process.exit(1) +} + +// total should have objects for lines, statements, functions and branches +// each object should have total, covered, skipped and pct numbers +const statements = total.statements +if (!statements) { + console.error('Could not find statements in total %o', total) + process.exit(1) +} + +if (statements.pct < minStatementPercentage) { + console.log('🚨 Statement coverage %d is below minimum %d%%', statements.pct, minStatementPercentage) + console.log('file %s', coverageFilename) + process.exit(1) +} + +console.log( + '✅ Total statement coverage %d%% is >= minimum %d%%', + statements.pct, minStatementPercentage +) diff --git a/coverage/coverage-summary.json b/coverage/coverage-summary.json new file mode 100644 index 0000000..45a2ceb --- /dev/null +++ b/coverage/coverage-summary.json @@ -0,0 +1,4 @@ +{"total": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/gleb/git/instrument-example/src/App.js": {"lines":{"total":1,"covered":1,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":1,"covered":1,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +,"/Users/gleb/git/instrument-example/src/index.js": {"lines":{"total":2,"covered":2,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":2,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} +} diff --git a/package.json b/package.json index f5388a9..c10a290 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "index.js", "bin": { "check-coverage": "bin/check-coverage.js", - "only-covered": "bin/only-covered.js" + "only-covered": "bin/only-covered.js", + "check-total": "bin/check-total.js" }, "files": [ "bin"