Guide
Uploading Test Coverage to Codecov from a CI Pipeline
Learn how to upload test coverage to Codecov from any CI pipeline using the official uploader, with steps for prerequisites, execution, verification, and recovery.
Published by Tasadduq Burney
23 Jul 2025, 00:57 UTC
4 min47.1K views0

Desired outcome
After your test suite runs, you want the coverage data to be sent to Codecov so that the repository dashboard shows the latest percentage and any pull request receives a status check indicating whether the change meets your coverage thresholds.
Prerequisites
- A Codecov upload token with the
uploadscope. Treat this token as a secret; store it in your CI system’s secret store and reference it as an environment variable (e.g.,$CODECOV_TOKEN). - A CI environment that can execute tests and generate a coverage report in a format Codecov understands (LCOV
.info, Cobertura XML, JaCoCo XML, or Pythoncoverage.xml). - The Codecov uploader available in the runner’s
PATH. You can obtain it by downloading the official bash script (curl -s https://codecov.io/bash) or by using the official Docker image (docker pull codecov/codecov). - Basic command‑line tools such as
curlandjq(required by the bash uploader). If your runner is minimal (e.g., Alpine), ensure these are installed or use the Docker image which already includes them.
Focused procedure
- Run your test suite and produce a coverage file. Example for a Python project using
pytestandpytest‑cov:# In the CI job, after installing dependencies pytest --cov=my_package --cov-report=xml:coverage.xml - Make the coverage file accessible to the uploader. The file path can be absolute or relative to the working directory.
- Invoke the Codecov uploader, passing the token and the path to the report. Using the bash uploader:
Optional flags:bash <(curl -s https://codecov.io/bash) -t $CODECOV_TOKEN -f coverage.xml-F ui,apito apply flags for different parts of the codebase.-X gcovto disable gcov processing if not needed.-vfor verbose output (useful for debugging).
- If you prefer the Docker image, the command is:
docker run --rm -v $(pwd):/workspace -e CODECOV_TOKEN=$CODECOV_TOKEN \ codecov/codecov -f coverage.xml - Allow the uploader to finish. It will exit with status code
0on success and print a line similar toUploaded to Codecovfollowed by a URL to the upload result.
Expected checks
- The CI job should record an exit code of
0from the uploader step; any non‑zero exit indicates a problem. - Codecov processes the upload and updates the repository’s coverage dashboard. The latest commit will display a refreshed coverage percentage.
- On any pull request associated with the commit, Codecov adds a status check (e.g.,
codecov/patch) that shows the coverage delta and passes when the change satisfies the thresholds you configured in Codecov’s project settings. - In the CI logs you should see a message confirming the upload and a URL such as
https://codecov.io/gh/owner/repo/commit/sha.
Recovery options
- If the uploader exits with a non‑zero code, first re‑run the step with the
-vflag to obtain verbose output. This will reveal issues such as missing dependencies, token problems, or file‑format errors. - Verify that the environment variable
$CODECOV_TOKENis set and not masked in the logs. If you suspect the token was leaked, rotate it immediately in the Codecov UI and update the CI secret. - Confirm that the coverage file exists and is not empty (
ls -lh coverage.xmlorstat coverage.info). An empty or malformed file will be rejected with a clear error message. - Ensure the runner provides
curlandjq(or use the Docker image, which bundles them). On minimal images, install them via the package manager (apk add curl jqfor Alpine). - As a last resort, you can upload the report manually via the Codecov website: navigate to
https://codecov.io/gh/owner/repo/upload, drag‑and‑drop the coverage file, and provide the token when prompted. Use the request ID shown after upload to contact Codecov support if needed.
Limitations and practical verification
- The uploader only accepts the formats listed above; using an unsupported format (e.g., a custom JSON summary) will cause an immediate rejection.
- Token leakage is a security risk; never hard‑code the token in repository files or expose it in build logs. Use secret‑masking features of your CI system.
- Version mismatches between the uploader and the runner are rare with the bash script, but if you rely on a very old version of
bashlackingprocess substitution(<( … )>), the download step will fail. In such cases, download the script to a file first (curl -s https://codecov.io/bash -o codecov_uploader.sh) and execute it withbash codecov_uploader.sh. - To verify success without relying solely on CI logs, open the Codecov dashboard for the repository after the CI run completes. The
Latesttab should show the new coverage percentage and a green checkmark if the upload succeeded. Additionally, open the associated pull request and look for thecodecov/patchstatus check; it will display a message likeCoverage increased (+0.3%) compared to basewhen thresholds are met.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.