Share a Cucumber HTML report
Cucumber reports exist to be read by people who don't run the suite. That is the whole premise of BDD: the scenarios are written in the language of the business so the business can check them. Then CI takes the report, zips it, and puts it behind a login the business doesn't have.
The mismatch is the problem, not the format. @cucumber/html-formatter
already produces exactly the right artifact — one self-contained file,
the run's messages embedded, a bundled React app rendering the feature
tree. It needs a URL, not a build system.
Publish it with one curl
npx cucumber-js --format html:cucumber-report.html
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 cucumber-report.html \
--arg title "Acceptance — $(git rev-parse --short HEAD)" \
'{title: $title, html: $html}')"
PATCH on a saved report id instead of POST means every run appends a
revision at the same URL. The link in the team channel is written
once and never goes stale. Use a scoped token —
reports:write is all this needs.
For cucumber-jvm, the same file comes out of
@CucumberOptions(plugin = "html:target/cucumber-report.html"); for
Behave or SpecFlow, point the curl at whatever single HTML file the
reporter wrote. Nothing here is JS-specific.
What changes when the report has a URL
- A failing scenario gets a thread on it. A reviewer highlights the step that broke and pins a comment there — "this is the pricing change from Tuesday, expected" — and the thread stays put across the next dozen runs. See commenting on HTML.
- Product owners can actually open it. No CI seat, no repo access, no zip. The sharing model is per report: private, team-visible, domain-gated, or named reviewers.
- Run-over-run diffs. "Which scenarios flipped since the last green build?" is a revision diff rather than two tabs and a memory test.
- Announcements. A webhook on
revision.createdposts each run into Slack.
Limits worth knowing
- HTML body: 5 MB. Base64 screenshots inlined by the formatter add up quickly. Past the cap, upload them as assets (25 MB per file, 250 MB per report) instead of inlining.
- Scripts run, sandboxed. The report renders in an iframe with
sandbox="allow-scripts"and noallow-same-origin, so the interactive feature tree works. Reports that fetch sibling files at view time need those files uploaded as assets — see Playwright for that shape. - Rate limits are per token, 60/minute. One publish per build is not close.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history. Publish one suite and send the link to someone who has never logged into your CI.
Related
- Publish from CI — the general pipeline pattern
- Playwright · Cypress · pytest · Allure
- Robot Framework — same problem, different runner