Coverage docs
The words
- Repo: a code repository, such as
acme/widgets. It has one owner (the person who added it) and a default branch. - Upload: one coverage report for one commit, one branch and one flag.
- Flag: the part of the repo that a report covers. In a monorepo, the project folder (
apps/coro,packages/i18n). - Carry forward: a flag with no upload for a commit keeps its latest earlier upload on that branch. The total of a repo on a branch is the sum of the latest upload of each flag.
A percent is covered divided by total, and 100 when the total is 0. It is red below 80, yellow below 95 and green from 95.
POST /api/v1/upload
Send the header Authorization: Bearer <token> (the token names the repo) and Content-Type: application/json. The body may be gzip, with Content-Encoding: gzip.
gzip -c report.json | curl --fail-with-body \
-X POST https://coverage.utilarium.app/api/v1/upload \
-H "Authorization: Bearer $COVERAGE_TOKEN" \
-H "Content-Type: application/json" \
-H "Content-Encoding: gzip" \
--data-binary @-import { gzipSync } from "node:zlib";
const report = {
commit: process.env.GITHUB_SHA,
branch: process.env.GITHUB_REF_NAME,
flag: "apps/coro",
message: "Fix the login page",
files: [
{
path: "client/lib/x.ts",
lines: [12, 14], // [covered, total]
statements: [13, 15],
functions: [3, 3],
branches: [4, 6],
missed: "3-5,9", // the uncovered lines, as sorted ranges
},
],
};
const response = await fetch("https://coverage.utilarium.app/api/v1/upload", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.COVERAGE_TOKEN}`,
"Content-Type": "application/json",
"Content-Encoding": "gzip",
},
body: gzipSync(JSON.stringify(report)),
});
console.log(response.status, await response.json());- name: Upload coverage
run: node upload-coverage.mjs
env:
COVERAGE_TOKEN: ${{ secrets.COVERAGE_TOKEN }}The body
{
"commit": "0123456789abcdef0123456789abcdef01234567",
"branch": "main",
"flag": "apps/coro",
"message": "Fix the login page",
"files": [
{
"path": "client/lib/x.ts",
"lines": [12, 14],
"statements": [13, 15],
"functions": [3, 3],
"branches": [4, 6],
"missed": "3-5,9"
}
]
}commit: 40 lower case hex digits.branch: up to 200 characters, no spaces.flag: up to 200 characters ofA-Z a-z 0-9 . _ / -, with no empty,.or..part.message: optional, the commit subject, up to 200 characters.files: the list of files.pathis relative to the flag folder, with/, no.., up to 500 characters.lines,statements,functionsandbranchesare[covered, total], two integers with 0 ≤ covered ≤ total.missedis the uncovered line numbers as sorted ranges ("3-5,9", or""for none), up to 20000 characters.
Any other field is refused, so a typo does not go unnoticed. Two files cannot have the same path.
Limits
- 8 MB for the body, counted as sent and again after gunzip.
- 5000 files in one upload.
- 20 repos for each person and 20 upload tokens for each repo.
- 10 repos or tokens made in a minute.
Answers
{
"ok": true,
"upload": "42",
"url": "https://coverage.utilarium.app/r/kamadorueda/apps/commit/0123456789abcdef0123456789abcdef01234567"
}201: stored.urlis the commit page (it opens in the dashboard after you sign in).400{"ok":false,"error":"..."}: the body is not valid; the error says why.401: no token, or a wrong or revoked one.413: the body is over 8 MB.
One upload for each repo, commit and flag: a second upload replaces the first (its files too), so you can send again after a retry.
Badge
A badge shows the line coverage of the default branch. It is off until you turn on "Public badge" in the repo's settings; until then the address answers 404. Add ?flag=apps/coro for one flag.
