From 07c5332d1d5ad64a0388b98a31f44aa4befcceed Mon Sep 17 00:00:00 2001 From: Kilian Ciuffolo <385716+kilianc@users.noreply.github.com> Date: Tue, 14 May 2024 16:15:55 -0700 Subject: [PATCH] feat: add ability to set a min threshold for coverage (#32) --- .github/workflows/ci.yaml | 2 ++ README.md | 4 ++++ action.yaml | 16 ++++++++++++++- src/check-threshold.js | 15 ++++++++++++++ src/update-comment.js | 41 +++++++++++++++++++++++++++------------ 5 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 src/check-threshold.js diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 735ee33..acce089 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -27,9 +27,11 @@ jobs: make test - name: Go Beautiful HTML Coverage + if: always() uses: './' with: path: go-test-app-01/ + threshold: 66.7 - name: Go Beautiful HTML Coverage uses: './' diff --git a/README.md b/README.md index 99b39dc..3e6620c 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,10 @@ Once your test has ran and `cover.out` has been generated, the GHA does the foll # The relative path of your go project. Useful for monorepos and custom folder structures. # Default: ./ path: '' + + # The minimum % of coverage required. + # Default: 0 + threshold: '' ``` ## Examples diff --git a/action.yaml b/action.yaml index 89e3cb8..d3c95d0 100644 --- a/action.yaml +++ b/action.yaml @@ -17,6 +17,9 @@ inputs: path: description: The relative path of your go project. Useful for monorepos and custom folder structures. default: './' + threshold: + description: The minimum % of coverage required. + default: '0' runs: using: composite steps: @@ -69,4 +72,15 @@ runs: const script = require(`${process.env.GITHUB_ACTION_PATH}/src/update-comment.js`) const revision = '${{ github.event.pull_request.head.sha || github.sha }}' const path = '${{ inputs.path }}' - await script({ context, github }, path, revision) + const threshold = parseFloat('${{ inputs.threshold }}', 10) + await script({ context, github, path, revision, threshold }) + + - name: Check Coverage Threshold + uses: actions/github-script@v6 + with: + github-token: ${{ inputs.token }} + script: | + const script = require(`${process.env.GITHUB_ACTION_PATH}/src/check-threshold.js`) + const revision = '${{ github.event.pull_request.head.sha || github.sha }}' + const threshold = parseFloat('${{ inputs.threshold }}', 10) + await script({ threshold, revision }) diff --git a/src/check-threshold.js b/src/check-threshold.js new file mode 100644 index 0000000..036165a --- /dev/null +++ b/src/check-threshold.js @@ -0,0 +1,15 @@ +const fs = require('fs') + +const checkThreshold = module.exports = async ({ threshold, revision }) => { + const coverageText = fs.readFileSync(`go-cover/${revision}.txt`, 'utf8').split('\n').slice(0, -1) + const coverageTextSummary = coverageText[coverageText.length-1].split('\t').pop() + + const coverage = parseFloat(coverageTextSummary.replace('%', ''), 10) + + if (coverage < threshold) { + console.log(`\x1b[91m✘ coverage ${coverage}% < ${threshold}%`) + process.exit(1) + } + + console.log(`\x1b[92m✔ coverage ${coverage}% >= ${threshold}%`) +} diff --git a/src/update-comment.js b/src/update-comment.js index 85183ff..fd990ec 100644 --- a/src/update-comment.js +++ b/src/update-comment.js @@ -1,6 +1,6 @@ const fs = require('fs') -const updateCodeCoverageComment = module.exports = async ({ context, github }, path, revision) => { +const updateCodeCoverageComment = module.exports = async ({ context, github, path, revision, threshold }) => { const comments = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, @@ -14,23 +14,40 @@ const updateCodeCoverageComment = module.exports = async ({ context, github }, p const coverageText = fs.readFileSync(`go-cover/${revision}.txt`, 'utf8').split('\n').slice(0, -1) const coverageTextSummary = coverageText[coverageText.length-1].split('\t').pop() - const pathText = (path !== './' ? ` for \`${path}/\`` : '').replace('//', '/') + const coverage = parseFloat(coverageTextSummary.replace('%', ''), 10) + const coverageEmoji = coverage >= threshold ? '' : `🔻 ${(coverage - threshold).toFixed(1)}% ` + const pathText = (path !== './' ? ` for ${path}/` : '').replace('//', '/') const commentBody = [ ``, - `### [Code Coverage Report 🔗](https://${context.repo.owner}.github.io/${context.repo.repo}/?hash=${revision})${pathText} at ${revision}`, + `##### ${coverageEmoji}[🔗 Code Coverage Report](https://${context.repo.owner}.github.io/${context.repo.repo}/?hash=${revision})${pathText} at ${revision}`, '```', - `Total: ${coverageTextSummary}`, - '```', - '
', - 'Full coverage report', - '', - '```', - ...coverageText, - '```', - '
', + `📔 Total: ${coverageTextSummary}`, ] + if (threshold > 0) { + commentBody.push( + `🎯 Threshold: ${threshold}%`, + ) + + if (coverage >= threshold) { + commentBody.push(`✅ ${coverageTextSummary} >= ${threshold}%`) + } else { + commentBody.push(`❌ ${coverageTextSummary} < ${threshold}%`) + } + } + + commentBody.push( + '```', + '
', + 'Full coverage report', + '', + '```', + ...coverageText, + '```', + '
', + ) + const upsertCommentOptions = { owner: context.repo.owner, repo: context.repo.repo,