Introduction
This blog post demonstrates how to add badges to a Python project on GitLab.
The "pipeline" and "coverage" badges are the two badges that I like to include for each Python project that I have on GitLab. They provide a quick overview of the status of the project.
This blog post assumes that the Python project is using GitLab CI (Continuous Integration) to run a job that calculates the test coverage, such as using the
pytest-cov
package.
Add the Badges
Start with a Python project in GitLab that doesn’t have any badges:
In the left-hand navigation pane, scroll down to the bottom and select ‘Settings’ –> ‘General’:
Scroll down to the ‘Badges’ sections and click on ‘Expand’:
Add the ‘Pipeline Status’ badge:
The values to fill in to the three fields are:
- Name: Pipeline Status
- Link: https://gitlab.com/%{project_path}/-/commits/%{default_branch}
- Badge image URL: https://gitlab.com/%{project_path}/badges/%{default_branch}/pipeline.svg
Add the ‘Test Coverage’ badge:
The values to fill in to the three fields are:
- Name: Test Coverage
- Link: https://gitlab.com/%{project_path}/-/commits/%{default_branch}
- Badge image URL: https://gitlab.com/%{project_path}/badges/%{default_branch}/coverage.svg
At the bottom of the ‘Badges’ section, you should now see that both badges have been added:
However, the ‘Test Coverage’ badge is still reporting an "unknown" coverage...
GitLab CI Script
The ‘Test Coverage’ badge uses a regex (Regular Expression) to parse the results of running a test coverage job in the CI (Continuous Integration) pipeline.
In the .gitlab-ci.yml file for your project, the job that runs your test coverage tool needs to updated to include a new coverage
element:
coverage:
stage: Test
script:
- python -m pytest --cov-report term-missing --cov=project
coverage: '/^TOTAL.+?(\d+\%)$/'
The last line is a regex to extract the total coverage from the last line in the ‘Coverage’ job that runs in the Gitlab CI pipeline:
Name Stmts Miss Cover Missing
-------------------------------------------------
bild/__init__.py 0 0 100%
bild/directory.py 47 1 98% 43
bild/file.py 88 14 84% 49, 77-82, 94-96, 102-103, 111-112
-------------------------------------------------
TOTAL 135 15 89%
For more information about how to parse other coverage reports:
For reference, here is a typical GitLab CI script (.gitlab-ci.yml) that I use to run a static analysis tool (flake8), run all the tests (pytest), and collect the test coverage metrics (pytest-cov):
# Tagged releases of Python docker images can be found at:
# https://hub.docker.com/r/library/python/tags/
image: python:3.10
# Change pip's cache directory to be inside the project directory since we can
# only cache local items.
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
# Pip's cache doesn't store the python packages
# https://pip.pypa.io/en/stable/reference/pip_install/#caching
#
# If you want to also cache the installed packages, you have to install
# them in a virtualenv and cache it as well.
cache:
paths:
- .cache/pip
- venv/
before_script:
- python --version # Print out python version for debugging
- python3 -m venv venv
- source venv/bin/activate
- pip install -r requirements.txt
stages:
- Static Analysis
- Test
flake8:
stage: Static Analysis
script:
- flake8 --max-line-length=150 --ignore=E266 *.py project/*.py project/*/routes.py
pytest:
stage: Test
script:
- python -m pytest
coverage:
stage: Test
script:
- python -m pytest --cov-report term-missing --cov=project
coverage: '/^TOTAL.+?(\d+\%)$/'
In order to have the regex change take effect, a new commit needs to be made to the default branch for the project:
$ git commit -m “Update GitLab CI script”
$ git push origin main
Wait for GitLab CI pipeline to run:
Once the pipeline completes, you should see the badges working in the ‘Project Overview’ section:
Conclusion
This blog post demonstrated the steps for adding badges to a Python project in GitLab.