Bitbucket repositoty status badges!

This is a short post to help you set up build status and test coverage badges for your Bitbucket repositories.

In the picture: Nice looking badges at the top of a Bitbucket repository (by the author)

Part 1: Just using this solution

Getting the files

  1. Download the bitbucket-pipelines.yml and status_badge.sh files found in this Github gist and add them to your repository:
    https://gist.github.com/shaypal5/064dd0254a9f32c7549f8d42c26fef90
  2. Create a ci folder at the root of your repository and move the status_badge.sh file there. The bitbucket-pipelines.yml should stay at the root of the repository

Dependecy installation

If your project is essentially a Python package which you install and then test, and you also manage extra_requires test dependecies, then add the following two dependecies to your extra_requires: {'test': …} of your setup.py : pybadges, coverage-badge

If not, the change line 11 at of the bitbucket-pipelines.yml — that currently installs the Python package at the repository’s root, including its test dependencies — to the following line:

pip install --user pybadges coverage-badge

Under it, add a line installing your code or its dependecies, as required for testing.

Coverage report

This method assumes you run your tests in some way that generate a .coverage report file, which is what the coverage-badge package uses to find out what is your test coverage and generate the badge with.

If you have none, I recommend using pytest , with the additional depencies of coverage and pytest-cov, and to run the pytest command with the cov flag: pytest --cov=myproj .

Setup the required Pipelines variables

Follows steps 1 and 2 here for your repository to populate the BITBUCKET_USERNAME and BITBUCKET_APP_PASSWORD variables:

https://support.atlassian.com/bitbucket-cloud/docs/deploy-build-artifacts-to-bitbucket-downloads/

You do not need to follow the later steps, as the bitbucket-pipelines.yml file already references them. You can read more about Bitbucket app passwords here.

Updating your README file to show the badges

I use a README.rst file (using the RestructuredText format), so this is how the top of my readme file looks, for a repository named my-project in an organization name myorg .

my-project
##########
|Build-Status| |Coverage|.. |Build-Status| image:: https://bitbucket.org/myorg/my-project/downloads/status.svg
:target: https://bitbucket.org/myorg/my-project/addon/pipelines/home#!/
.. |Coverage| image:: https://bitbucket.org/myorg/my-project/downloads/coverage.svg
:target: https://bitbucket.org/myorg/my-project/addon/pipelines/home#!/

If you you use markdown (as in README.md), the following should do:

# my-project[![Build-Status](https://bitbucket.org/myorg/my-project/downloads/status.svg)](https://bitbucket.org/myorg/my-project/addon/pipelines/home#!/)
[![Coverage](https://bitbucket.org/myorg/my-project/downloads/coverage.svg)](https://bitbucket.org/myorg/my-project/addon/pipelines/home#!/)

That’s it! If anything doesn’t work read part 2 to understand more about the solution. It should help you adapt the code or configuration to make it work for you.

Part 2: Understanding how it works

The required files

The solution is made up of several parts:

  1. bitbucket-pipelines.yml — This is the configuration file for Bitbucket’s CI/CD component, much like Github Actions or independent ones like Travis or Circle CI. Most of the logic goes here.
  2. status_badge.sh — A script generating the appropriate status and coverage badges. I placed this in a directory named ci in the root of my repository.
  3. README.rst (or README.md ) — Here you just reference the right urls for the generated badges.
  4. pytest.ini or arguments you provide to the pytest command — Not really a part of the solution, but the script assumes your testing phase generates a coverage report.

The overall structure

Since most of the work is done through the different steps configured by the bitbucket-pipelines.yml file, let’s start by going over the file, and the short status_badge.sh script it uses:

So the main point of this configuration is to run four pipeline steps on each commit to our master branch:

pipelines:
default:
- <<: *test
branches:
master:
- <<: *test
- <<: *upload-status-badge
- <<: *upload-coverage-badge
- <<: *build-status

The default part means only the test phase will run for commits to other branches, but for master we will perform the following four steps:

  1. Run the test phase, which will run all tests AND generate appropriate status.svg and coverage.svg files AND will save them (and the exit code returned by the pytest command) using the Bitbucket Pipelines artifacts mechanism.
  2. Upload the status badge to the Downloads section of your repository.
  3. Upload the coverage badge to the Downloads section of your repository.
  4. Run a step that will simply exit with the previously-stored exit value returned by pytest. This will make sure the build will fail if pytest fails, but will pass if everything goes fine.

This whole structure is the result of two technical details:

  • The easiest way, at the moment, to upload Bitbucket Pipelines build artifacts to the corresponding repository’s Downloads store/section is using the official bitbucket-upload-file docker/step (see here for details).
  • Bitbucket Pipelines does not, at the moment, support running pipeline steps after a step has failed. As a result, and since upload is done by separate steps, we can’t have the test step — and thus the pytest command — fail, and so we have to add a final step just to make the overall build status correspond to test results. Not very elegant, but it’s the best I could think of.

The solution I ended up with is to export an environment variable holding the exit status of the pytest into a shared_vars.sh file, and then use Bitbucket’s artifacts mechanism to save both this file and the two generated svg badges and have them carry over to future steps.

The way the shared_vars.sh file used here to export environment variables into and source environment variables from in a later stage can be generally used for communication between Bitbucket Pipelines stages.

Dependencies & assumptions

The python code used here has several Python package dependencies:

  • pytest runs the tests.
  • coverage and pytest-cov produce coverage reports on pytest runs
  • pybadges generates the build status badge.
  • coverage-badge generates the coverage badge.

Sources

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store