From 44f1924a14d968e69c6d965db2d1254a160d3bd9 Mon Sep 17 00:00:00 2001 From: Tomas Zijdemans <113360400+tomas-zijdemans-vipps@users.noreply.github.com> Date: Mon, 18 Dec 2023 10:50:58 +0100 Subject: [PATCH] Ci coverage (#5) * ci: Add code coverage script --- .github/workflows/deno.yml | 9 ++++-- .gitignore | 4 +-- scripts/coverage.ts | 66 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 scripts/coverage.ts diff --git a/.github/workflows/deno.yml b/.github/workflows/deno.yml index 63c2370..f1b8f93 100644 --- a/.github/workflows/deno.yml +++ b/.github/workflows/deno.yml @@ -8,14 +8,17 @@ on: jobs: deno: - runs-on: macos-latest + runs-on: ubuntu-latest steps: - name: Setup repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Deno - run: brew install deno + run: sudo snap install deno - name: Run tests run: deno fmt --check && deno lint && deno test --allow-net --parallel tests/ + + - name: Check coverage + run: deno run -A scripts/coverage.ts diff --git a/.gitignore b/.gitignore index d017ef9..15a0881 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ .DS_Store -.coverage -lcov.info -staging/ +coverage/ .env \ No newline at end of file diff --git a/scripts/coverage.ts b/scripts/coverage.ts new file mode 100644 index 0000000..8f5eb09 --- /dev/null +++ b/scripts/coverage.ts @@ -0,0 +1,66 @@ +/** + * Calculates and checks the branch coverage of a Deno project. + * + * @remarks + * This script runs the tests with coverage enabled and then analyzes the coverage results. + * If the branch coverage is below a specified threshold, it exits with an error. + * + * @param THRESHOLD - The minimum branch coverage threshold (in percentage) required for the project. + */ + +// Minimum branch coverage threshold (in percentage) +const THRESHOLD = 90; + +const getCommandOutput = async (command: Deno.Command) => { + const { code, stdout, stderr } = await command.output(); + const error = new TextDecoder().decode(stderr); + if (code || error) { + console.error(error); + Deno.exit(1); + } + const output = new TextDecoder().decode(stdout); + return output; +}; + +// Run tests with coverage enabled +const testCmd = new Deno.Command(Deno.execPath(), { + args: [ + "test", + "--coverage", + ], +}); + +// Check that the command ran successfully +await getCommandOutput(testCmd); + +// Calculate branch coverage +const covCmd = new Deno.Command(Deno.execPath(), { + args: [ + "coverage", + "./coverage", + ], +}); + +// Check that the command ran successfully +const coverageReport = await getCommandOutput(covCmd); + +// Remove ANSI escape codes +const words = coverageReport.replaceAll("\x1b", " ").split(" "); + +// Remove all non-numbers +const floats = words.filter((word) => !isNaN(parseFloat(word))); + +// Pick the second last number +const branchTotal = parseFloat(floats.at(-2) || ""); + +if (!branchTotal) { + console.error("Could not retrieve branch coverage"); + Deno.exit(1); +} + +if (branchTotal > THRESHOLD) { + console.log(`Branch coverage is good: ${branchTotal}`); +} else { + console.log(`Branch coverage is bad: ${branchTotal}`); + Deno.exit(1); +}