CircleCI Pipeline

Add the following job to your .circleci/config.yml. It triggers on pushes to the configured branches:
version: 2.1

jobs:
  test-coverage:
    docker:
      - image: cimg/python:3.11
    
    environment:
      API_BASE: https://api.codeant.ai
    
    steps:
      - checkout
      
      - run:
          name: Extract repository information
          command: |
            # CircleCI provides these automatically
            echo "Repository: ${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}"
            echo "Branch: ${CIRCLE_BRANCH}"
            echo "Commit: ${CIRCLE_SHA1}"
      
      - run:
          name: Run tests and generate coverage
          command: |
            # Activate virtual environment if exists
            if [ -f .venv/bin/activate ]; then
              source .venv/bin/activate
            fi
            
            # Install coverage tools
            pip install coverage pytest
            
            # Run tests with coverage
            coverage run -m pytest tests/
            coverage xml -o coverage.xml
            
            # Display coverage report
            cat coverage.xml
      
      - run:
          name: Fetch coverage-upload script
          command: |
            curl -sS -X GET "${API_BASE}/pr/analysis/coverage/script/get" \
              --output upload_coverage.sh.b64
      
      - run:
          name: Make script executable
          command: |
            base64 -d upload_coverage.sh.b64 > upload_coverage.sh
            chmod +x upload_coverage.sh
      
      - run:
          name: Upload coverage and set status
          command: |
            bash upload_coverage.sh \
              -t "${ACCESS_TOKEN}" \
              -r "${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}" \
              -c "${CIRCLE_SHA1}" \
              -f coverage.xml \
              -p github \
              -b "${CIRCLE_BRANCH}"
      
      - run:
          name: Clean up
          when: always
          command: |
            rm -f upload_coverage.sh upload_coverage.sh.b64
      
      - store_artifacts:
          path: coverage.xml
          destination: coverage-reports

workflows:
  version: 2
  build:
    jobs:
      - test-coverage:
          context: codeant-context
For monorepo projects, add the module name parameter -m module_name to the upload script. You can upload multiple coverage files using multiple -m flags.

Environment Variables Configuration

Add your access token to CircleCI:
  1. Go to Project Settings -> Environment Variables
  2. Click Add Environment Variable
  3. Add variable name: ACCESS_TOKEN
  4. Paste your GitHub access token as the value
  5. Click Add Environment Variable
Alternatively, use a context for organization-wide settings:
  1. Go to Organization Settings -> Contexts
  2. Create a context named codeant-context
  3. Add the ACCESS_TOKEN variable with your GitHub access token

Token Permissions

The access token requires the following permissions:
  • Metadata: Read-only access
  • Commit statuses: Read and write access
These permissions allow the token to access repository metadata and update commit status checks for coverage reporting.

Coverage config file

You have to create a .coveragerc file in the project’s root folder to include all the source files in the test coverage calculation. Example:
# include every Python file under the repo root
source = .

# exclude tests, virtualenvs, build artifacts, etc.
omit =
    */tests/*
    */.venv/*
    */build/*
    */dist/*
When you assign source to ”.” , It checks for every python file in the root folder and its sub directories. You can omit some directories by placing them in the omit section of the file.

How it works

With the above configuration:
  1. coverage run -m pytest tests/ will count every .py under the workspace as “valid” lines except for those in the omitted directories.
  2. Lines actually executed by your tests are marked “covered.”
  3. coverage xml -o coverage.xml produces a Cobertura-style report reflecting true coverage over the entire codebase.
  4. Using this coverage xml, we calculate the coverage percentage and the status check will be done on every new push to the branch.

Troubleshooting

Coverage file not found

If the coverage file is not generated:
  • Verify tests are running successfully
  • Check that coverage is installed: pip install coverage
  • Ensure the correct test command is used
  • Check the working directory

Upload fails with authentication error

If you see “Access token invalid”:
  • Verify the ACCESS_TOKEN environment variable is correctly configured
  • Ensure the token has the required permissions
  • Check that you’re using the correct context or project environment variables

Coverage percentage is 0%

If coverage shows 0%:
  • Check your .coveragerc configuration
  • Verify the source paths are correct
  • Ensure tests are actually exercising the code
  • Check omit patterns aren’t excluding too much

Branch name extraction issues

CircleCI automatically provides:
  • CIRCLE_BRANCH: The branch name
  • CIRCLE_SHA1: The commit SHA
  • CIRCLE_PROJECT_USERNAME: The organization/username
  • CIRCLE_PROJECT_REPONAME: The repository name