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 (just reports:write) in your CI secret store, then:

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, and bookmarks never go stale:

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

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.

Notes for pipelines

  • HTML limit is 5 MB. Bigger payloads (screenshots, JS bundles) go in as assets — 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 on revision.created and the new revision announces itself in Slack or Discord.
  • Access control: CI-published reports follow the same sharing model as everything else — keep them team-visible rather than public-by-default.