Repository files navigation

Codecov Action

build

Self-hosted coverage and test reporting with GitHub Actions. Uses GitHub Artifacts for storage — no external service or Codecov token required.

Quick Start

name: Teston:
push:
branches: [main]pull_request:
jobs:
test:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: Run tests with coveragerun: npm test -- --coverage
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Supported Coverage Formats

FormatFile PatternsLanguages/Tools
Clover XMLclover.xmlIstanbul/NYC (JS/TS), PHPUnit, OpenClover
Cobertura XMLcoverage.xml, cobertura.xmlcoverage.py (Python), Coverlet (.NET), PHPUnit
JaCoCo XMLjacoco.xmlJava, Kotlin, Scala
LCOVlcov.info, *.lcovc8, lcov (C/C++), grcov (Rust), gcov
Istanbul JSONcoverage-final.jsonJest, Vitest, NYC (JS/TS)
Go Coveragecoverage.out, cover.outgo test -coverprofile
Codecov JSONcodecov.jsoncargo-llvm-cov (Rust), custom tools

Inputs

Core Inputs

InputDescriptionRequiredDefault
tokenGitHub token for API access and artifactsYes
base-branchBase branch to compare results againstNoAuto-detected
enable-testsEnable test results reportingNotrue
enable-coverageEnable coverage reportingNotrue
post-pr-commentPost results as a PR commentNofalse
comment-keyNamespace the PR comment per step so steps sharing this action post separate comments instead of overwriting each otherNo

Coverage File Discovery (Codecov-style)

InputDescriptionRequiredDefault
filesComma-separated list of coverage filesNo
directoryFolder to search for coverage filesNo.
excludeComma-separated patterns to excludeNo
coverage-formatFormat hint: auto, clover, cobertura, jacoco, lcov, istanbul, go, codecovNoauto
disable-searchDisable auto-search, use only explicit filesNofalse

Behavior Flags (Codecov-style)

InputDescriptionRequiredDefault
fail-ci-if-errorFail if coverage processing errors (e.g., parsing failures, missing files)Nofalse
handle-no-reports-foundDon't fail if no coverage foundNofalse
verboseEnable verbose loggingNofalse

Status Checks & Thresholds

InputDescriptionRequiredDefault
target-projectTarget project coverage % (or auto to use base branch coverage)No
threshold-projectAllowed project coverage drop % (only used when target is auto)No
target-patchTarget patch coverage % for changed linesNo80
fail-on-errorFail CI if coverage thresholds are not met (distinct from fail-ci-if-error)Nofalse

When thresholds are not configured, status checks report coverage metrics without enforcing pass/fail.

Grouping & Identification

InputDescriptionRequiredDefault
flagsComma-separated flags to tag coverage (e.g., unittests,frontend)No
nameCustom name for this coverage upload. Also used to differentiate artifacts in matrix buildsNo

Test Results

InputDescriptionRequiredDefault
junit-xml-patternGlob pattern for JUnit XML filesNo./**/*.junit.xml

Outputs

Test Outputs

OutputDescription
total-testsTotal number of tests run
passed-testsNumber of passed tests
failed-testsNumber of failed tests
test-pass-ratePercentage of tests that passed
tests-addedTests added compared to base branch
tests-removedTests removed compared to base branch
tests-fixedTests changed from failing to passing
tests-brokenTests changed from passing to failing

Coverage Outputs

OutputDescription
line-coverageLine coverage percentage
branch-coverageBranch coverage percentage
coverage-changeChange in line coverage vs base branch
branch-coverage-changeChange in branch coverage vs base branch
coverage-improvedWhether coverage improved (true/false)
coverage-formatThe detected/used coverage format

Usage Examples

Basic Usage (Auto-detect)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Explicit Files (Codecov-style)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage/lcov.info,./backend/coverage.xmldisable-search: trueflags: unittestsname: my-coverageverbose: true

Python with Cobertura

- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coverage-format: coberturafail-ci-if-error: true

Java with JaCoCo

- name: Build and testrun: ./gradlew test jacocoTestReport
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./build/reports/jacoco/test/jacocoTestReport.xmlcoverage-format: jacoco

Go Coverage

- name: Run testsrun: go test -coverprofile=coverage.out ./...
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage.outcoverage-format: go

Rust with cargo-llvm-cov

- name: Install cargo-llvm-covuses: taiki-e/install-action@cargo-llvm-cov
- name: Run tests with coveragerun: cargo llvm-cov --codecov --output-path codecov.json
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./codecov.jsoncoverage-format: codecov

JavaScript/TypeScript with LCOV

- name: Run testsrun: npm test -- --coverage --coverageReporters=lcov
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coveragecoverage-format: lcov

Monorepo with Flags

- name: Frontend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./frontend/coverageflags: frontendname: frontend-coverage
- name: Backend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./backend/coverageflags: backendname: backend-coverage

Matrix Builds

When running coverage in a matrix strategy (e.g., multiple Python versions), use the name input to give each matrix entry a unique artifact name and avoid upload conflicts:

jobs:
test:
runs-on: ubuntu-lateststrategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5with:
python-version: ${{ matrix.python-version }}
- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: coverage.xmlname: py${{ matrix.python-version }}

Coverage Thresholds with Status Checks

Use built-in threshold enforcement with GitHub status checks:

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}target-project: auto # Use base branch coverage as targetthreshold-project: 1# Allow up to 1% coverage droptarget-patch: 80# Require 80% coverage on changed linesfail-on-error: true # Fail CI if thresholds not met

This creates two status checks (codecov/project and codecov/patch) that:

  • Appear on commits and PRs
  • Can be required via branch protection rules
  • Provide clear pass/fail feedback

How It Works

1. File Discovery

The action searches for coverage files using:

  • Explicit files: If files input is provided
  • Auto-discovery: Searches directory for known coverage file patterns
  • Format detection: Auto-detects format from file content

2. Parsing & Aggregation

Multiple coverage files are parsed and aggregated:

  • Supports mixing formats (e.g., frontend LCOV + backend Cobertura)
  • Calculates unified line, branch, and method coverage

3. Artifact Storage

Results are stored as GitHub Artifacts:

  • codecov-coverage-results-{branch}[-{name}][-{flags}] — Aggregated coverage data
  • codecov-test-results-{branch} — Aggregated test results

When using the name input, it is appended to the artifact name to avoid conflicts in matrix builds.

4. Base Branch Comparison

On PRs or feature branches:

  1. Auto-detects the repository's default branch (or uses the explicit base-branch input)
  2. Downloads latest results from base branch
  3. Compares current vs baseline
  4. Calculates deltas

5. Reporting

  • Job Summary: Always generated in Actions UI
  • PR Comment: Optional detailed comment on PRs

6. Status Checks

The action creates GitHub commit status checks that appear on commits and PRs:

Status ContextDescription
codecov/projectOverall project coverage status (pass/fail based on target)
codecov/patchCoverage for changed lines in the PR

These status checks:

  • Show as green checkmarks or red X marks on commits and PRs
  • Can be used in branch protection rules to require coverage thresholds
  • Provide immediate feedback on coverage quality

Status Badges

Display your CI status in your README using GitHub's workflow badge:

![CI](https://github.com/{owner}/{repo}/actions/workflows/{workflow}.yml/badge.svg)

Test Results

Supported Format

FormatTypical FileCommon Test Frameworks
JUnit XML*.junit.xmlJest, Vitest, Mocha, pytest, JUnit, NUnit, PHPUnit

Configuration Examples

Jest / Vitest:

{
"reporters": ["default", ["jest-junit", { "outputFile": "report.junit.xml" }]]
}

pytest:

pytest --junitxml=report.junit.xml

Coverage Configuration Examples

JavaScript/TypeScript (Jest/Vitest)

{
"coverageReporters": ["lcov", "clover", "json"]
}

Python (pytest-cov)

pytest --cov=src --cov-report=xml # Cobertura format

Java (Gradle + JaCoCo)

jacocoTestReport {
reports {
xml.required =true
}
}

Go

go test -coverprofile=coverage.out ./...

Rust (cargo-llvm-cov)

# Install cargo-llvm-cov
cargo install cargo-llvm-cov
# Generate Codecov JSON format
cargo llvm-cov --codecov --output-path codecov.json
# Or generate LCOV format
cargo llvm-cov --lcov --output-path lcov.info

.NET (Coverlet)

dotnet test --collect:"XPlat Code Coverage"# or
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura

Configuration File

You can configure status check thresholds using a .github/coverage.yml file in your repository. Action inputs take precedence over the config file, allowing you to override settings per-workflow.

# .github/coverage.ymlcoverage:
status:
project:
target: 80# Target coverage percentage (or "auto" to use base branch)threshold: 1# Allowed coverage drop when using "auto" (supports "1%" or 1)informational: false # When true, status check reports but never fails the buildpatch:
target: 90# Target coverage for changed linesinformational: falseignore:
- "**/*.test.ts"# Patterns to exclude from coverage
- "**/fixtures/**"# Enable PR comments from config (alternative to post-pr-comment input)comment: true# Report display settingsconfig:
files: changed # all (default) | changed | none
OptionDescription
status.project.targetTarget project coverage % (number or "auto")
status.project.thresholdAllowed drop from base branch when target is "auto". Supports number (1) or string ("1%")
status.project.informationalWhen true, status check reports but never fails the build (advisory mode)
status.patch.targetTarget coverage % for changed lines
status.patch.informationalWhen true, patch status check is advisory-only
ignoreGlob patterns to exclude from coverage calculations
commentEnable PR comments. Set to true or false
config.filesControl file table scope in reports (Job Summary + PR comments). Values: all (default), changed, none

Codecov YAML Compatibility

This action also supports the standard Codecov YAML format with nested default keys:

# .github/codecov.yml (Codecov-compatible format)coverage:
status:
project:
default:
target: autothreshold: 10%# Percentage strings are supportedinformational: truepatch:
default:
target: 80ignore:
- "tests/**"comment: trueconfig:
files: changed

Both formats work identically—use whichever style you prefer.

Report File List Mode

Use config.files to control the "Files with missing lines" section in both Job Summary and PR comments:

  • all (default): show all files with missing/partial lines
  • changed: show only non-deleted files from the PR diff
  • none: hide the section entirely

Permissions

permissions:
contents: read # Read repository contentsactions: read # Read workflow runs and artifactspull-requests: write # Post PR comments (if enabled)statuses: write # Create commit status checks

Note: On pull requests from forks, GITHUB_TOKEN has restricted permissions regardless of the workflow's permissions block. PR comments and commit status checks will be skipped gracefully with a warning in this case. Coverage results and Job Summary are still generated.

Migration from Codecov

If you're migrating from the official Codecov action:

Codecov InputThis Action
fail_ci_if_errorfail-ci-if-error
filesfiles
directorydirectory
excludeexclude
flagsflags
namename
verboseverbose
handle-no-reports-foundhandle-no-reports-found

Note: This action doesn't require a Codecov token—it uses GitHub's native artifacts for storage.

About

GitHub Action for code coverage and test result reporting using GitHub Artifacts.

Topics

Resources

Code of conduct

Security policy

Stars

7 stars

Watchers

2 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Codecov Action

build

Self-hosted coverage and test reporting with GitHub Actions. Uses GitHub Artifacts for storage — no external service or Codecov token required.

Quick Start

name: Teston:
push:
branches: [main]pull_request:
jobs:
test:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: Run tests with coveragerun: npm test -- --coverage
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Supported Coverage Formats

FormatFile PatternsLanguages/Tools
Clover XMLclover.xmlIstanbul/NYC (JS/TS), PHPUnit, OpenClover
Cobertura XMLcoverage.xml, cobertura.xmlcoverage.py (Python), Coverlet (.NET), PHPUnit
JaCoCo XMLjacoco.xmlJava, Kotlin, Scala
LCOVlcov.info, *.lcovc8, lcov (C/C++), grcov (Rust), gcov
Istanbul JSONcoverage-final.jsonJest, Vitest, NYC (JS/TS)
Go Coveragecoverage.out, cover.outgo test -coverprofile
Codecov JSONcodecov.jsoncargo-llvm-cov (Rust), custom tools

Inputs

Core Inputs

InputDescriptionRequiredDefault
tokenGitHub token for API access and artifactsYes
base-branchBase branch to compare results againstNoAuto-detected
enable-testsEnable test results reportingNotrue
enable-coverageEnable coverage reportingNotrue
post-pr-commentPost results as a PR commentNofalse
comment-keyNamespace the PR comment per step so steps sharing this action post separate comments instead of overwriting each otherNo

Coverage File Discovery (Codecov-style)

InputDescriptionRequiredDefault
filesComma-separated list of coverage filesNo
directoryFolder to search for coverage filesNo.
excludeComma-separated patterns to excludeNo
coverage-formatFormat hint: auto, clover, cobertura, jacoco, lcov, istanbul, go, codecovNoauto
disable-searchDisable auto-search, use only explicit filesNofalse

Behavior Flags (Codecov-style)

InputDescriptionRequiredDefault
fail-ci-if-errorFail if coverage processing errors (e.g., parsing failures, missing files)Nofalse
handle-no-reports-foundDon't fail if no coverage foundNofalse
verboseEnable verbose loggingNofalse

Status Checks & Thresholds

InputDescriptionRequiredDefault
target-projectTarget project coverage % (or auto to use base branch coverage)No
threshold-projectAllowed project coverage drop % (only used when target is auto)No
target-patchTarget patch coverage % for changed linesNo80
fail-on-errorFail CI if coverage thresholds are not met (distinct from fail-ci-if-error)Nofalse

When thresholds are not configured, status checks report coverage metrics without enforcing pass/fail.

Grouping & Identification

InputDescriptionRequiredDefault
flagsComma-separated flags to tag coverage (e.g., unittests,frontend)No
nameCustom name for this coverage upload. Also used to differentiate artifacts in matrix buildsNo

Test Results

InputDescriptionRequiredDefault
junit-xml-patternGlob pattern for JUnit XML filesNo./**/*.junit.xml

Outputs

Test Outputs

OutputDescription
total-testsTotal number of tests run
passed-testsNumber of passed tests
failed-testsNumber of failed tests
test-pass-ratePercentage of tests that passed
tests-addedTests added compared to base branch
tests-removedTests removed compared to base branch
tests-fixedTests changed from failing to passing
tests-brokenTests changed from passing to failing

Coverage Outputs

OutputDescription
line-coverageLine coverage percentage
branch-coverageBranch coverage percentage
coverage-changeChange in line coverage vs base branch
branch-coverage-changeChange in branch coverage vs base branch
coverage-improvedWhether coverage improved (true/false)
coverage-formatThe detected/used coverage format

Usage Examples

Basic Usage (Auto-detect)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Explicit Files (Codecov-style)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage/lcov.info,./backend/coverage.xmldisable-search: trueflags: unittestsname: my-coverageverbose: true

Python with Cobertura

- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coverage-format: coberturafail-ci-if-error: true

Java with JaCoCo

- name: Build and testrun: ./gradlew test jacocoTestReport
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./build/reports/jacoco/test/jacocoTestReport.xmlcoverage-format: jacoco

Go Coverage

- name: Run testsrun: go test -coverprofile=coverage.out ./...
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage.outcoverage-format: go

Rust with cargo-llvm-cov

- name: Install cargo-llvm-covuses: taiki-e/install-action@cargo-llvm-cov
- name: Run tests with coveragerun: cargo llvm-cov --codecov --output-path codecov.json
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./codecov.jsoncoverage-format: codecov

JavaScript/TypeScript with LCOV

- name: Run testsrun: npm test -- --coverage --coverageReporters=lcov
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coveragecoverage-format: lcov

Monorepo with Flags

- name: Frontend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./frontend/coverageflags: frontendname: frontend-coverage
- name: Backend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./backend/coverageflags: backendname: backend-coverage

Matrix Builds

When running coverage in a matrix strategy (e.g., multiple Python versions), use the name input to give each matrix entry a unique artifact name and avoid upload conflicts:

jobs:
test:
runs-on: ubuntu-lateststrategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5with:
python-version: ${{ matrix.python-version }}
- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: coverage.xmlname: py${{ matrix.python-version }}

Coverage Thresholds with Status Checks

Use built-in threshold enforcement with GitHub status checks:

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}target-project: auto # Use base branch coverage as targetthreshold-project: 1# Allow up to 1% coverage droptarget-patch: 80# Require 80% coverage on changed linesfail-on-error: true # Fail CI if thresholds not met

This creates two status checks (codecov/project and codecov/patch) that:

  • Appear on commits and PRs
  • Can be required via branch protection rules
  • Provide clear pass/fail feedback

How It Works

1. File Discovery

The action searches for coverage files using:

  • Explicit files: If files input is provided
  • Auto-discovery: Searches directory for known coverage file patterns
  • Format detection: Auto-detects format from file content

2. Parsing & Aggregation

Multiple coverage files are parsed and aggregated:

  • Supports mixing formats (e.g., frontend LCOV + backend Cobertura)
  • Calculates unified line, branch, and method coverage

3. Artifact Storage

Results are stored as GitHub Artifacts:

  • codecov-coverage-results-{branch}[-{name}][-{flags}] — Aggregated coverage data
  • codecov-test-results-{branch} — Aggregated test results

When using the name input, it is appended to the artifact name to avoid conflicts in matrix builds.

4. Base Branch Comparison

On PRs or feature branches:

  1. Auto-detects the repository's default branch (or uses the explicit base-branch input)
  2. Downloads latest results from base branch
  3. Compares current vs baseline
  4. Calculates deltas

5. Reporting

  • Job Summary: Always generated in Actions UI
  • PR Comment: Optional detailed comment on PRs

6. Status Checks

The action creates GitHub commit status checks that appear on commits and PRs:

Status ContextDescription
codecov/projectOverall project coverage status (pass/fail based on target)
codecov/patchCoverage for changed lines in the PR

These status checks:

  • Show as green checkmarks or red X marks on commits and PRs
  • Can be used in branch protection rules to require coverage thresholds
  • Provide immediate feedback on coverage quality

Status Badges

Display your CI status in your README using GitHub's workflow badge:

![CI](https://github.com/{owner}/{repo}/actions/workflows/{workflow}.yml/badge.svg)

Test Results

Supported Format

FormatTypical FileCommon Test Frameworks
JUnit XML*.junit.xmlJest, Vitest, Mocha, pytest, JUnit, NUnit, PHPUnit

Configuration Examples

Jest / Vitest:

{
"reporters": ["default", ["jest-junit", { "outputFile": "report.junit.xml" }]]
}

pytest:

pytest --junitxml=report.junit.xml

Coverage Configuration Examples

JavaScript/TypeScript (Jest/Vitest)

{
"coverageReporters": ["lcov", "clover", "json"]
}

Python (pytest-cov)

pytest --cov=src --cov-report=xml # Cobertura format

Java (Gradle + JaCoCo)

jacocoTestReport {
reports {
xml.required =true
}
}

Go

go test -coverprofile=coverage.out ./...

Rust (cargo-llvm-cov)

# Install cargo-llvm-cov
cargo install cargo-llvm-cov
# Generate Codecov JSON format
cargo llvm-cov --codecov --output-path codecov.json
# Or generate LCOV format
cargo llvm-cov --lcov --output-path lcov.info

.NET (Coverlet)

dotnet test --collect:"XPlat Code Coverage"# or
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura

Configuration File

You can configure status check thresholds using a .github/coverage.yml file in your repository. Action inputs take precedence over the config file, allowing you to override settings per-workflow.

# .github/coverage.ymlcoverage:
status:
project:
target: 80# Target coverage percentage (or "auto" to use base branch)threshold: 1# Allowed coverage drop when using "auto" (supports "1%" or 1)informational: false # When true, status check reports but never fails the buildpatch:
target: 90# Target coverage for changed linesinformational: falseignore:
- "**/*.test.ts"# Patterns to exclude from coverage
- "**/fixtures/**"# Enable PR comments from config (alternative to post-pr-comment input)comment: true# Report display settingsconfig:
files: changed # all (default) | changed | none
OptionDescription
status.project.targetTarget project coverage % (number or "auto")
status.project.thresholdAllowed drop from base branch when target is "auto". Supports number (1) or string ("1%")
status.project.informationalWhen true, status check reports but never fails the build (advisory mode)
status.patch.targetTarget coverage % for changed lines
status.patch.informationalWhen true, patch status check is advisory-only
ignoreGlob patterns to exclude from coverage calculations
commentEnable PR comments. Set to true or false
config.filesControl file table scope in reports (Job Summary + PR comments). Values: all (default), changed, none

Codecov YAML Compatibility

This action also supports the standard Codecov YAML format with nested default keys:

# .github/codecov.yml (Codecov-compatible format)coverage:
status:
project:
default:
target: autothreshold: 10%# Percentage strings are supportedinformational: truepatch:
default:
target: 80ignore:
- "tests/**"comment: trueconfig:
files: changed

Both formats work identically—use whichever style you prefer.

Report File List Mode

Use config.files to control the "Files with missing lines" section in both Job Summary and PR comments:

  • all (default): show all files with missing/partial lines
  • changed: show only non-deleted files from the PR diff
  • none: hide the section entirely

Permissions

permissions:
contents: read # Read repository contentsactions: read # Read workflow runs and artifactspull-requests: write # Post PR comments (if enabled)statuses: write # Create commit status checks

Note: On pull requests from forks, GITHUB_TOKEN has restricted permissions regardless of the workflow's permissions block. PR comments and commit status checks will be skipped gracefully with a warning in this case. Coverage results and Job Summary are still generated.

Migration from Codecov

If you're migrating from the official Codecov action:

Codecov InputThis Action
fail_ci_if_errorfail-ci-if-error
filesfiles
directorydirectory
excludeexclude
flagsflags
namename
verboseverbose
handle-no-reports-foundhandle-no-reports-found

Note: This action doesn't require a Codecov token—it uses GitHub's native artifacts for storage.

About

GitHub Action for code coverage and test result reporting using GitHub Artifacts.

Topics

Resources

Code of conduct

Security policy

Stars

7 stars

Watchers

2 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Codecov Action

build

Self-hosted coverage and test reporting with GitHub Actions. Uses GitHub Artifacts for storage — no external service or Codecov token required.

Quick Start

name: Teston:
push:
branches: [main]pull_request:
jobs:
test:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: Run tests with coveragerun: npm test -- --coverage
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Supported Coverage Formats

FormatFile PatternsLanguages/Tools
Clover XMLclover.xmlIstanbul/NYC (JS/TS), PHPUnit, OpenClover
Cobertura XMLcoverage.xml, cobertura.xmlcoverage.py (Python), Coverlet (.NET), PHPUnit
JaCoCo XMLjacoco.xmlJava, Kotlin, Scala
LCOVlcov.info, *.lcovc8, lcov (C/C++), grcov (Rust), gcov
Istanbul JSONcoverage-final.jsonJest, Vitest, NYC (JS/TS)
Go Coveragecoverage.out, cover.outgo test -coverprofile
Codecov JSONcodecov.jsoncargo-llvm-cov (Rust), custom tools

Inputs

Core Inputs

InputDescriptionRequiredDefault
tokenGitHub token for API access and artifactsYes
base-branchBase branch to compare results againstNoAuto-detected
enable-testsEnable test results reportingNotrue
enable-coverageEnable coverage reportingNotrue
post-pr-commentPost results as a PR commentNofalse
comment-keyNamespace the PR comment per step so steps sharing this action post separate comments instead of overwriting each otherNo

Coverage File Discovery (Codecov-style)

InputDescriptionRequiredDefault
filesComma-separated list of coverage filesNo
directoryFolder to search for coverage filesNo.
excludeComma-separated patterns to excludeNo
coverage-formatFormat hint: auto, clover, cobertura, jacoco, lcov, istanbul, go, codecovNoauto
disable-searchDisable auto-search, use only explicit filesNofalse

Behavior Flags (Codecov-style)

InputDescriptionRequiredDefault
fail-ci-if-errorFail if coverage processing errors (e.g., parsing failures, missing files)Nofalse
handle-no-reports-foundDon't fail if no coverage foundNofalse
verboseEnable verbose loggingNofalse

Status Checks & Thresholds

InputDescriptionRequiredDefault
target-projectTarget project coverage % (or auto to use base branch coverage)No
threshold-projectAllowed project coverage drop % (only used when target is auto)No
target-patchTarget patch coverage % for changed linesNo80
fail-on-errorFail CI if coverage thresholds are not met (distinct from fail-ci-if-error)Nofalse

When thresholds are not configured, status checks report coverage metrics without enforcing pass/fail.

Grouping & Identification

InputDescriptionRequiredDefault
flagsComma-separated flags to tag coverage (e.g., unittests,frontend)No
nameCustom name for this coverage upload. Also used to differentiate artifacts in matrix buildsNo

Test Results

InputDescriptionRequiredDefault
junit-xml-patternGlob pattern for JUnit XML filesNo./**/*.junit.xml

Outputs

Test Outputs

OutputDescription
total-testsTotal number of tests run
passed-testsNumber of passed tests
failed-testsNumber of failed tests
test-pass-ratePercentage of tests that passed
tests-addedTests added compared to base branch
tests-removedTests removed compared to base branch
tests-fixedTests changed from failing to passing
tests-brokenTests changed from passing to failing

Coverage Outputs

OutputDescription
line-coverageLine coverage percentage
branch-coverageBranch coverage percentage
coverage-changeChange in line coverage vs base branch
branch-coverage-changeChange in branch coverage vs base branch
coverage-improvedWhether coverage improved (true/false)
coverage-formatThe detected/used coverage format

Usage Examples

Basic Usage (Auto-detect)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Explicit Files (Codecov-style)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage/lcov.info,./backend/coverage.xmldisable-search: trueflags: unittestsname: my-coverageverbose: true

Python with Cobertura

- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coverage-format: coberturafail-ci-if-error: true

Java with JaCoCo

- name: Build and testrun: ./gradlew test jacocoTestReport
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./build/reports/jacoco/test/jacocoTestReport.xmlcoverage-format: jacoco

Go Coverage

- name: Run testsrun: go test -coverprofile=coverage.out ./...
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage.outcoverage-format: go

Rust with cargo-llvm-cov

- name: Install cargo-llvm-covuses: taiki-e/install-action@cargo-llvm-cov
- name: Run tests with coveragerun: cargo llvm-cov --codecov --output-path codecov.json
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./codecov.jsoncoverage-format: codecov

JavaScript/TypeScript with LCOV

- name: Run testsrun: npm test -- --coverage --coverageReporters=lcov
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coveragecoverage-format: lcov

Monorepo with Flags

- name: Frontend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./frontend/coverageflags: frontendname: frontend-coverage
- name: Backend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./backend/coverageflags: backendname: backend-coverage

Matrix Builds

When running coverage in a matrix strategy (e.g., multiple Python versions), use the name input to give each matrix entry a unique artifact name and avoid upload conflicts:

jobs:
test:
runs-on: ubuntu-lateststrategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5with:
python-version: ${{ matrix.python-version }}
- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: coverage.xmlname: py${{ matrix.python-version }}

Coverage Thresholds with Status Checks

Use built-in threshold enforcement with GitHub status checks:

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}target-project: auto # Use base branch coverage as targetthreshold-project: 1# Allow up to 1% coverage droptarget-patch: 80# Require 80% coverage on changed linesfail-on-error: true # Fail CI if thresholds not met

This creates two status checks (codecov/project and codecov/patch) that:

  • Appear on commits and PRs
  • Can be required via branch protection rules
  • Provide clear pass/fail feedback

How It Works

1. File Discovery

The action searches for coverage files using:

  • Explicit files: If files input is provided
  • Auto-discovery: Searches directory for known coverage file patterns
  • Format detection: Auto-detects format from file content

2. Parsing & Aggregation

Multiple coverage files are parsed and aggregated:

  • Supports mixing formats (e.g., frontend LCOV + backend Cobertura)
  • Calculates unified line, branch, and method coverage

3. Artifact Storage

Results are stored as GitHub Artifacts:

  • codecov-coverage-results-{branch}[-{name}][-{flags}] — Aggregated coverage data
  • codecov-test-results-{branch} — Aggregated test results

When using the name input, it is appended to the artifact name to avoid conflicts in matrix builds.

4. Base Branch Comparison

On PRs or feature branches:

  1. Auto-detects the repository's default branch (or uses the explicit base-branch input)
  2. Downloads latest results from base branch
  3. Compares current vs baseline
  4. Calculates deltas

5. Reporting

  • Job Summary: Always generated in Actions UI
  • PR Comment: Optional detailed comment on PRs

6. Status Checks

The action creates GitHub commit status checks that appear on commits and PRs:

Status ContextDescription
codecov/projectOverall project coverage status (pass/fail based on target)
codecov/patchCoverage for changed lines in the PR

These status checks:

  • Show as green checkmarks or red X marks on commits and PRs
  • Can be used in branch protection rules to require coverage thresholds
  • Provide immediate feedback on coverage quality

Status Badges

Display your CI status in your README using GitHub's workflow badge:

![CI](https://github.com/{owner}/{repo}/actions/workflows/{workflow}.yml/badge.svg)

Test Results

Supported Format

FormatTypical FileCommon Test Frameworks
JUnit XML*.junit.xmlJest, Vitest, Mocha, pytest, JUnit, NUnit, PHPUnit

Configuration Examples

Jest / Vitest:

{
"reporters": ["default", ["jest-junit", { "outputFile": "report.junit.xml" }]]
}

pytest:

pytest --junitxml=report.junit.xml

Coverage Configuration Examples

JavaScript/TypeScript (Jest/Vitest)

{
"coverageReporters": ["lcov", "clover", "json"]
}

Python (pytest-cov)

pytest --cov=src --cov-report=xml # Cobertura format

Java (Gradle + JaCoCo)

jacocoTestReport {
reports {
xml.required =true
}
}

Go

go test -coverprofile=coverage.out ./...

Rust (cargo-llvm-cov)

# Install cargo-llvm-cov
cargo install cargo-llvm-cov
# Generate Codecov JSON format
cargo llvm-cov --codecov --output-path codecov.json
# Or generate LCOV format
cargo llvm-cov --lcov --output-path lcov.info

.NET (Coverlet)

dotnet test --collect:"XPlat Code Coverage"# or
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura

Configuration File

You can configure status check thresholds using a .github/coverage.yml file in your repository. Action inputs take precedence over the config file, allowing you to override settings per-workflow.

# .github/coverage.ymlcoverage:
status:
project:
target: 80# Target coverage percentage (or "auto" to use base branch)threshold: 1# Allowed coverage drop when using "auto" (supports "1%" or 1)informational: false # When true, status check reports but never fails the buildpatch:
target: 90# Target coverage for changed linesinformational: falseignore:
- "**/*.test.ts"# Patterns to exclude from coverage
- "**/fixtures/**"# Enable PR comments from config (alternative to post-pr-comment input)comment: true# Report display settingsconfig:
files: changed # all (default) | changed | none
OptionDescription
status.project.targetTarget project coverage % (number or "auto")
status.project.thresholdAllowed drop from base branch when target is "auto". Supports number (1) or string ("1%")
status.project.informationalWhen true, status check reports but never fails the build (advisory mode)
status.patch.targetTarget coverage % for changed lines
status.patch.informationalWhen true, patch status check is advisory-only
ignoreGlob patterns to exclude from coverage calculations
commentEnable PR comments. Set to true or false
config.filesControl file table scope in reports (Job Summary + PR comments). Values: all (default), changed, none

Codecov YAML Compatibility

This action also supports the standard Codecov YAML format with nested default keys:

# .github/codecov.yml (Codecov-compatible format)coverage:
status:
project:
default:
target: autothreshold: 10%# Percentage strings are supportedinformational: truepatch:
default:
target: 80ignore:
- "tests/**"comment: trueconfig:
files: changed

Both formats work identically—use whichever style you prefer.

Report File List Mode

Use config.files to control the "Files with missing lines" section in both Job Summary and PR comments:

  • all (default): show all files with missing/partial lines
  • changed: show only non-deleted files from the PR diff
  • none: hide the section entirely

Permissions

permissions:
contents: read # Read repository contentsactions: read # Read workflow runs and artifactspull-requests: write # Post PR comments (if enabled)statuses: write # Create commit status checks

Note: On pull requests from forks, GITHUB_TOKEN has restricted permissions regardless of the workflow's permissions block. PR comments and commit status checks will be skipped gracefully with a warning in this case. Coverage results and Job Summary are still generated.

Migration from Codecov

If you're migrating from the official Codecov action:

Codecov InputThis Action
fail_ci_if_errorfail-ci-if-error
filesfiles
directorydirectory
excludeexclude
flagsflags
namename
verboseverbose
handle-no-reports-foundhandle-no-reports-found

Note: This action doesn't require a Codecov token—it uses GitHub's native artifacts for storage.

About

GitHub Action for code coverage and test result reporting using GitHub Artifacts.

Topics

Resources

Code of conduct

Security policy

Stars

7 stars

Watchers

2 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Codecov Action

build

Self-hosted coverage and test reporting with GitHub Actions. Uses GitHub Artifacts for storage — no external service or Codecov token required.

Quick Start

name: Teston:
push:
branches: [main]pull_request:
jobs:
test:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: Run tests with coveragerun: npm test -- --coverage
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Supported Coverage Formats

FormatFile PatternsLanguages/Tools
Clover XMLclover.xmlIstanbul/NYC (JS/TS), PHPUnit, OpenClover
Cobertura XMLcoverage.xml, cobertura.xmlcoverage.py (Python), Coverlet (.NET), PHPUnit
JaCoCo XMLjacoco.xmlJava, Kotlin, Scala
LCOVlcov.info, *.lcovc8, lcov (C/C++), grcov (Rust), gcov
Istanbul JSONcoverage-final.jsonJest, Vitest, NYC (JS/TS)
Go Coveragecoverage.out, cover.outgo test -coverprofile
Codecov JSONcodecov.jsoncargo-llvm-cov (Rust), custom tools

Inputs

Core Inputs

InputDescriptionRequiredDefault
tokenGitHub token for API access and artifactsYes
base-branchBase branch to compare results againstNoAuto-detected
enable-testsEnable test results reportingNotrue
enable-coverageEnable coverage reportingNotrue
post-pr-commentPost results as a PR commentNofalse
comment-keyNamespace the PR comment per step so steps sharing this action post separate comments instead of overwriting each otherNo

Coverage File Discovery (Codecov-style)

InputDescriptionRequiredDefault
filesComma-separated list of coverage filesNo
directoryFolder to search for coverage filesNo.
excludeComma-separated patterns to excludeNo
coverage-formatFormat hint: auto, clover, cobertura, jacoco, lcov, istanbul, go, codecovNoauto
disable-searchDisable auto-search, use only explicit filesNofalse

Behavior Flags (Codecov-style)

InputDescriptionRequiredDefault
fail-ci-if-errorFail if coverage processing errors (e.g., parsing failures, missing files)Nofalse
handle-no-reports-foundDon't fail if no coverage foundNofalse
verboseEnable verbose loggingNofalse

Status Checks & Thresholds

InputDescriptionRequiredDefault
target-projectTarget project coverage % (or auto to use base branch coverage)No
threshold-projectAllowed project coverage drop % (only used when target is auto)No
target-patchTarget patch coverage % for changed linesNo80
fail-on-errorFail CI if coverage thresholds are not met (distinct from fail-ci-if-error)Nofalse

When thresholds are not configured, status checks report coverage metrics without enforcing pass/fail.

Grouping & Identification

InputDescriptionRequiredDefault
flagsComma-separated flags to tag coverage (e.g., unittests,frontend)No
nameCustom name for this coverage upload. Also used to differentiate artifacts in matrix buildsNo

Test Results

InputDescriptionRequiredDefault
junit-xml-patternGlob pattern for JUnit XML filesNo./**/*.junit.xml

Outputs

Test Outputs

OutputDescription
total-testsTotal number of tests run
passed-testsNumber of passed tests
failed-testsNumber of failed tests
test-pass-ratePercentage of tests that passed
tests-addedTests added compared to base branch
tests-removedTests removed compared to base branch
tests-fixedTests changed from failing to passing
tests-brokenTests changed from passing to failing

Coverage Outputs

OutputDescription
line-coverageLine coverage percentage
branch-coverageBranch coverage percentage
coverage-changeChange in line coverage vs base branch
branch-coverage-changeChange in branch coverage vs base branch
coverage-improvedWhether coverage improved (true/false)
coverage-formatThe detected/used coverage format

Usage Examples

Basic Usage (Auto-detect)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Explicit Files (Codecov-style)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage/lcov.info,./backend/coverage.xmldisable-search: trueflags: unittestsname: my-coverageverbose: true

Python with Cobertura

- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coverage-format: coberturafail-ci-if-error: true

Java with JaCoCo

- name: Build and testrun: ./gradlew test jacocoTestReport
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./build/reports/jacoco/test/jacocoTestReport.xmlcoverage-format: jacoco

Go Coverage

- name: Run testsrun: go test -coverprofile=coverage.out ./...
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage.outcoverage-format: go

Rust with cargo-llvm-cov

- name: Install cargo-llvm-covuses: taiki-e/install-action@cargo-llvm-cov
- name: Run tests with coveragerun: cargo llvm-cov --codecov --output-path codecov.json
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./codecov.jsoncoverage-format: codecov

JavaScript/TypeScript with LCOV

- name: Run testsrun: npm test -- --coverage --coverageReporters=lcov
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coveragecoverage-format: lcov

Monorepo with Flags

- name: Frontend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./frontend/coverageflags: frontendname: frontend-coverage
- name: Backend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./backend/coverageflags: backendname: backend-coverage

Matrix Builds

When running coverage in a matrix strategy (e.g., multiple Python versions), use the name input to give each matrix entry a unique artifact name and avoid upload conflicts:

jobs:
test:
runs-on: ubuntu-lateststrategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5with:
python-version: ${{ matrix.python-version }}
- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: coverage.xmlname: py${{ matrix.python-version }}

Coverage Thresholds with Status Checks

Use built-in threshold enforcement with GitHub status checks:

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}target-project: auto # Use base branch coverage as targetthreshold-project: 1# Allow up to 1% coverage droptarget-patch: 80# Require 80% coverage on changed linesfail-on-error: true # Fail CI if thresholds not met

This creates two status checks (codecov/project and codecov/patch) that:

  • Appear on commits and PRs
  • Can be required via branch protection rules
  • Provide clear pass/fail feedback

How It Works

1. File Discovery

The action searches for coverage files using:

  • Explicit files: If files input is provided
  • Auto-discovery: Searches directory for known coverage file patterns
  • Format detection: Auto-detects format from file content

2. Parsing & Aggregation

Multiple coverage files are parsed and aggregated:

  • Supports mixing formats (e.g., frontend LCOV + backend Cobertura)
  • Calculates unified line, branch, and method coverage

3. Artifact Storage

Results are stored as GitHub Artifacts:

  • codecov-coverage-results-{branch}[-{name}][-{flags}] — Aggregated coverage data
  • codecov-test-results-{branch} — Aggregated test results

When using the name input, it is appended to the artifact name to avoid conflicts in matrix builds.

4. Base Branch Comparison

On PRs or feature branches:

  1. Auto-detects the repository's default branch (or uses the explicit base-branch input)
  2. Downloads latest results from base branch
  3. Compares current vs baseline
  4. Calculates deltas

5. Reporting

  • Job Summary: Always generated in Actions UI
  • PR Comment: Optional detailed comment on PRs

6. Status Checks

The action creates GitHub commit status checks that appear on commits and PRs:

Status ContextDescription
codecov/projectOverall project coverage status (pass/fail based on target)
codecov/patchCoverage for changed lines in the PR

These status checks:

  • Show as green checkmarks or red X marks on commits and PRs
  • Can be used in branch protection rules to require coverage thresholds
  • Provide immediate feedback on coverage quality

Status Badges

Display your CI status in your README using GitHub's workflow badge:

![CI](https://github.com/{owner}/{repo}/actions/workflows/{workflow}.yml/badge.svg)

Test Results

Supported Format

FormatTypical FileCommon Test Frameworks
JUnit XML*.junit.xmlJest, Vitest, Mocha, pytest, JUnit, NUnit, PHPUnit

Configuration Examples

Jest / Vitest:

{
"reporters": ["default", ["jest-junit", { "outputFile": "report.junit.xml" }]]
}

pytest:

pytest --junitxml=report.junit.xml

Coverage Configuration Examples

JavaScript/TypeScript (Jest/Vitest)

{
"coverageReporters": ["lcov", "clover", "json"]
}

Python (pytest-cov)

pytest --cov=src --cov-report=xml # Cobertura format

Java (Gradle + JaCoCo)

jacocoTestReport {
reports {
xml.required =true
}
}

Go

go test -coverprofile=coverage.out ./...

Rust (cargo-llvm-cov)

# Install cargo-llvm-cov
cargo install cargo-llvm-cov
# Generate Codecov JSON format
cargo llvm-cov --codecov --output-path codecov.json
# Or generate LCOV format
cargo llvm-cov --lcov --output-path lcov.info

.NET (Coverlet)

dotnet test --collect:"XPlat Code Coverage"# or
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura

Configuration File

You can configure status check thresholds using a .github/coverage.yml file in your repository. Action inputs take precedence over the config file, allowing you to override settings per-workflow.

# .github/coverage.ymlcoverage:
status:
project:
target: 80# Target coverage percentage (or "auto" to use base branch)threshold: 1# Allowed coverage drop when using "auto" (supports "1%" or 1)informational: false # When true, status check reports but never fails the buildpatch:
target: 90# Target coverage for changed linesinformational: falseignore:
- "**/*.test.ts"# Patterns to exclude from coverage
- "**/fixtures/**"# Enable PR comments from config (alternative to post-pr-comment input)comment: true# Report display settingsconfig:
files: changed # all (default) | changed | none
OptionDescription
status.project.targetTarget project coverage % (number or "auto")
status.project.thresholdAllowed drop from base branch when target is "auto". Supports number (1) or string ("1%")
status.project.informationalWhen true, status check reports but never fails the build (advisory mode)
status.patch.targetTarget coverage % for changed lines
status.patch.informationalWhen true, patch status check is advisory-only
ignoreGlob patterns to exclude from coverage calculations
commentEnable PR comments. Set to true or false
config.filesControl file table scope in reports (Job Summary + PR comments). Values: all (default), changed, none

Codecov YAML Compatibility

This action also supports the standard Codecov YAML format with nested default keys:

# .github/codecov.yml (Codecov-compatible format)coverage:
status:
project:
default:
target: autothreshold: 10%# Percentage strings are supportedinformational: truepatch:
default:
target: 80ignore:
- "tests/**"comment: trueconfig:
files: changed

Both formats work identically—use whichever style you prefer.

Report File List Mode

Use config.files to control the "Files with missing lines" section in both Job Summary and PR comments:

  • all (default): show all files with missing/partial lines
  • changed: show only non-deleted files from the PR diff
  • none: hide the section entirely

Permissions

permissions:
contents: read # Read repository contentsactions: read # Read workflow runs and artifactspull-requests: write # Post PR comments (if enabled)statuses: write # Create commit status checks

Note: On pull requests from forks, GITHUB_TOKEN has restricted permissions regardless of the workflow's permissions block. PR comments and commit status checks will be skipped gracefully with a warning in this case. Coverage results and Job Summary are still generated.

Migration from Codecov

If you're migrating from the official Codecov action:

Codecov InputThis Action
fail_ci_if_errorfail-ci-if-error
filesfiles
directorydirectory
excludeexclude
flagsflags
namename
verboseverbose
handle-no-reports-foundhandle-no-reports-found

Note: This action doesn't require a Codecov token—it uses GitHub's native artifacts for storage.

About

GitHub Action for code coverage and test result reporting using GitHub Artifacts.

Topics

Resources

Code of conduct

Security policy

Stars

7 stars

Watchers

2 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Codecov Action

build

Self-hosted coverage and test reporting with GitHub Actions. Uses GitHub Artifacts for storage — no external service or Codecov token required.

Quick Start

name: Teston:
push:
branches: [main]pull_request:
jobs:
test:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: Run tests with coveragerun: npm test -- --coverage
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Supported Coverage Formats

FormatFile PatternsLanguages/Tools
Clover XMLclover.xmlIstanbul/NYC (JS/TS), PHPUnit, OpenClover
Cobertura XMLcoverage.xml, cobertura.xmlcoverage.py (Python), Coverlet (.NET), PHPUnit
JaCoCo XMLjacoco.xmlJava, Kotlin, Scala
LCOVlcov.info, *.lcovc8, lcov (C/C++), grcov (Rust), gcov
Istanbul JSONcoverage-final.jsonJest, Vitest, NYC (JS/TS)
Go Coveragecoverage.out, cover.outgo test -coverprofile
Codecov JSONcodecov.jsoncargo-llvm-cov (Rust), custom tools

Inputs

Core Inputs

InputDescriptionRequiredDefault
tokenGitHub token for API access and artifactsYes
base-branchBase branch to compare results againstNoAuto-detected
enable-testsEnable test results reportingNotrue
enable-coverageEnable coverage reportingNotrue
post-pr-commentPost results as a PR commentNofalse
comment-keyNamespace the PR comment per step so steps sharing this action post separate comments instead of overwriting each otherNo

Coverage File Discovery (Codecov-style)

InputDescriptionRequiredDefault
filesComma-separated list of coverage filesNo
directoryFolder to search for coverage filesNo.
excludeComma-separated patterns to excludeNo
coverage-formatFormat hint: auto, clover, cobertura, jacoco, lcov, istanbul, go, codecovNoauto
disable-searchDisable auto-search, use only explicit filesNofalse

Behavior Flags (Codecov-style)

InputDescriptionRequiredDefault
fail-ci-if-errorFail if coverage processing errors (e.g., parsing failures, missing files)Nofalse
handle-no-reports-foundDon't fail if no coverage foundNofalse
verboseEnable verbose loggingNofalse

Status Checks & Thresholds

InputDescriptionRequiredDefault
target-projectTarget project coverage % (or auto to use base branch coverage)No
threshold-projectAllowed project coverage drop % (only used when target is auto)No
target-patchTarget patch coverage % for changed linesNo80
fail-on-errorFail CI if coverage thresholds are not met (distinct from fail-ci-if-error)Nofalse

When thresholds are not configured, status checks report coverage metrics without enforcing pass/fail.

Grouping & Identification

InputDescriptionRequiredDefault
flagsComma-separated flags to tag coverage (e.g., unittests,frontend)No
nameCustom name for this coverage upload. Also used to differentiate artifacts in matrix buildsNo

Test Results

InputDescriptionRequiredDefault
junit-xml-patternGlob pattern for JUnit XML filesNo./**/*.junit.xml

Outputs

Test Outputs

OutputDescription
total-testsTotal number of tests run
passed-testsNumber of passed tests
failed-testsNumber of failed tests
test-pass-ratePercentage of tests that passed
tests-addedTests added compared to base branch
tests-removedTests removed compared to base branch
tests-fixedTests changed from failing to passing
tests-brokenTests changed from passing to failing

Coverage Outputs

OutputDescription
line-coverageLine coverage percentage
branch-coverageBranch coverage percentage
coverage-changeChange in line coverage vs base branch
branch-coverage-changeChange in branch coverage vs base branch
coverage-improvedWhether coverage improved (true/false)
coverage-formatThe detected/used coverage format

Usage Examples

Basic Usage (Auto-detect)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Explicit Files (Codecov-style)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage/lcov.info,./backend/coverage.xmldisable-search: trueflags: unittestsname: my-coverageverbose: true

Python with Cobertura

- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coverage-format: coberturafail-ci-if-error: true

Java with JaCoCo

- name: Build and testrun: ./gradlew test jacocoTestReport
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./build/reports/jacoco/test/jacocoTestReport.xmlcoverage-format: jacoco

Go Coverage

- name: Run testsrun: go test -coverprofile=coverage.out ./...
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage.outcoverage-format: go

Rust with cargo-llvm-cov

- name: Install cargo-llvm-covuses: taiki-e/install-action@cargo-llvm-cov
- name: Run tests with coveragerun: cargo llvm-cov --codecov --output-path codecov.json
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./codecov.jsoncoverage-format: codecov

JavaScript/TypeScript with LCOV

- name: Run testsrun: npm test -- --coverage --coverageReporters=lcov
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coveragecoverage-format: lcov

Monorepo with Flags

- name: Frontend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./frontend/coverageflags: frontendname: frontend-coverage
- name: Backend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./backend/coverageflags: backendname: backend-coverage

Matrix Builds

When running coverage in a matrix strategy (e.g., multiple Python versions), use the name input to give each matrix entry a unique artifact name and avoid upload conflicts:

jobs:
test:
runs-on: ubuntu-lateststrategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5with:
python-version: ${{ matrix.python-version }}
- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: coverage.xmlname: py${{ matrix.python-version }}

Coverage Thresholds with Status Checks

Use built-in threshold enforcement with GitHub status checks:

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}target-project: auto # Use base branch coverage as targetthreshold-project: 1# Allow up to 1% coverage droptarget-patch: 80# Require 80% coverage on changed linesfail-on-error: true # Fail CI if thresholds not met

This creates two status checks (codecov/project and codecov/patch) that:

  • Appear on commits and PRs
  • Can be required via branch protection rules
  • Provide clear pass/fail feedback

How It Works

1. File Discovery

The action searches for coverage files using:

  • Explicit files: If files input is provided
  • Auto-discovery: Searches directory for known coverage file patterns
  • Format detection: Auto-detects format from file content

2. Parsing & Aggregation

Multiple coverage files are parsed and aggregated:

  • Supports mixing formats (e.g., frontend LCOV + backend Cobertura)
  • Calculates unified line, branch, and method coverage

3. Artifact Storage

Results are stored as GitHub Artifacts:

  • codecov-coverage-results-{branch}[-{name}][-{flags}] — Aggregated coverage data
  • codecov-test-results-{branch} — Aggregated test results

When using the name input, it is appended to the artifact name to avoid conflicts in matrix builds.

4. Base Branch Comparison

On PRs or feature branches:

  1. Auto-detects the repository's default branch (or uses the explicit base-branch input)
  2. Downloads latest results from base branch
  3. Compares current vs baseline
  4. Calculates deltas

5. Reporting

  • Job Summary: Always generated in Actions UI
  • PR Comment: Optional detailed comment on PRs

6. Status Checks

The action creates GitHub commit status checks that appear on commits and PRs:

Status ContextDescription
codecov/projectOverall project coverage status (pass/fail based on target)
codecov/patchCoverage for changed lines in the PR

These status checks:

  • Show as green checkmarks or red X marks on commits and PRs
  • Can be used in branch protection rules to require coverage thresholds
  • Provide immediate feedback on coverage quality

Status Badges

Display your CI status in your README using GitHub's workflow badge:

![CI](https://github.com/{owner}/{repo}/actions/workflows/{workflow}.yml/badge.svg)

Test Results

Supported Format

FormatTypical FileCommon Test Frameworks
JUnit XML*.junit.xmlJest, Vitest, Mocha, pytest, JUnit, NUnit, PHPUnit

Configuration Examples

Jest / Vitest:

{
"reporters": ["default", ["jest-junit", { "outputFile": "report.junit.xml" }]]
}

pytest:

pytest --junitxml=report.junit.xml

Coverage Configuration Examples

JavaScript/TypeScript (Jest/Vitest)

{
"coverageReporters": ["lcov", "clover", "json"]
}

Python (pytest-cov)

pytest --cov=src --cov-report=xml # Cobertura format

Java (Gradle + JaCoCo)

jacocoTestReport {
reports {
xml.required =true
}
}

Go

go test -coverprofile=coverage.out ./...

Rust (cargo-llvm-cov)

# Install cargo-llvm-cov
cargo install cargo-llvm-cov
# Generate Codecov JSON format
cargo llvm-cov --codecov --output-path codecov.json
# Or generate LCOV format
cargo llvm-cov --lcov --output-path lcov.info

.NET (Coverlet)

dotnet test --collect:"XPlat Code Coverage"# or
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura

Configuration File

You can configure status check thresholds using a .github/coverage.yml file in your repository. Action inputs take precedence over the config file, allowing you to override settings per-workflow.

# .github/coverage.ymlcoverage:
status:
project:
target: 80# Target coverage percentage (or "auto" to use base branch)threshold: 1# Allowed coverage drop when using "auto" (supports "1%" or 1)informational: false # When true, status check reports but never fails the buildpatch:
target: 90# Target coverage for changed linesinformational: falseignore:
- "**/*.test.ts"# Patterns to exclude from coverage
- "**/fixtures/**"# Enable PR comments from config (alternative to post-pr-comment input)comment: true# Report display settingsconfig:
files: changed # all (default) | changed | none
OptionDescription
status.project.targetTarget project coverage % (number or "auto")
status.project.thresholdAllowed drop from base branch when target is "auto". Supports number (1) or string ("1%")
status.project.informationalWhen true, status check reports but never fails the build (advisory mode)
status.patch.targetTarget coverage % for changed lines
status.patch.informationalWhen true, patch status check is advisory-only
ignoreGlob patterns to exclude from coverage calculations
commentEnable PR comments. Set to true or false
config.filesControl file table scope in reports (Job Summary + PR comments). Values: all (default), changed, none

Codecov YAML Compatibility

This action also supports the standard Codecov YAML format with nested default keys:

# .github/codecov.yml (Codecov-compatible format)coverage:
status:
project:
default:
target: autothreshold: 10%# Percentage strings are supportedinformational: truepatch:
default:
target: 80ignore:
- "tests/**"comment: trueconfig:
files: changed

Both formats work identically—use whichever style you prefer.

Report File List Mode

Use config.files to control the "Files with missing lines" section in both Job Summary and PR comments:

  • all (default): show all files with missing/partial lines
  • changed: show only non-deleted files from the PR diff
  • none: hide the section entirely

Permissions

permissions:
contents: read # Read repository contentsactions: read # Read workflow runs and artifactspull-requests: write # Post PR comments (if enabled)statuses: write # Create commit status checks

Note: On pull requests from forks, GITHUB_TOKEN has restricted permissions regardless of the workflow's permissions block. PR comments and commit status checks will be skipped gracefully with a warning in this case. Coverage results and Job Summary are still generated.

Migration from Codecov

If you're migrating from the official Codecov action:

Codecov InputThis Action
fail_ci_if_errorfail-ci-if-error
filesfiles
directorydirectory
excludeexclude
flagsflags
namename
verboseverbose
handle-no-reports-foundhandle-no-reports-found

Note: This action doesn't require a Codecov token—it uses GitHub's native artifacts for storage.

About

GitHub Action for code coverage and test result reporting using GitHub Artifacts.

Topics

Resources

Code of conduct

Security policy

Stars

7 stars

Watchers

2 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Codecov Action

build

Self-hosted coverage and test reporting with GitHub Actions. Uses GitHub Artifacts for storage — no external service or Codecov token required.

Quick Start

name: Teston:
push:
branches: [main]pull_request:
jobs:
test:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: Run tests with coveragerun: npm test -- --coverage
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Supported Coverage Formats

FormatFile PatternsLanguages/Tools
Clover XMLclover.xmlIstanbul/NYC (JS/TS), PHPUnit, OpenClover
Cobertura XMLcoverage.xml, cobertura.xmlcoverage.py (Python), Coverlet (.NET), PHPUnit
JaCoCo XMLjacoco.xmlJava, Kotlin, Scala
LCOVlcov.info, *.lcovc8, lcov (C/C++), grcov (Rust), gcov
Istanbul JSONcoverage-final.jsonJest, Vitest, NYC (JS/TS)
Go Coveragecoverage.out, cover.outgo test -coverprofile
Codecov JSONcodecov.jsoncargo-llvm-cov (Rust), custom tools

Inputs

Core Inputs

InputDescriptionRequiredDefault
tokenGitHub token for API access and artifactsYes
base-branchBase branch to compare results againstNoAuto-detected
enable-testsEnable test results reportingNotrue
enable-coverageEnable coverage reportingNotrue
post-pr-commentPost results as a PR commentNofalse
comment-keyNamespace the PR comment per step so steps sharing this action post separate comments instead of overwriting each otherNo

Coverage File Discovery (Codecov-style)

InputDescriptionRequiredDefault
filesComma-separated list of coverage filesNo
directoryFolder to search for coverage filesNo.
excludeComma-separated patterns to excludeNo
coverage-formatFormat hint: auto, clover, cobertura, jacoco, lcov, istanbul, go, codecovNoauto
disable-searchDisable auto-search, use only explicit filesNofalse

Behavior Flags (Codecov-style)

InputDescriptionRequiredDefault
fail-ci-if-errorFail if coverage processing errors (e.g., parsing failures, missing files)Nofalse
handle-no-reports-foundDon't fail if no coverage foundNofalse
verboseEnable verbose loggingNofalse

Status Checks & Thresholds

InputDescriptionRequiredDefault
target-projectTarget project coverage % (or auto to use base branch coverage)No
threshold-projectAllowed project coverage drop % (only used when target is auto)No
target-patchTarget patch coverage % for changed linesNo80
fail-on-errorFail CI if coverage thresholds are not met (distinct from fail-ci-if-error)Nofalse

When thresholds are not configured, status checks report coverage metrics without enforcing pass/fail.

Grouping & Identification

InputDescriptionRequiredDefault
flagsComma-separated flags to tag coverage (e.g., unittests,frontend)No
nameCustom name for this coverage upload. Also used to differentiate artifacts in matrix buildsNo

Test Results

InputDescriptionRequiredDefault
junit-xml-patternGlob pattern for JUnit XML filesNo./**/*.junit.xml

Outputs

Test Outputs

OutputDescription
total-testsTotal number of tests run
passed-testsNumber of passed tests
failed-testsNumber of failed tests
test-pass-ratePercentage of tests that passed
tests-addedTests added compared to base branch
tests-removedTests removed compared to base branch
tests-fixedTests changed from failing to passing
tests-brokenTests changed from passing to failing

Coverage Outputs

OutputDescription
line-coverageLine coverage percentage
branch-coverageBranch coverage percentage
coverage-changeChange in line coverage vs base branch
branch-coverage-changeChange in branch coverage vs base branch
coverage-improvedWhether coverage improved (true/false)
coverage-formatThe detected/used coverage format

Usage Examples

Basic Usage (Auto-detect)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Explicit Files (Codecov-style)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage/lcov.info,./backend/coverage.xmldisable-search: trueflags: unittestsname: my-coverageverbose: true

Python with Cobertura

- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coverage-format: coberturafail-ci-if-error: true

Java with JaCoCo

- name: Build and testrun: ./gradlew test jacocoTestReport
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./build/reports/jacoco/test/jacocoTestReport.xmlcoverage-format: jacoco

Go Coverage

- name: Run testsrun: go test -coverprofile=coverage.out ./...
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage.outcoverage-format: go

Rust with cargo-llvm-cov

- name: Install cargo-llvm-covuses: taiki-e/install-action@cargo-llvm-cov
- name: Run tests with coveragerun: cargo llvm-cov --codecov --output-path codecov.json
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./codecov.jsoncoverage-format: codecov

JavaScript/TypeScript with LCOV

- name: Run testsrun: npm test -- --coverage --coverageReporters=lcov
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coveragecoverage-format: lcov

Monorepo with Flags

- name: Frontend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./frontend/coverageflags: frontendname: frontend-coverage
- name: Backend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./backend/coverageflags: backendname: backend-coverage

Matrix Builds

When running coverage in a matrix strategy (e.g., multiple Python versions), use the name input to give each matrix entry a unique artifact name and avoid upload conflicts:

jobs:
test:
runs-on: ubuntu-lateststrategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5with:
python-version: ${{ matrix.python-version }}
- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: coverage.xmlname: py${{ matrix.python-version }}

Coverage Thresholds with Status Checks

Use built-in threshold enforcement with GitHub status checks:

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}target-project: auto # Use base branch coverage as targetthreshold-project: 1# Allow up to 1% coverage droptarget-patch: 80# Require 80% coverage on changed linesfail-on-error: true # Fail CI if thresholds not met

This creates two status checks (codecov/project and codecov/patch) that:

  • Appear on commits and PRs
  • Can be required via branch protection rules
  • Provide clear pass/fail feedback

How It Works

1. File Discovery

The action searches for coverage files using:

  • Explicit files: If files input is provided
  • Auto-discovery: Searches directory for known coverage file patterns
  • Format detection: Auto-detects format from file content

2. Parsing & Aggregation

Multiple coverage files are parsed and aggregated:

  • Supports mixing formats (e.g., frontend LCOV + backend Cobertura)
  • Calculates unified line, branch, and method coverage

3. Artifact Storage

Results are stored as GitHub Artifacts:

  • codecov-coverage-results-{branch}[-{name}][-{flags}] — Aggregated coverage data
  • codecov-test-results-{branch} — Aggregated test results

When using the name input, it is appended to the artifact name to avoid conflicts in matrix builds.

4. Base Branch Comparison

On PRs or feature branches:

  1. Auto-detects the repository's default branch (or uses the explicit base-branch input)
  2. Downloads latest results from base branch
  3. Compares current vs baseline
  4. Calculates deltas

5. Reporting

  • Job Summary: Always generated in Actions UI
  • PR Comment: Optional detailed comment on PRs

6. Status Checks

The action creates GitHub commit status checks that appear on commits and PRs:

Status ContextDescription
codecov/projectOverall project coverage status (pass/fail based on target)
codecov/patchCoverage for changed lines in the PR

These status checks:

  • Show as green checkmarks or red X marks on commits and PRs
  • Can be used in branch protection rules to require coverage thresholds
  • Provide immediate feedback on coverage quality

Status Badges

Display your CI status in your README using GitHub's workflow badge:

![CI](https://github.com/{owner}/{repo}/actions/workflows/{workflow}.yml/badge.svg)

Test Results

Supported Format

FormatTypical FileCommon Test Frameworks
JUnit XML*.junit.xmlJest, Vitest, Mocha, pytest, JUnit, NUnit, PHPUnit

Configuration Examples

Jest / Vitest:

{
"reporters": ["default", ["jest-junit", { "outputFile": "report.junit.xml" }]]
}

pytest:

pytest --junitxml=report.junit.xml

Coverage Configuration Examples

JavaScript/TypeScript (Jest/Vitest)

{
"coverageReporters": ["lcov", "clover", "json"]
}

Python (pytest-cov)

pytest --cov=src --cov-report=xml # Cobertura format

Java (Gradle + JaCoCo)

jacocoTestReport {
reports {
xml.required =true
}
}

Go

go test -coverprofile=coverage.out ./...

Rust (cargo-llvm-cov)

# Install cargo-llvm-cov
cargo install cargo-llvm-cov
# Generate Codecov JSON format
cargo llvm-cov --codecov --output-path codecov.json
# Or generate LCOV format
cargo llvm-cov --lcov --output-path lcov.info

.NET (Coverlet)

dotnet test --collect:"XPlat Code Coverage"# or
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura

Configuration File

You can configure status check thresholds using a .github/coverage.yml file in your repository. Action inputs take precedence over the config file, allowing you to override settings per-workflow.

# .github/coverage.ymlcoverage:
status:
project:
target: 80# Target coverage percentage (or "auto" to use base branch)threshold: 1# Allowed coverage drop when using "auto" (supports "1%" or 1)informational: false # When true, status check reports but never fails the buildpatch:
target: 90# Target coverage for changed linesinformational: falseignore:
- "**/*.test.ts"# Patterns to exclude from coverage
- "**/fixtures/**"# Enable PR comments from config (alternative to post-pr-comment input)comment: true# Report display settingsconfig:
files: changed # all (default) | changed | none
OptionDescription
status.project.targetTarget project coverage % (number or "auto")
status.project.thresholdAllowed drop from base branch when target is "auto". Supports number (1) or string ("1%")
status.project.informationalWhen true, status check reports but never fails the build (advisory mode)
status.patch.targetTarget coverage % for changed lines
status.patch.informationalWhen true, patch status check is advisory-only
ignoreGlob patterns to exclude from coverage calculations
commentEnable PR comments. Set to true or false
config.filesControl file table scope in reports (Job Summary + PR comments). Values: all (default), changed, none

Codecov YAML Compatibility

This action also supports the standard Codecov YAML format with nested default keys:

# .github/codecov.yml (Codecov-compatible format)coverage:
status:
project:
default:
target: autothreshold: 10%# Percentage strings are supportedinformational: truepatch:
default:
target: 80ignore:
- "tests/**"comment: trueconfig:
files: changed

Both formats work identically—use whichever style you prefer.

Report File List Mode

Use config.files to control the "Files with missing lines" section in both Job Summary and PR comments:

  • all (default): show all files with missing/partial lines
  • changed: show only non-deleted files from the PR diff
  • none: hide the section entirely

Permissions

permissions:
contents: read # Read repository contentsactions: read # Read workflow runs and artifactspull-requests: write # Post PR comments (if enabled)statuses: write # Create commit status checks

Note: On pull requests from forks, GITHUB_TOKEN has restricted permissions regardless of the workflow's permissions block. PR comments and commit status checks will be skipped gracefully with a warning in this case. Coverage results and Job Summary are still generated.

Migration from Codecov

If you're migrating from the official Codecov action:

Codecov InputThis Action
fail_ci_if_errorfail-ci-if-error
filesfiles
directorydirectory
excludeexclude
flagsflags
namename
verboseverbose
handle-no-reports-foundhandle-no-reports-found

Note: This action doesn't require a Codecov token—it uses GitHub's native artifacts for storage.

About

GitHub Action for code coverage and test result reporting using GitHub Artifacts.

Topics

Resources

Code of conduct

Security policy

Stars

7 stars

Watchers

2 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Codecov Action

build

Self-hosted coverage and test reporting with GitHub Actions. Uses GitHub Artifacts for storage — no external service or Codecov token required.

Quick Start

name: Teston:
push:
branches: [main]pull_request:
jobs:
test:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: Run tests with coveragerun: npm test -- --coverage
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Supported Coverage Formats

FormatFile PatternsLanguages/Tools
Clover XMLclover.xmlIstanbul/NYC (JS/TS), PHPUnit, OpenClover
Cobertura XMLcoverage.xml, cobertura.xmlcoverage.py (Python), Coverlet (.NET), PHPUnit
JaCoCo XMLjacoco.xmlJava, Kotlin, Scala
LCOVlcov.info, *.lcovc8, lcov (C/C++), grcov (Rust), gcov
Istanbul JSONcoverage-final.jsonJest, Vitest, NYC (JS/TS)
Go Coveragecoverage.out, cover.outgo test -coverprofile
Codecov JSONcodecov.jsoncargo-llvm-cov (Rust), custom tools

Inputs

Core Inputs

InputDescriptionRequiredDefault
tokenGitHub token for API access and artifactsYes
base-branchBase branch to compare results againstNoAuto-detected
enable-testsEnable test results reportingNotrue
enable-coverageEnable coverage reportingNotrue
post-pr-commentPost results as a PR commentNofalse
comment-keyNamespace the PR comment per step so steps sharing this action post separate comments instead of overwriting each otherNo

Coverage File Discovery (Codecov-style)

InputDescriptionRequiredDefault
filesComma-separated list of coverage filesNo
directoryFolder to search for coverage filesNo.
excludeComma-separated patterns to excludeNo
coverage-formatFormat hint: auto, clover, cobertura, jacoco, lcov, istanbul, go, codecovNoauto
disable-searchDisable auto-search, use only explicit filesNofalse

Behavior Flags (Codecov-style)

InputDescriptionRequiredDefault
fail-ci-if-errorFail if coverage processing errors (e.g., parsing failures, missing files)Nofalse
handle-no-reports-foundDon't fail if no coverage foundNofalse
verboseEnable verbose loggingNofalse

Status Checks & Thresholds

InputDescriptionRequiredDefault
target-projectTarget project coverage % (or auto to use base branch coverage)No
threshold-projectAllowed project coverage drop % (only used when target is auto)No
target-patchTarget patch coverage % for changed linesNo80
fail-on-errorFail CI if coverage thresholds are not met (distinct from fail-ci-if-error)Nofalse

When thresholds are not configured, status checks report coverage metrics without enforcing pass/fail.

Grouping & Identification

InputDescriptionRequiredDefault
flagsComma-separated flags to tag coverage (e.g., unittests,frontend)No
nameCustom name for this coverage upload. Also used to differentiate artifacts in matrix buildsNo

Test Results

InputDescriptionRequiredDefault
junit-xml-patternGlob pattern for JUnit XML filesNo./**/*.junit.xml

Outputs

Test Outputs

OutputDescription
total-testsTotal number of tests run
passed-testsNumber of passed tests
failed-testsNumber of failed tests
test-pass-ratePercentage of tests that passed
tests-addedTests added compared to base branch
tests-removedTests removed compared to base branch
tests-fixedTests changed from failing to passing
tests-brokenTests changed from passing to failing

Coverage Outputs

OutputDescription
line-coverageLine coverage percentage
branch-coverageBranch coverage percentage
coverage-changeChange in line coverage vs base branch
branch-coverage-changeChange in branch coverage vs base branch
coverage-improvedWhether coverage improved (true/false)
coverage-formatThe detected/used coverage format

Usage Examples

Basic Usage (Auto-detect)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Explicit Files (Codecov-style)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage/lcov.info,./backend/coverage.xmldisable-search: trueflags: unittestsname: my-coverageverbose: true

Python with Cobertura

- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coverage-format: coberturafail-ci-if-error: true

Java with JaCoCo

- name: Build and testrun: ./gradlew test jacocoTestReport
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./build/reports/jacoco/test/jacocoTestReport.xmlcoverage-format: jacoco

Go Coverage

- name: Run testsrun: go test -coverprofile=coverage.out ./...
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage.outcoverage-format: go

Rust with cargo-llvm-cov

- name: Install cargo-llvm-covuses: taiki-e/install-action@cargo-llvm-cov
- name: Run tests with coveragerun: cargo llvm-cov --codecov --output-path codecov.json
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./codecov.jsoncoverage-format: codecov

JavaScript/TypeScript with LCOV

- name: Run testsrun: npm test -- --coverage --coverageReporters=lcov
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coveragecoverage-format: lcov

Monorepo with Flags

- name: Frontend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./frontend/coverageflags: frontendname: frontend-coverage
- name: Backend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./backend/coverageflags: backendname: backend-coverage

Matrix Builds

When running coverage in a matrix strategy (e.g., multiple Python versions), use the name input to give each matrix entry a unique artifact name and avoid upload conflicts:

jobs:
test:
runs-on: ubuntu-lateststrategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5with:
python-version: ${{ matrix.python-version }}
- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: coverage.xmlname: py${{ matrix.python-version }}

Coverage Thresholds with Status Checks

Use built-in threshold enforcement with GitHub status checks:

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}target-project: auto # Use base branch coverage as targetthreshold-project: 1# Allow up to 1% coverage droptarget-patch: 80# Require 80% coverage on changed linesfail-on-error: true # Fail CI if thresholds not met

This creates two status checks (codecov/project and codecov/patch) that:

  • Appear on commits and PRs
  • Can be required via branch protection rules
  • Provide clear pass/fail feedback

How It Works

1. File Discovery

The action searches for coverage files using:

  • Explicit files: If files input is provided
  • Auto-discovery: Searches directory for known coverage file patterns
  • Format detection: Auto-detects format from file content

2. Parsing & Aggregation

Multiple coverage files are parsed and aggregated:

  • Supports mixing formats (e.g., frontend LCOV + backend Cobertura)
  • Calculates unified line, branch, and method coverage

3. Artifact Storage

Results are stored as GitHub Artifacts:

  • codecov-coverage-results-{branch}[-{name}][-{flags}] — Aggregated coverage data
  • codecov-test-results-{branch} — Aggregated test results

When using the name input, it is appended to the artifact name to avoid conflicts in matrix builds.

4. Base Branch Comparison

On PRs or feature branches:

  1. Auto-detects the repository's default branch (or uses the explicit base-branch input)
  2. Downloads latest results from base branch
  3. Compares current vs baseline
  4. Calculates deltas

5. Reporting

  • Job Summary: Always generated in Actions UI
  • PR Comment: Optional detailed comment on PRs

6. Status Checks

The action creates GitHub commit status checks that appear on commits and PRs:

Status ContextDescription
codecov/projectOverall project coverage status (pass/fail based on target)
codecov/patchCoverage for changed lines in the PR

These status checks:

  • Show as green checkmarks or red X marks on commits and PRs
  • Can be used in branch protection rules to require coverage thresholds
  • Provide immediate feedback on coverage quality

Status Badges

Display your CI status in your README using GitHub's workflow badge:

![CI](https://github.com/{owner}/{repo}/actions/workflows/{workflow}.yml/badge.svg)

Test Results

Supported Format

FormatTypical FileCommon Test Frameworks
JUnit XML*.junit.xmlJest, Vitest, Mocha, pytest, JUnit, NUnit, PHPUnit

Configuration Examples

Jest / Vitest:

{
"reporters": ["default", ["jest-junit", { "outputFile": "report.junit.xml" }]]
}

pytest:

pytest --junitxml=report.junit.xml

Coverage Configuration Examples

JavaScript/TypeScript (Jest/Vitest)

{
"coverageReporters": ["lcov", "clover", "json"]
}

Python (pytest-cov)

pytest --cov=src --cov-report=xml # Cobertura format

Java (Gradle + JaCoCo)

jacocoTestReport {
reports {
xml.required =true
}
}

Go

go test -coverprofile=coverage.out ./...

Rust (cargo-llvm-cov)

# Install cargo-llvm-cov
cargo install cargo-llvm-cov
# Generate Codecov JSON format
cargo llvm-cov --codecov --output-path codecov.json
# Or generate LCOV format
cargo llvm-cov --lcov --output-path lcov.info

.NET (Coverlet)

dotnet test --collect:"XPlat Code Coverage"# or
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura

Configuration File

You can configure status check thresholds using a .github/coverage.yml file in your repository. Action inputs take precedence over the config file, allowing you to override settings per-workflow.

# .github/coverage.ymlcoverage:
status:
project:
target: 80# Target coverage percentage (or "auto" to use base branch)threshold: 1# Allowed coverage drop when using "auto" (supports "1%" or 1)informational: false # When true, status check reports but never fails the buildpatch:
target: 90# Target coverage for changed linesinformational: falseignore:
- "**/*.test.ts"# Patterns to exclude from coverage
- "**/fixtures/**"# Enable PR comments from config (alternative to post-pr-comment input)comment: true# Report display settingsconfig:
files: changed # all (default) | changed | none
OptionDescription
status.project.targetTarget project coverage % (number or "auto")
status.project.thresholdAllowed drop from base branch when target is "auto". Supports number (1) or string ("1%")
status.project.informationalWhen true, status check reports but never fails the build (advisory mode)
status.patch.targetTarget coverage % for changed lines
status.patch.informationalWhen true, patch status check is advisory-only
ignoreGlob patterns to exclude from coverage calculations
commentEnable PR comments. Set to true or false
config.filesControl file table scope in reports (Job Summary + PR comments). Values: all (default), changed, none

Codecov YAML Compatibility

This action also supports the standard Codecov YAML format with nested default keys:

# .github/codecov.yml (Codecov-compatible format)coverage:
status:
project:
default:
target: autothreshold: 10%# Percentage strings are supportedinformational: truepatch:
default:
target: 80ignore:
- "tests/**"comment: trueconfig:
files: changed

Both formats work identically—use whichever style you prefer.

Report File List Mode

Use config.files to control the "Files with missing lines" section in both Job Summary and PR comments:

  • all (default): show all files with missing/partial lines
  • changed: show only non-deleted files from the PR diff
  • none: hide the section entirely

Permissions

permissions:
contents: read # Read repository contentsactions: read # Read workflow runs and artifactspull-requests: write # Post PR comments (if enabled)statuses: write # Create commit status checks

Note: On pull requests from forks, GITHUB_TOKEN has restricted permissions regardless of the workflow's permissions block. PR comments and commit status checks will be skipped gracefully with a warning in this case. Coverage results and Job Summary are still generated.

Migration from Codecov

If you're migrating from the official Codecov action:

Codecov InputThis Action
fail_ci_if_errorfail-ci-if-error
filesfiles
directorydirectory
excludeexclude
flagsflags
namename
verboseverbose
handle-no-reports-foundhandle-no-reports-found

Note: This action doesn't require a Codecov token—it uses GitHub's native artifacts for storage.

About

GitHub Action for code coverage and test result reporting using GitHub Artifacts.

Topics

Resources

Code of conduct

Security policy

Stars

7 stars

Watchers

2 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Codecov Action

build

Self-hosted coverage and test reporting with GitHub Actions. Uses GitHub Artifacts for storage — no external service or Codecov token required.

Quick Start

name: Teston:
push:
branches: [main]pull_request:
jobs:
test:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- name: Run tests with coveragerun: npm test -- --coverage
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Supported Coverage Formats

FormatFile PatternsLanguages/Tools
Clover XMLclover.xmlIstanbul/NYC (JS/TS), PHPUnit, OpenClover
Cobertura XMLcoverage.xml, cobertura.xmlcoverage.py (Python), Coverlet (.NET), PHPUnit
JaCoCo XMLjacoco.xmlJava, Kotlin, Scala
LCOVlcov.info, *.lcovc8, lcov (C/C++), grcov (Rust), gcov
Istanbul JSONcoverage-final.jsonJest, Vitest, NYC (JS/TS)
Go Coveragecoverage.out, cover.outgo test -coverprofile
Codecov JSONcodecov.jsoncargo-llvm-cov (Rust), custom tools

Inputs

Core Inputs

InputDescriptionRequiredDefault
tokenGitHub token for API access and artifactsYes
base-branchBase branch to compare results againstNoAuto-detected
enable-testsEnable test results reportingNotrue
enable-coverageEnable coverage reportingNotrue
post-pr-commentPost results as a PR commentNofalse
comment-keyNamespace the PR comment per step so steps sharing this action post separate comments instead of overwriting each otherNo

Coverage File Discovery (Codecov-style)

InputDescriptionRequiredDefault
filesComma-separated list of coverage filesNo
directoryFolder to search for coverage filesNo.
excludeComma-separated patterns to excludeNo
coverage-formatFormat hint: auto, clover, cobertura, jacoco, lcov, istanbul, go, codecovNoauto
disable-searchDisable auto-search, use only explicit filesNofalse

Behavior Flags (Codecov-style)

InputDescriptionRequiredDefault
fail-ci-if-errorFail if coverage processing errors (e.g., parsing failures, missing files)Nofalse
handle-no-reports-foundDon't fail if no coverage foundNofalse
verboseEnable verbose loggingNofalse

Status Checks & Thresholds

InputDescriptionRequiredDefault
target-projectTarget project coverage % (or auto to use base branch coverage)No
threshold-projectAllowed project coverage drop % (only used when target is auto)No
target-patchTarget patch coverage % for changed linesNo80
fail-on-errorFail CI if coverage thresholds are not met (distinct from fail-ci-if-error)Nofalse

When thresholds are not configured, status checks report coverage metrics without enforcing pass/fail.

Grouping & Identification

InputDescriptionRequiredDefault
flagsComma-separated flags to tag coverage (e.g., unittests,frontend)No
nameCustom name for this coverage upload. Also used to differentiate artifacts in matrix buildsNo

Test Results

InputDescriptionRequiredDefault
junit-xml-patternGlob pattern for JUnit XML filesNo./**/*.junit.xml

Outputs

Test Outputs

OutputDescription
total-testsTotal number of tests run
passed-testsNumber of passed tests
failed-testsNumber of failed tests
test-pass-ratePercentage of tests that passed
tests-addedTests added compared to base branch
tests-removedTests removed compared to base branch
tests-fixedTests changed from failing to passing
tests-brokenTests changed from passing to failing

Coverage Outputs

OutputDescription
line-coverageLine coverage percentage
branch-coverageBranch coverage percentage
coverage-changeChange in line coverage vs base branch
branch-coverage-changeChange in branch coverage vs base branch
coverage-improvedWhether coverage improved (true/false)
coverage-formatThe detected/used coverage format

Usage Examples

Basic Usage (Auto-detect)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}

Explicit Files (Codecov-style)

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage/lcov.info,./backend/coverage.xmldisable-search: trueflags: unittestsname: my-coverageverbose: true

Python with Cobertura

- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coverage-format: coberturafail-ci-if-error: true

Java with JaCoCo

- name: Build and testrun: ./gradlew test jacocoTestReport
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./build/reports/jacoco/test/jacocoTestReport.xmlcoverage-format: jacoco

Go Coverage

- name: Run testsrun: go test -coverprofile=coverage.out ./...
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./coverage.outcoverage-format: go

Rust with cargo-llvm-cov

- name: Install cargo-llvm-covuses: taiki-e/install-action@cargo-llvm-cov
- name: Run tests with coveragerun: cargo llvm-cov --codecov --output-path codecov.json
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: ./codecov.jsoncoverage-format: codecov

JavaScript/TypeScript with LCOV

- name: Run testsrun: npm test -- --coverage --coverageReporters=lcov
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./coveragecoverage-format: lcov

Monorepo with Flags

- name: Frontend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./frontend/coverageflags: frontendname: frontend-coverage
- name: Backend Coverageuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}directory: ./backend/coverageflags: backendname: backend-coverage

Matrix Builds

When running coverage in a matrix strategy (e.g., multiple Python versions), use the name input to give each matrix entry a unique artifact name and avoid upload conflicts:

jobs:
test:
runs-on: ubuntu-lateststrategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5with:
python-version: ${{ matrix.python-version }}
- name: Run testsrun: pytest --cov=src --cov-report=xml
- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}files: coverage.xmlname: py${{ matrix.python-version }}

Coverage Thresholds with Status Checks

Use built-in threshold enforcement with GitHub status checks:

- name: Codecov Actionuses: getsentry/codecov-action@v1with:
token: ${{ secrets.GITHUB_TOKEN }}target-project: auto # Use base branch coverage as targetthreshold-project: 1# Allow up to 1% coverage droptarget-patch: 80# Require 80% coverage on changed linesfail-on-error: true # Fail CI if thresholds not met

This creates two status checks (codecov/project and codecov/patch) that:

  • Appear on commits and PRs
  • Can be required via branch protection rules
  • Provide clear pass/fail feedback

How It Works

1. File Discovery

The action searches for coverage files using:

  • Explicit files: If files input is provided
  • Auto-discovery: Searches directory for known coverage file patterns
  • Format detection: Auto-detects format from file content

2. Parsing & Aggregation

Multiple coverage files are parsed and aggregated:

  • Supports mixing formats (e.g., frontend LCOV + backend Cobertura)
  • Calculates unified line, branch, and method coverage

3. Artifact Storage

Results are stored as GitHub Artifacts:

  • codecov-coverage-results-{branch}[-{name}][-{flags}] — Aggregated coverage data
  • codecov-test-results-{branch} — Aggregated test results

When using the name input, it is appended to the artifact name to avoid conflicts in matrix builds.

4. Base Branch Comparison

On PRs or feature branches:

  1. Auto-detects the repository's default branch (or uses the explicit base-branch input)
  2. Downloads latest results from base branch
  3. Compares current vs baseline
  4. Calculates deltas

5. Reporting

  • Job Summary: Always generated in Actions UI
  • PR Comment: Optional detailed comment on PRs

6. Status Checks

The action creates GitHub commit status checks that appear on commits and PRs:

Status ContextDescription
codecov/projectOverall project coverage status (pass/fail based on target)
codecov/patchCoverage for changed lines in the PR

These status checks:

  • Show as green checkmarks or red X marks on commits and PRs
  • Can be used in branch protection rules to require coverage thresholds
  • Provide immediate feedback on coverage quality

Status Badges

Display your CI status in your README using GitHub's workflow badge:

![CI](https://github.com/{owner}/{repo}/actions/workflows/{workflow}.yml/badge.svg)

Test Results

Supported Format

FormatTypical FileCommon Test Frameworks
JUnit XML*.junit.xmlJest, Vitest, Mocha, pytest, JUnit, NUnit, PHPUnit

Configuration Examples

Jest / Vitest:

{
"reporters": ["default", ["jest-junit", { "outputFile": "report.junit.xml" }]]
}

pytest:

pytest --junitxml=report.junit.xml

Coverage Configuration Examples

JavaScript/TypeScript (Jest/Vitest)

{
"coverageReporters": ["lcov", "clover", "json"]
}

Python (pytest-cov)

pytest --cov=src --cov-report=xml # Cobertura format

Java (Gradle + JaCoCo)

jacocoTestReport {
reports {
xml.required =true
}
}

Go

go test -coverprofile=coverage.out ./...

Rust (cargo-llvm-cov)

# Install cargo-llvm-cov
cargo install cargo-llvm-cov
# Generate Codecov JSON format
cargo llvm-cov --codecov --output-path codecov.json
# Or generate LCOV format
cargo llvm-cov --lcov --output-path lcov.info

.NET (Coverlet)

dotnet test --collect:"XPlat Code Coverage"# or
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura

Configuration File

You can configure status check thresholds using a .github/coverage.yml file in your repository. Action inputs take precedence over the config file, allowing you to override settings per-workflow.

# .github/coverage.ymlcoverage:
status:
project:
target: 80# Target coverage percentage (or "auto" to use base branch)threshold: 1# Allowed coverage drop when using "auto" (supports "1%" or 1)informational: false # When true, status check reports but never fails the buildpatch:
target: 90# Target coverage for changed linesinformational: falseignore:
- "**/*.test.ts"# Patterns to exclude from coverage
- "**/fixtures/**"# Enable PR comments from config (alternative to post-pr-comment input)comment: true# Report display settingsconfig:
files: changed # all (default) | changed | none
OptionDescription
status.project.targetTarget project coverage % (number or "auto")
status.project.thresholdAllowed drop from base branch when target is "auto". Supports number (1) or string ("1%")
status.project.informationalWhen true, status check reports but never fails the build (advisory mode)
status.patch.targetTarget coverage % for changed lines
status.patch.informationalWhen true, patch status check is advisory-only
ignoreGlob patterns to exclude from coverage calculations
commentEnable PR comments. Set to true or false
config.filesControl file table scope in reports (Job Summary + PR comments). Values: all (default), changed, none

Codecov YAML Compatibility

This action also supports the standard Codecov YAML format with nested default keys:

# .github/codecov.yml (Codecov-compatible format)coverage:
status:
project:
default:
target: autothreshold: 10%# Percentage strings are supportedinformational: truepatch:
default:
target: 80ignore:
- "tests/**"comment: trueconfig:
files: changed

Both formats work identically—use whichever style you prefer.

Report File List Mode

Use config.files to control the "Files with missing lines" section in both Job Summary and PR comments:

  • all (default): show all files with missing/partial lines
  • changed: show only non-deleted files from the PR diff
  • none: hide the section entirely

Permissions

permissions:
contents: read # Read repository contentsactions: read # Read workflow runs and artifactspull-requests: write # Post PR comments (if enabled)statuses: write # Create commit status checks

Note: On pull requests from forks, GITHUB_TOKEN has restricted permissions regardless of the workflow's permissions block. PR comments and commit status checks will be skipped gracefully with a warning in this case. Coverage results and Job Summary are still generated.

Migration from Codecov

If you're migrating from the official Codecov action:

Codecov InputThis Action
fail_ci_if_errorfail-ci-if-error
filesfiles
directorydirectory
excludeexclude
flagsflags
namename
verboseverbose
handle-no-reports-foundhandle-no-reports-found

Note: This action doesn't require a Codecov token—it uses GitHub's native artifacts for storage.

About

GitHub Action for code coverage and test result reporting using GitHub Artifacts.

Topics

Resources

Code of conduct

Security policy

Stars

7 stars

Watchers

2 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages