Share an HTML report from Travis CI

Every other CI provider gives you something to complain about. Travis gives you nothing to complain about, because there is nothing there: no artifacts tab, no report viewer, no retention window to argue with. Your job writes coverage/index.html, the job finishes, the container is destroyed, and the report never existed as far as anyone outside that log is concerned.

The two workarounds are both bad:

  • cat it into the log. Now the report is 4,000 lines of markup in a scrolling text pane. Nobody reads it. The failing test gets screenshotted into Slack, which is where this always ends.
  • Push it to your own S3 bucket. Now you own a bucket policy, a lifecycle rule, a public-access decision and a CORS config, in order to show someone a test report. The bucket outlives whoever set it up.

One call in after_script

Mint a scoped token with reports:write and nothing else, add it as a repository environment variable with the display value off, create the report once, and PATCH that id from every build:

language: python
python: "3.12"

install:
  - pip install -r requirements.txt

script:
  - pytest --cov --cov-report=html

after_script:
  - |
    curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$COMMA_REPORT_ID" \
      -H "Authorization: Bearer $COMMA_API_TOKEN" \
      -H "Content-Type: application/json" \
      -d "$(jq -n --rawfile html htmlcov/index.html \
            --arg title "Coverage — ${TRAVIS_BRANCH} @ ${TRAVIS_COMMIT:0:7}" \
            '{title: $title, html: $html}')"
    echo "Report → https://commareports.com/p/$COMMA_REPORT_ID"

after_script, not after_success — that is the whole trick. after_success skips exactly the builds whose report someone wanted to read. after_script runs either way and its own exit status does not change the build result, so a transient publish failure cannot turn a green build red.

For a pull-request build, note that Travis does not expose secure environment variables to builds from forks. That is a security property worth keeping: the fork build simply skips the publish, and the branch build after the merge publishes the real thing.

What you get instead of a bucket

  • A permanent URL. Each build appends a revision at the same address and any two revisions can be diffed — no lifecycle rule, no retention clock.
  • It renders. The HTML is stored verbatim and served inside a sandboxed iframe with scripts enabled, so a coverage tree or a chart still works.
  • Readers who are not in your Travis org. Visibility is private, team, domain-gated, or link, decided per report.
  • Comments anchored to the content. A reviewer highlights the uncovered branch and pins a thread to it — see commenting on HTML.
  • No infrastructure. No bucket, no policy, no CORS, nothing to inherit.

Limits

  • HTML body: 5 MB. Larger files go in as assets at 25 MB per file, 250 MB per report.
  • A report that loads sibling data files at view time can't, from the sandbox — publish a static digest with the archive attached, as in sharing an Allure report.
  • Rate limit: 60 requests/minute per token.

Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision history.

Create your first report →

Related