# Publish from CI · Comma Docs

Canonical: https://commareports.com/docs/ci

> Publish HTML reports to Comma from GitHub Actions, GitLab CI, or any pipeline with one curl. Stable URLs, revision history, and webhook notifications on every push.

# Publish from CI

Coverage reports, eval results, benchmark dashboards, release notes — if
your pipeline produces HTML, one `curl` puts it at a stable URL your team
can open, comment on, and diff against the previous run. No Pages setup, no
artifact-zip downloads.

## The pattern

Store a [scoped token](/docs/api-tokens) (just `reports:write`) in your CI
secret store, then:

```bash
curl -fsS -X POST https://commareports.com/api/v1/reports \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html coverage/index.html \
        '{title: "Coverage — \(env.GITHUB_SHA[0:7])", html: $html}')"
```

To keep **one URL per report** instead of one per run, create the report
once, save its id, and `PATCH` it on every run — each push appends a
revision, reviewers can [diff any two](/docs/api), and bookmarks never go
stale:

```bash
curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html coverage/index.html '{html: $html}')"
```

## GitHub Actions

```yaml
name: coverage-report
on:
  push:
    branches: [main]

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run coverage
      - name: Publish coverage to Comma
        env:
          COMMA_API_TOKEN: ${{ secrets.COMMA_API_TOKEN }}
          REPORT_ID: ${{ vars.COMMA_COVERAGE_REPORT_ID }}
        run: |
          curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
            -H "Authorization: Bearer $COMMA_API_TOKEN" \
            -H "Content-Type: application/json" \
            -d "$(jq -n --rawfile html coverage/index.html '{html: $html}')"
```

The same two lines work in GitLab CI, CircleCI, Buildkite, or a cron on a
box — it's plain HTTPS. For test suites specifically, see
[sharing a Playwright report from CI →](/share-playwright-report).

## Notes for pipelines

- **HTML limit is 5 MB.** Bigger payloads (screenshots, JS bundles) go in as
  [assets](/docs/api) — 25 MB per file.
- **Rate limits** are per token (60/min by default). One report per build is
  nowhere near it.
- **Notify on push:** add a [webhook notification](/docs/api) on
  `revision.created` and the new revision announces itself in Slack or
  Discord.
- **Access control:** CI-published reports follow the same
  [sharing model](/docs/sharing) as everything else — keep them
  team-visible rather than public-by-default.
