In this post join me as I publish a project's unit tests coverage report to GitHub Pages using GitHub actions.
Your project probably has a coverage report. If you’re using Jest as your unit test runner, generating a coverage report is embedded in it. It is done with Istanbul under the hood, which generates a nice HTML page presenting the entire project unit test coverage.
I too have this kind of coverage, but it's a little bit more advanced since I wanted to have a coverage report for the entire packages under a single Monorepo. You can read how I achieved that in this post.
It’s lovely that there’s a coverage report for all packages, which I can trigger manually in my local env, but I would like it to be accessible to anyone who wishes to check up the coverage status of the project.
In other words, I would like a way to publish my report somewhere public.
Luckily GitHub offers “GitHub pages” which simply put is “Websites for you and your projects”. I wonder if I can harness its powers for this goal.
It’s always a good idea to set the requirement before rushing into coding, so here they are:
- Automate the creation of a GitHub page displaying the current coverage
- Have this automation triggered when pushes are made to “master” branch
- Grab a beer
Here we go!
Prerequisites
Just before we start, you should have a script which generates a coverage report. In a simple project, using Jest, generating the coverage can be done by running Jest with the --coverage
option. I’m counting that you have such a script that can be triggered from a GitHub action.
The project I’m about to implement this on is a Monorepo called “Pedalboard” which I maintain. In it I’ve created a script which aggregates coverage reports from all nested packages into a single report residing at the project’s root. You can read more about it here.
The command used to generate this report is
yarn coverage:combined
GitHub pages
How do we enable GitHub pages in our project to begin with?
Go to your repo’s settings, and under the “Pages” menu item you will see the GitHub pages “wizard”. Here is an image which will help us with the following explanations :
As you can see you can choose whether you’d like the site to be generated by GitHub action or deploy from a branch. Since I need to generate the report before deploying it I will choose the GitHub action option (note that this option is Beta).
As you can see in the image above there are 2 options under it as well - I will choose the Static HTML since my script creates a “coverage” directory and in it you will have a static index.html
which is the main doc of the report. I click the “Configure” button and move on.
The Action’s YAML
GitHub now presents the YAML file for the new workflow. Here it is:
# Simple workflow for deploying static content to GitHub Pages
name: Deploy static content to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["master"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow one concurrent deployment
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Pages
uses: actions/configure-pages@v2
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
# Upload entire repository
path: '.'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1
Obviously we need to do some modifications to it. Let’s start -
We change the name of the YAML file to “coverage-report” and we change the description to fit our intention.
The next lines describe when this action should be triggered, and OOTB it triggers when push is made to the “master” branch. This means that the build-and-publish workflow and the coverage-report workflow will start together and run in parallel. I know that it is not the most optimized way of synching between the 2 workflows, but for now it will do fine.
Next we would like to generate our report, before we can deploy it. For this purpose I’m adding 2 commands to the workflow - installing Yarn dependencies and running the coverage:combine
- run: yarn
- run: yarn coverage:combined
Now, let’s have a look at another important line which tells the action which path to deploy from:
with:
# Upload entire repository
path: '.'
Currently it points to the project’s root, and this is not what we’re aiming for. We want the site content to be taken from the generated coverage directory. I change it into this:
with:
# Upload the coverage directory from the repository
path: './coverage/lcov-report'
Let’s check if this action does what it should. I’m committing the new workflow file (from GitHub). And sure enough when we commit it to master the action is triggered:
It completes successfully and if we navigate to https://mbarzeev.github.io/pedalboard/ we will get our combined coverage report!
Here is how the final workflow’s YAML looks like:
# A workflow for deploying the Unit Tests coverage report to GitHub Pages
name: Deploy coverage report to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ['master']
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow one concurrent deployment
concurrency:
group: 'pages'
cancel-in-progress: true
jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- run: yarn
- run: yarn coverage:combined
- name: Setup Pages
uses: actions/configure-pages@v2
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
# Upload the coverage directory from the repository
path: './coverage/lcov-report'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1
Wrapping up
Exposing reports such as this coverage report is very helpful for stakeholders to understand where projects stand in terms of quality and where are the parts that are more prone to regressions.
Having the coverage report as the main page of your project at GitHub though, is not the most elegant way of doing it, so you might wanna generate a “real” main HTML page which links to the report (and other generated reports), but that’s out of the scope of this post :)
As always, if you have any questions or ideas on how this can be done better, please share them with us in the comments section below.
Hey! If you liked what you've just read check out @mattibarzeev on Twitter 🍻
Photo by Christin Hume on Unsplash
Top comments (0)