Share a TeamCity HTML report

TeamCity is more generous than most CI servers here: point a build report tab at an artifact path and the report appears as a tab on the build page, inside TeamCity, no download required.

Then you hit the three walls around it.

  • The sandbox. Artifacts are served under a restrictive Content-Security-Policy — a build that could script the page it renders in would be a build that could script TeamCity. The policy is right and the consequence is that a report whose value is interactive (a coverage tree you expand, a chart, a filterable test list) degrades to a static shell or a blank tab.
  • The login. Viewing a build requires a TeamCity account with permission on the project. That is fine for engineers and a non-starter for the PM, the security reviewer, the customer, or the auditor — which is precisely how reports end up as screenshots in chat.
  • Cleanup rules. Artifacts are deleted on the schedule you configured, and the schedule is always shorter than the question someone eventually asks.

Publish it from a build step

Store a scoped token (reports:write only) as a typed password parameter so TeamCity masks it in the build log, create the report once, and PATCH it every run:

# Command Line build step — "Publish report"
# Execute step: Even if some previous steps failed
curl -fsS -X PATCH "https://commareports.com/api/v1/reports/%comma.report.id%" \
  -H "Authorization: Bearer %env.COMMA_API_TOKEN%" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html build/reports/tests/test/index.html \
        --arg title "Tests — %teamcity.build.branch% @ %build.vcs.number%" \
        '{title: $title, html: $html}')"

echo "##teamcity[buildStatus text='{build.status.text} · report: https://commareports.com/p/%comma.report.id%']"

Two details do the work:

  • Execution policy: "Even if some previous steps failed." The default only publishes green builds, which are the builds nobody needed the report for.
  • The service message puts the link on the build page, so the path from a red build to something readable is one click, for someone who may not have a TeamCity seat at all.

The report tab stays. It costs nothing and it is convenient for whoever is already in TeamCity; the published copy is for everyone else.

What the published copy adds

  • Scripts actually run. Report HTML is stored verbatim and rendered inside a sandboxed iframe with scripts enabled and CDN scripts and styles limited to jsdelivr, unpkg, cdnjs and esm.sh — the interactive report stays interactive.
  • One URL, no cleanup rule. Each build appends a revision at the same address, revisions are kept, and any two can be diffed.
  • Readers without a TeamCity account. Visibility is private, team, domain-gated, or link, set per report.
  • Comments anchored to the content. A reviewer highlights the failing assertion and pins a thread to it; the thread outlives the build — see commenting on HTML.
  • Announcements. A webhook on revision.created posts each new revision into Slack or Teams.

Limits

  • HTML body: 5 MB. Screenshots, videos and archives go in as assets at 25 MB per file, 250 MB per report.
  • A report that fetches sibling data files at view time can't do so 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