Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SonarQube 6.0 get code coverage for a specific version of a project

I am trying to write a tiny script that

  1. Gets the versions of all microserves that are in a particular environment (solved)

  2. For each project/version gets the sonarqube code coverage for that exact version. I am having problems getting sonarqube coverage for an exact version of a particular project.

I am using sonarqube 6.0 (as per my /api/server/version endpoint) (I hope that we can upgrade to 6.4 the latest soon, but that's not in my direct control and I don't want to wait for it)

My problem is- I can't tie the data together, because when I call the /api/events endpoint, I only get back date and coverage for a project, not version. Here is a working code sample (credentials and base url not included)

I would be happy to solve this in any language- ruby, python, php, java, js, whatever works.

#!/usr/bin/ruby
require 'rest-client'
require 'json'
require 'ostruct'
require 'date'
require 'nokogiri'

projects_endpoint='/api/projects/'
time_machine_endpoint='/api/timemachine/'
events_endpoint='/api/events'

rc = RestClient::Resource.new(server_url, user, pass)
sonarqube_projects = JSON.parse(rc["#{projects_endpoint}index?format=json"].get, object_class: OpenStruct)

coverage_per_project = sonarqube_projects.map {|sq_project|
  # data shape: #<OpenStruct id="1687", k="foo-project", nm="foo-project", sc="PRJ", qu="TRK", lv="0.0.617", v=#<OpenStruct 0.0.617=#<OpenStruct sid="4197", d="2017-07-18T03:50:48+0000">>>
  project_name = sq_project.k
  url = "#{time_machine_endpoint}?format=json&resource=#{project_name}&metrics=coverage"
  events = JSON.parse(rc[url].get, object_class: OpenStruct)

  # data shape:
  # [#<OpenStruct cols=[#<OpenStruct metric="coverage">], cells=[#<OpenStruct d="2016-12-08T19:26:24+0000", v=[68.0]>, #<OpenStruct d="2016-12-08T19:36:46+0000", v=[68.0]>, #<OpenStruct d="2016-12-08T20:26:28+0000", v=[79.5]>, #<OpenStruct d="2016-12-08T20:36:53+0000", v=[79.5]>]
  # my problem is right here- I need a version of the app in each cells object so that I can search for one that matches my deployed version!

  # idealistic pseudo-code that doesn't work:
  correct_event = events.first {|event|
    event.version == my_deployed_app_version
  }

  return {project_name: project_name, coverage: correct_event.coverage}
}
puts coverage_per_project
like image 916
compiledweird Avatar asked Jul 18 '17 04:07

compiledweird


People also ask

How do I get code coverage in SonarQube?

Code coverage is a metric that teams use to measure the quality of their tests, and it represents the percentage of production code that has been tested. Discover how to apply the Gradle Jacoco plugin to your project and run a SonarQube scan to generate a code coverage report.

Which tool is used to analyze the code coverage in SonarQube?

SonarQube and JaCoCo are two tools that we can use together to make it easy to measure code coverage. They also provide an overview of the overall health of the source code by finding code duplications, bugs and other issues in the code. This helps us to know whether our code is production-ready or not.

Does SonarLint show code coverage?

SonarLint doesn't compute code coverage. To have the code coverage, you should use one of the scanners with SonarQube.

What is difference between JaCoCo and SonarQube?

JaCoCo vs SonarQube: What are the differences? JaCoCo: A code coverage library for Java. It is a free code coverage library for Java, which has been created based on the lessons learned from using and integration existing libraries for many years; SonarQube: Continuous Code Quality.


1 Answers

Starting with SonarQube 6.3

To get the measures of a specific version (because it's the use case), you need to use 2 Web Services:

  • One WS call to know the analysis date of the version you want
    • Ex: https://sonarcloud.io/api/project_analyses/search?project=sonarqube-scanner&category=VERSION
    • This will return something like:
{

    "paging": {
        "pageIndex": 1,
        "pageSize": 100,
        "total": 10
    },
    "analyses": [
        {
            "key": "AV07Vpk4NAVDjyrgWPAw",
            "date": "2017-07-13T11:45:12+0200",
            "events": [
                {
                    "key": "AV07VpslNAVDjyrgWPAx",
                    "category": "VERSION",
                    "name": "1.4.0"
                }
            ]
        },
...
}
  • Once you have found the date of the version you're looking for, one WS call to retrieve the metrics you want:
    • Ex: https://sonarcloud.io/api/measures/search_history?component=sonarqube-scanner&metrics=coverage&from=2017-07-13T11:45:12%2B0200&to=2017-07-13T11:45:12%2B0200
    • Note: make sure that you encode the '+' sign (with "%2B")
    • This will return something like:
{

    "paging": {
        "pageIndex": 1,
        "pageSize": 100,
        "total": 1
    },
    "measures": [
        {
            "metric": "coverage",
            "history": [
                {
                    "date": "2017-07-13T11:45:12+0200",
                    "value": "51.1"
                }
            ]
        }
    ]

}

Prior to SonarQube 6.3

The principle is the same, but the WS differ:

  • For the first call, you probably want to use the /api/events WS that returns a slightly different JSON document.
    • see the contract of this "old" WS on our archived documentation
  • For the second call, /api/timemachine should do the work with the date that was returned by the first WS call
    • see the contract of this "old" WS on our archived documentation
like image 165
Fabrice - SonarSource Team Avatar answered Oct 10 '22 00:10

Fabrice - SonarSource Team