Codecov YAML Configuration: Flags, Thresholds, and PR Comments

Codecov YAML Configuration: Flags, Thresholds, and PR Comments

Codecov's codecov.yml file controls thresholds, PR comments, coverage flags, carryforward settings, and ignore patterns. Without it, Codecov uses defaults that may not match your project's standards. This guide covers the most useful settings.

Key Takeaways

codecov.yml lives at the root of your repository. Codecov reads it automatically on every upload.

coverage.status controls when checks pass or fail. Configure target percentage, threshold (allowed drop), and which flags to evaluate.

Flags group coverage reports. Use flags to separate unit test coverage from integration test coverage, then set independent thresholds.

carryforward handles tests that don't run on every commit. Tells Codecov to carry the last known coverage for a flag when it's not uploaded in this run.

ignore excludes files from coverage calculations. Use globs to exclude generated code, test helpers, and vendor directories.

Basic codecov.yml Structure

# codecov.yml
coverage:
  status:
    project:
      default:
        target: 80%          # fail if total coverage drops below 80%
        threshold: 2%        # allow up to 2% drop without failing
    patch:
      default:
        target: 80%          # fail if new code in PR is below 80% covered

ignore:
  - "**/*.test.ts"
  - "src/generated/**"
  - "vendor/**"
  - "**/__fixtures__/**"

comment:
  layout: "reach, diff, flags, files"
  behavior: default
  require_changes: true       # only comment when coverage changes

Coverage Status Checks

Codecov posts two status checks to PRs: project (overall coverage) and patch (coverage on new/changed code).

Project Status

coverage:
  status:
    project:
      default:
        # Fail if project coverage drops more than 5% below target
        target: auto          # use current project coverage as target
        threshold: 5%
        base: auto

      # Override for specific paths
      frontend:
        paths:
          - src/frontend/**
        target: 70%           # lower threshold for frontend

      backend:
        paths:
          - src/backend/**
        target: 85%

Patch Status (New Code in PRs)

coverage:
  status:
    patch:
      default:
        target: 80%           # new code must be 80% covered
        threshold: 0%         # no tolerance for new uncovered code
        only_pulls: true      # only enforce on pull requests

Set target: off to disable patch checks:

coverage:
  status:
    patch: off

Flags for Separated Test Suites

Flags let you track coverage from different test suites independently:

# codecov.yml
flags:
  unit:
    paths:
      - src/
    carryforward: false

  integration:
    paths:
      - src/
    carryforward: true        # carry forward if integration tests didn't run

In CI, upload with the appropriate flag:

# GitHub Actions
- name: Upload unit test coverage
  uses: codecov/codecov-action@v4
  with:
    files: coverage/lcov.info
    flags: unit

- name: Upload integration test coverage
  uses: codecov/codecov-action@v4
  with:
    files: coverage/integration-lcov.info
    flags: integration

Set status checks per flag:

coverage:
  status:
    project:
      unit:
        flags:
          - unit
        target: 85%
      integration:
        flags:
          - integration
        target: 75%

Carryforward

When a test suite doesn't run on every commit (e.g., integration tests only on main branch), Codecov would show 0% for that flag on commits that skip those tests. Carryforward uses the last known value instead:

flags:
  integration:
    carryforward: true      # use last integration coverage if not uploaded
    carryforward_mode: labels  # more accurate — carries per-file, not just total

Two modes:

  • carryforward: true — carries the total coverage percentage
  • carryforward_mode: labels — carries per-file coverage (requires Codecov Enterprise or Teams plan)

PR Comment Customization

comment:
  # What to show in the comment
  layout: "reach, diff, flags, files, footer"
  
  # When to comment
  behavior: default           # comment on every PR
  # behavior: once            # comment once, update on new commits
  # behavior: new             # new comment on every new commit (noisy)
  
  require_changes: true       # only comment if coverage changed
  require_base: true          # only comment if base coverage report exists
  
  # Hide individual files below this coverage threshold
  hide_project_coverage: false
  
  after_n_builds: 2          # wait for 2 CI runs before commenting

Ignore Patterns

ignore:
  # Test files
  - "**/*.test.ts"
  - "**/*.test.tsx"
  - "**/*.spec.js"
  - "src/**/__tests__/**"

  # Generated code
  - "src/generated/**"
  - "**/*.pb.ts"          # protobuf
  - "**/*.graphql.ts"     # generated GraphQL types

  # Build output
  - "dist/**"
  - "build/**"
  - ".next/**"

  # Vendor/dependencies
  - "vendor/**"
  - "node_modules/**"

  # Test fixtures and mocks
  - "**/__fixtures__/**"
  - "**/mocks/**"
  - "src/testing/**"

  # Config files at root
  - "*.config.js"
  - "*.config.ts"

Branches Configuration

Control which branches Codecov tracks:

codecov:
  branch: main              # default branch

  # Ignore coverage uploads from these branches
  # (prevents feature branches from affecting project metrics)
  # Note: feature branch coverage is still shown on PRs

ignore_uncovered_files: false

branch_exclusions:
  # These patterns prevent status checks from posting
  - dependabot/**
  - renovate/**

Notifications

coverage:
  notify:
    slack:
      default:
        url: https://hooks.slack.com/services/your/webhook/url
        only_pulls: false
        threshold: 5%         # only notify if coverage drops >5%
        branches:
          - main

Complete Example

# codecov.yml
codecov:
  branch: main

coverage:
  precision: 2
  round: nearest
  range: "70...100"

  status:
    project:
      default:
        target: 80%
        threshold: 2%
    patch:
      default:
        target: 75%
        threshold: 0%
        only_pulls: true

flags:
  unit:
    paths:
      - src/
    carryforward: false

  integration:
    paths:
      - src/
    carryforward: true

comment:
  layout: "reach, diff, flags, files, footer"
  behavior: default
  require_changes: true
  require_base: true

ignore:
  - "src/**/*.test.{ts,tsx,js}"
  - "src/generated/**"
  - "src/testing/**"
  - "**/__mocks__/**"
  - "dist/**"

parsers:
  javascript:
    enable_partials: yes    # partial coverage for || and && expressions

Validating Your Config

# Validate with Codecov CLI
curl -X POST https://codecov.io/validate \
  -F 'yaml=@codecov.yml'

# Or via Codecov CLI
pip install codecov-cli
codecov-cli validate-yaml codecov.yml

A well-configured codecov.yml makes coverage enforcement practical — it enforces exactly what you care about (new code coverage, specific module thresholds) without false positives from generated code or temporary drops from test refactoring.

Read more

Start now free