Reporting Results

Everything in UniTrack starts with an ingest: a CI job posts its JUnit and JaCoCo reports to the server after a build. This page describes what the endpoint accepts; the CLI & CI Integration and REST API pages cover the wrapper script and the raw HTTP contract.

1. The endpoint

POST /api/v1/ingest
Content-Type: multipart/form-data

2. Fields

Field Required Description

project

yes

Project name; created on first sight.

junit

yes

One or more Surefire/JUnit XML files (repeatable).

jacoco

no

One or more coverage reports (repeatable): JaCoCo XML, Cobertura XML, LCOV, or OpenCover XML — auto-detected.

perf

no

A performance/load-test result — JMeter JTL or k6 JSON summary (auto-detected): latency percentiles, throughput, error rate.

branch

no

Git branch the build ran on.

commit

no

Commit SHA — used for flaky detection and GitHub status.

buildUrl

no

Link back to the CI build.

repoUrl

no

Repository URL (enables GitHub status publishing).

ciProvider

no

Free-text CI identifier, e.g. github-actions.

flag

no

Coverage/component flag — see Coverage Flags.

runKey

no

Stable key to merge sharded runs — see Report Merging.

Only project and at least one junit or perf file are required; everything else is optional metadata that unlocks additional features. A perf upload (JMeter JTL) is stored as a performance run alongside the test/coverage history; the parser computes p50/p90/p95/p99 latency, throughput and error rate (overall and per request label). The response carries a perfRunId. Upload it from CI with scripts/unitrack-upload.sh --perf results.jtl.

3. What happens on ingest

  1. The JUnit XML is parsed into suites and cases, capturing status and any system-out/system-err output and attachments.

  2. The coverage report’s format is auto-detected from its content — JaCoCo XML, Cobertura XML, LCOV (.info), or OpenCover XML — and its counters are aggregated into a line-coverage percentage and stored per file. The jacoco upload field accepts any of these, so non-JVM projects can report coverage too:

    Ecosystem Producer → format

    JVM

    JaCoCo (jacoco.xml)

    JavaScript

    Istanbul/nyc, Jest (lcov.info)

    Python

    coverage.py (coverage xml → Cobertura)

    .NET

    Coverlet default (Cobertura) or --format opencover; OpenCover (<CoverageSession>)

  3. A TestRun is created, linked to its Project, with pass/fail totals.

  4. Flaky detection compares this run to other runs of the same commit.

  5. Triage rules categorise any failures, and similar failures are clustered.

  6. The quality gate evaluates the run; if a repoUrl and GitHub token are configured, a commit status is posted to the pull request.

4. Response

201 Created with a JSON body summarising the stored run (id, totals, coverage). A malformed upload returns 4xx with an error message.

5. Size limits

Multipart uploads default to 25 MB per file and 100 MB per request. Raise these via spring.servlet.multipart.max-file-size / max-request-size if you upload large merged reports.