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.createdposts 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.
Related
- Publish from CI — the general pipeline pattern
- Jenkins HTML reports — the same CSP fight, a different server
- Share a JaCoCo report · Share a Gradle test report