Coverage badge in Gitlab CI with Python coverage always unknown
Asked Answered
C

5

22

I am trying to show a coverage badge for a Python project in a private Gitlab CE installation (v11.8.6), using coverage.py for Python. However, the badge always says unknown.

This is the relevant job in my .gitlab-ci.yaml file:

coverage:
    stage: test
    before_script:
        - pip3.6 install coverage
        - mkdir -p public
    script:
        - coverage run --source=my_service setup.py test
        - coverage report | tee public/coverage.txt
    artifacts:
        paths:
            - public/coverage.txt
    coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'

I expected the badge to show the actual coverage at this URL, so this is what I have entered in the project settings under General/Badges:

http://<privategitlaburl>/%{project_path}/badges/%{default_branch}/coverage.svg?job=coverage

I read these instructions using Gitlab pages. However, I do not want to use pages just for this purpose, and I am dealing with a Python project.

According to the example in the CI/CD settings, and in this post, the regex in the coverage entry should work. which I could confirm by trying it locally:

$ grep -P "TOTAL\s+\d+\s+\d+\s+(\d+%)" public/coverage.txt
TOTAL                                           289     53    82%

I also tried the same regex in the field Test coverage parsing in the project settings under CI/CD/Pipeline settings, but the badge shown on that same page keeps showing unknown.

The documentation is not quite clear to me, as it does not describe the whole procedure. It is clear how to use a badge once created, and there is a manual for publishing a coverage report to pages, but there seems to be no clear path from extracting the score to displaying the badge.

Should I use the coverage entry in my .gitlab-ci.yaml file or fill in the regex in the pipeline settings?

Either way, is Gitlab CI supposed to update the coverage badge based on that, or do I need to use additional tools like coverage-badge to do so?

Where is the extracted coverage score supposed to be reported; how can I find out if my regex works?

Clavichord answered 14/5, 2019 at 16:52 Comment(4)
Update: this actually works for displaying the coverage in a Gitlab CI pipeline, but does not generate a badge. Maybe this is the expected behaviour, but who knows?Clavichord
Hey @Carsten, were you able to find a way out for getting the percentage?Wedurn
@Junkrat No update from my side, sorry.Clavichord
I had similar issue when Badge successfully worked on feature branch, but had Unknown on master. The issue was in pipeline settings. On Master branch we had additional last step that was manual (Rollback). That is why actual status of the build was BLOCKED. But coverage badge is waiting for last Successful pipeline. So, removeing tha last step made pipline status SUCCESS and Badge started to work fine!Larger
P
19

I finally got the coverage badge displaying a percentage instead of unknown today for my python project. Here's the relevant content from my .gitlab-ci.yml:

job:
 script:
  - 'python -m venv venv'
  - '.\venv\Scripts\activate'
  - 'python -m pip install -r requirements.txt'
  - 'coverage run --source=python_project -m unittest discover ./tests'
  - 'coverage report --omit=things_that_arent_mine/*'
  - 'coverage xml'
 artifacts:
  reports:
   cobertura: 'coverage.xml'

I'm also using the regex for gcovr listed in the repo CI/CD Settings > General Pipelines > Test coverage parsing which I found after reading this as well as the second to last comment on this:

^TOTAL.*\s+(\d+\%)$

In the repo General Settings > Badges, my badge link is:

http://gitlab-server/%{project_path}/-/jobs

and my badge image url is:

http://gitlab-server/%{project_path}/badges/%{default_branch}/coverage.svg

I don't quite know what the Cobertura report artifact is for (I think it specifically has to do with merge requests) but I have it in there because the tutorials took me down that road. I did confirm that removing the following from the .gitlab-ci.yml doesn't break the badge or coverage number on the jobs page:

  - 'coverage xml'
 artifacts:
  reports:
   cobertura: 'coverage.xml'

While removing or commenting:

- 'coverage report --omit=things_that_arent_mine/*'

does break the badge as well as the coverage number displayed on the CI/CD jobs page of the repo. I also tried some regex variations that I tested in rubular but the only one that didn't cause gitlab to barf was the gcovr one.

Hopefully this helps out, it was kind of difficult and arduous to piece together what was needed for this badge to work on a python project.

EDIT: Also just figured out how to add some sexy precision to the coverage percentage number. If you change the coverage report line of the .gitlab-ci.yml to:

- 'coverage report --omit=things_that_arent_mine/* --precision=2'

And the regex in CI/CD Settings > General Pipelines > Test coverage parsing to:

^TOTAL.+?(\d+.\d+\%)$

That should give you a very precise coverage number that effectively no one but you and I will care about. But by gosh we'll know for sure if coverage is 99.99% or 100%.

Pub answered 6/11, 2020 at 2:52 Comment(2)
This is a good answer, but note that the project setting is deprecated per docs.gitlab.com/ee/update/…. So, what stackoverflow.com/users/223201/tom has is more likely to work for most.Concoction
GitLab documentation about Cobertura format: docs.gitlab.com/ee/ci/testing/test_coverage_visualization.htmlBalancer
T
5

A solution that worked for me:

In the .gitlab-ci.yml file, in the job that runs the coverage report, I added the following lines:

  script:
    # some lines omitted for brevity
    - coverage report --omit=venv/*
  coverage: '/TOTAL.*\s+(\d+\%)/'

In particular, I couldn't get the badge to show anything but unknown until I added the coverage directive to my test job. Bear in mind, different tools may print different output and so you will likely have to change the regular expression, as I did.

Thessalonian answered 31/8, 2021 at 17:1 Comment(1)
This also worked for a coverage report created in a tox script. No need to specify additional artifacts.Dorton
E
3

Spent three days on the problem above myself so I thought I'd post my working config. My project is a pyscaffolding project, uses tox, the pipeline triggers when you push a commit to a branch, and it pushes a pip package to the github packages library.

  1. Badge link is: http://gitlab.XXXX.com/XXmeXX/python-template/-/commits/develop

  2. Badge image is : http://gitlab.XXXX.com/XXmeXX/python-template/badges/develop/coverage.svg

  3. Regex is same as above.

  4. PYPIRC is an environment variable set in that looks like a .pypirc file and points to my internal pip registry.

  5. I used this tutorial

  6. updated -> --cov-report xml is in my setup.cfg and I'm pretty sure b/c of that I don't need the coverage command, but I haven't tested that since I wrote this post. I'll check that next time I'm in there.

My gitlab-ci.yml:

build-package:
  stage: deploy
  image: python:3.7
  script:
   - set
   - cat $PYPIRC > /tmp/.pypirc
   - pip3 install twine setuptools setuptools_scm wheel tox coverage
   # build the pip package
   - python3 setup.py bdist_wheel
   # $CI_COMMIT_TAG only works with the tagging pipeline, if you want to test a branch push directly, pull from fs
   - VERSION=$(python setup.py --version)
   # You can issue ls -al commands if you want, like to see variables or your published packages
   # - echo $VERSION
   # - ls -al ./dist |grep whl
   - tox
   - coverage xml -o coverage.xml
   # If you want to put artifacts up for storage, ...
   # - mkdir public
   - python3 -m twine upload --repository pythontemplate ./dist/my_python_template-${VERSION}-py2.py3-none-any.whl --config-file /tmp/.pypirc
 artifacts:
   reports:
     cobertura : 'coverage.xml'
   when: always
#   If you were copying artifacts up for later.
#  paths:
#     - public
 only:
  - branches

Biggest thing I learned was that first you get it showing as "Coverage" column in the jobs list, then you know you're parsing everything correctly and the regexes are working. From there you work on the coverage xml and the badge links.

Edgebone answered 19/7, 2021 at 20:23 Comment(0)
O
0

I also digged quite a little into this. And just as you said: The command coverage report produces output similar to this:

[...]
tests/__init__.py              0      0   100%
tests/test_ml_squarer.py       4      0   100%
tests/test_squarer.py          4      0   100%
----------------------------------------------
TOTAL                         17      2    88%
test_service run-test: commands[4] | coverage xml

and depending on the regex-expression that is saved, it simply looks for the 88% next to TOTAL. I used the recommend for pytest-cov (Python) , i.e. ^TOTAL.+?(\d+\%)$

regex expression

So running coverage xml looks rather optional to me at the moment. However, it is not working for me using: GitLab Community Edition 12.10.11

Ommatophore answered 21/1, 2021 at 5:0 Comment(3)
not or now? > However, it is not working for meClavichord
Unfortunately, it is not.Ommatophore
I did get it work using TOTAL.*\s+(\d+%)$Ommatophore
C
0

i got this working using an updated yml format.

  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: 'coverage.xml'
Commando answered 7/8, 2023 at 23:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.