Blog Post

Getting Started with the Codecov API v2

October 3, 2022 Tom Hu

A woman with a bright pink t-shirt sits on a cloud in the sky, smiling as she is working on her laptop. A dashboard with cloud-like traits forms to the right of her.

The Codecov API is used by many of our developers daily to understand and improve their code coverage. However, it has been many years since the release of updates to the API. As such, we are announcing a new v2 release of the API where we expect to make significant additions and improvements to our offerings since v1. This article helps explain what this means for users and how they can get started with the new API.

Documentation for the new API can be found here.

 

What’s changed since v1?

The move from v1 to v2 represents a shift in Codecov’s focus on supporting our users and our API. We have added three new endpoints that have been most requested by our users.

    1. Coverage Trends This endpoint will now provide users with aggregate coverage data over time for a repository. The intervals are currently set as 1d, 30d, and 7d.
    2. Flag List This endpoint provides a list of flags for a given repository.
    3. Flag Coverage Similar to the first item, this endpoint provides similar functionality except for a given flag. This helps to track coverage trends on a given flag of a repository over time.

 

What does this mean for v1 users?

The v1 endpoints are expected to be deprecated. This means that v1 users will need to update the API calls from v1 to v2 in order to start getting the new functionalities and to prevent any downtime. Most functionality between v1 and v2 should be the same, but existing users will still need to update their API calls accordingly.

There is currently no date scheduled for v1 deprecation, but we will maintain the endpoints at least 6 months after a date is announced.

 

Getting Started using Codecov API v2

For users not currently using the API, getting up and running should be fairly straightforward.

    1. First, log in to Codecov
    2. Click on your avatar in the top right corner and click on Settings.
    3. Under the Access tab on the left navigation menu, click Generate Token.

Name the token and copy the value where appropriate.

You can now use the token to access the API. As a test, you can hit the users list endpoint below.

curl --location --request GET 'https://codecov.io/api/v2/{{ SERVICE NAME }}/{{ ORGANIZATION NAME }}/users' \
--header 'Authorization: bearer {{ ACCESS TOKEN }}'

Be sure to replace {{ SERVICE NAME }}, {{ ORGANIZATION NAME }}, and {{ ACCESS TOKEN}}. A non-working example is provided below:

curl --location --request GET 'https://codecov.io/api/v2/github/codecov/users' \
--header 'Authorization: bearer 12345678-90ab-cdef-1234-567890abcdef'

 

Example: Getting current coverage for all repositories

Now that we have successfully sent our first API request, let’s see what we can do with a bigger example.

Let’s create a quick dashboard to show the latest coverage on a large number of repositories. For the following example, we will be using python3 to chain together requests.

We will need to take advantage of two endpoints: (1) the repo list and (2) the commit list endpoints.

First, let’s write a function that will pull all repository names for an organization

from collections import defaultdict
import json
import requests

CODECOV_ENDPOINT = "https://codecov.io/api/v2/github/codecov/{}"
TOKEN_NAME = "{{ ACCESS TOKEN }}"
CODECOV_HEADERS = {
    'Authorization': 'bearer {}'.format(TOKEN_NAME)
}

def _get_all_repos():
    print('Retrieving all repos...', end=" ")
    endpoint = CODECOV_ENDPOINT.format('repos?page_size=500')
    response = requests.get(
        endpoint,
        headers=CODECOV_HEADERS,
    )
    repos = json.loads(response.content)['results']
    print("Found {} repositories".format(len(repos)))
    return sorted(repo['name'] for repo in repos, key=str.casefold)

The _get_all_repos the function will get all the repositories under the Codecov organization that you have access to. Note that we are setting the page_size to 500. This may not be advisable for organizations with many repositories, and you will need to handle pagination.

Now to get coverage for each repository, we can write the below function

def _display_coverage(repo_name):
    endpoint = CODECOV_ENDPOINT.format("repos/{}/commits".format(repo_name))
    response = requests.get(
        endpoint,
        headers=CODECOV_HEADERS,
    )
    content = json.loads(response.content)
    commit = None
    if content['count'] == 0:
        return
    print(repo_name, end=" ")

    for commit in content['results']:
        totals = commit['totals']
        if totals is None:
            continue

        coverage = totals.get('coverage', None)
        if coverage is not None:
            print('{}%'.format(coverage))
            return

    print('No coverage found on any commit')

Combining the functions gives us the below script.

from collections import defaultdict
import json
import requests

CODECOV_ENDPOINT = "https://codecov.io/api/v2/github/codecov/{}"
TOKEN_NAME = "{{ ACCESS TOKEN }}"
CODECOV_HEADERS = {
    'Authorization': 'bearer {}'.format(TOKEN_NAME)
}

def _get_all_repos():
    print('Retrieving all repos...', end=" ")
    endpoint = CODECOV_ENDPOINT.format('repos?page_size=500')
    response = requests.get(
        endpoint,
        headers=CODECOV_HEADERS,
    )
    repos = json.loads(response.content)['results']
    print("Found {} repositories".format(len(repos)))
    return sorted(repo['name'] for repo in repos)

def _display_coverage(repo_name):
    endpoint = CODECOV_ENDPOINT.format("repos/{}/commits".format(repo_name))
    response = requests.get(
        endpoint,
        headers=CODECOV_HEADERS,
    )
    content = json.loads(response.content)
    commit = None
    if content['count'] == 0:
        return
    print(repo_name, end=" ")

    for commit in content['results']:
        totals = commit['totals']
        if totals is None:
            continue

        coverage = totals.get('coverage', None)
        if coverage is not None:
            print('{}%'.format(coverage))
            return

    print('No coverage found on any commit')

def display_coverage_dashboard():
    repos = _get_all_repos()
    for repo in repos:
        _display_coverage(repo)

if __name__=="__main__":
    display_coverage_dashboard()

Running the script gives us the following output

Retrieving all repos... Found 143 repositories
bitrise-demo 84.21%
cf-flags-demo 75.0%
ci-repo 0.0%
codecov-action 95.91%
codecov-bash 47.02%
codecov-circleci-orb 100.0%
codecov-demo 54.05%
codecov-demo-full 54.05%
codecov-exe 71.15%
codecov-node 0.0%
codecov-perl 85.71%
codecov-python 59.0%
codecov-racket 60.78%
codecov-ruby 89.27%
cpp-11-standard 62.5%
dart 0.0%
…

 

Giving feedback for Codecov API v2

Codecov is dedicated to helping our users access data more efficiently. If you are using our API in novel ways or need support for other use cases, please send us any feedback that would be helpful for you and your teams.

Before we redirect you to GitHub...
In order to use Codecov an admin must approve your org.