DEV Community

Cover image for Coverage Badge with GitHub Actions - FINALLY!

Coverage Badge with GitHub Actions - FINALLY!

The Jared Wilcurt on December 28, 2020

This is the only documented way to get coverage badges with GitHub Actions. It took a few months of research, trial, and error; but eventually I go...
Collapse
 
rainabba profile image
Michael Richardson

I may be missing something here, but since this comes down to creating and stashing a .json file that can be accessed in the context of a viewer on the readme.md, couldn't a repo be used just as well (with a token generated having appropriate perms to commit changes to the repo/branch that will be used in the badge to retrieve that .json file?

Collapse
 
thejaredwilcurt profile image
The Jared Wilcurt

That's another way, abusing Gist just has fewer steps. And lower risk (can't accidentally give permissions to the wrong repo, just to your gists).

Collapse
 
mishakav profile image
Misha Kav

You can get PR number easily:

name: Test PR number
on:
  pull_request:
jobs:
  test-pr-num:
    runs-on: ubuntu-latest
    steps:
      - name: Get PR number
        run: |
          echo "Current PR Number is: ${{ github.event.pull_request.number }}"
Enter fullscreen mode Exit fullscreen mode
Collapse
 
forgetso profile image
Chris • Edited

You can update the pull request template after the coverage badge has been created with an additional step in your workflow:

    - name: Update the Badge URL in the pull request body
      run: |
        BODY=$(curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/<your-username>/<your-repo>/pulls/${{ github.event.pull_request.number }} | jq .body | sed -En "s/protocol__pull_##.json/protocol__pull_${{ github.event.pull_request.number }}.json/p")
        JSON="{\"body\":$(echo $BODY | jq -sR .)}"
        curl \
          -X POST \
          -H "Authorization: token ${{ secrets.GIST_SECRET }}" \
          -H "Content-Type: application/json" \
          -d $JSON \
          https://api.github.com/repos/<your-username>/<your-repo>/pulls/${{ github.event.pull_request.number }}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
paleika profile image
Nadezhda Ivashchenko

Needed to make a few changes for Yarn (no need to add --, have to trim 3 lines on the tail)
Made a tiny version to renew the gist file only on push to main branch (when you need to display only in Readme)

name: coverage badge
on:
  push:
    branches: [ master ]

jobs:
  checks:
    runs-on: ubuntu-20.04
    steps:
    - uses: actions/checkout@v2

    - name: Install modules
      run: yarn --prefer-offline

    - name: Run unit tests with coverage
      run: |
        SUMMARY="$(yarn test --coverage --coverageReporters=text-summary | tail -3 | head -1)"
        TOKENS=($SUMMARY)
        echo "COVERAGE=$(echo ${TOKENS[2]})" >> $GITHUB_ENV

    - name: Create Coverage Badge
      uses: schneegans/dynamic-badges-action@v1.1.0
      with:
        auth: ${{ secrets.GIST_SECRET }}
        gistID: <your_gist_id>
        filename: <your_repo>_coverage.json
        label: coverage
        message: ${{ env.COVERAGE }}
        namedLogo: jest
        color: blue
        logoColor: lightblue
Enter fullscreen mode Exit fullscreen mode
Collapse
 
yuriyyakym profile image
Yuriy Yakym

Instead of parsing text-summary output, you can use a json-summary reporter and then get values that you need with jq tool, like so:

- name: Get coverage output
  id: coverage
  run: echo "value=$(jq -r '.total.lines.pct|tostring + "%"' coverage/coverage-summary.json)" >> $GITHUB_OUTPUT
Enter fullscreen mode Exit fullscreen mode

You can see it in action at my repository.

Collapse
 
mishakav profile image
Misha Kav • Edited

There are more easiest way like this action Jest Coverage Comment

It works in PR/Push, can extract the coverage, and there are also example of how to update the Readme with coverage.

Collapse
 
fritx profile image
Fritz Lin • Edited

@mishakav @thejaredwilcurt consider this action, no secrets config at all.
It's simple and fits simple projects,
with a continuously updated badge output to gh-pages.
github.com/we-cli/coverage-badge-a...

Collapse
 
pbdesk profile image
Pinal Bhatt

Great post. finally, something without any paid third-party usages.

Collapse
 
wesleyscholl profile image
Wesley Scholl • Edited

Great article, I was able to implement this with a bit of tinkering. It might be good to note that the your-repo/.github/workflows/node.js.yml file needs to be configured with the gistID and filename (repo name):

- if: ${{ matrix.node-version == '14.x' }}
      name: Create the Badge
      uses: schneegans/dynamic-badges-action@v1.0.0
      with:
        auth: ${{ secrets.GIST_SECRET }}
        gistID: 7d4c25ef2e97e8de523ef7c1fee26e8e # <-- Update this
        filename: your-repo-name__${{ env.BRANCH }}.json # <-- And this
Enter fullscreen mode Exit fullscreen mode
Collapse
 
apomalyn profile image
Xavier Chretien

Since one or two weeks Shield.io display "domain is blocked" when using this technique. Am I the only one getting this error?

Collapse
 
thejaredwilcurt profile image
The Jared Wilcurt

Just tested with https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/TheJaredWilcurt/9c5d16fe3fa8f8ef414fe8b0eff17f7f/raw/red-perfume__pull_31.json and it is working fine for me.