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 changesCoverage 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 requestsSet target: off to disable patch checks:
coverage:
status:
patch: offFlags 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 runIn 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: integrationSet 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 totalTwo modes:
carryforward: true— carries the total coverage percentagecarryforward_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 commentingIgnore 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:
- mainComplete 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 && expressionsValidating 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.ymlA 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.