# Share an HTML Report From Google Cloud Build

Canonical: https://commareports.com/ci/google-cloud-build-html-report
Published: 2026-09-02

> Cloud Build has no report viewer — your HTML lands in a GCS bucket that needs IAM, a signed URL or public access before anyone can read it. Publish it from cloudbuild.yaml in one step.

# Share an HTML report from Google Cloud Build

Cloud Build's UI is a log stream. That is an honest design — it is a build
service, not a report host — and it means your `coverage/index.html` has
exactly one destination: a GCS bucket, as an object, unrendered.

From there every path costs something:

- **Public bucket.** Now the report that lists your failing tests, internal
  hostnames and dependency versions is world-readable, permanently, for every
  build you ever ran.
- **Signed URLs.** Private, and they expire. The reviewer opens it on Thursday
  and gets `ExpiredToken`.
- **IAM on the bucket.** Correct, and it means the customer, the auditor and
  the PM all need Google Cloud identities and a role binding before they can
  read a test report.

None of the three gives anyone a way to respond to what they read.

## One step in `cloudbuild.yaml`

Put a [scoped token](/docs/api-tokens) (`reports:write` only) in Secret
Manager, create the report once, and `PATCH` that id from every build:

```yaml
availableSecrets:
  secretManager:
    - versionName: projects/$PROJECT_ID/secrets/comma-api-token/versions/latest
      env: COMMA_API_TOKEN

substitutions:
  _COMMA_REPORT_ID: rep_xxxxxxxx

steps:
  - name: python:3.12
    id: test
    allowFailure: true
    entrypoint: bash
    args:
      - -c
      - |
        pip install -r requirements.txt
        pytest --cov --cov-report=html

  - name: gcr.io/cloud-builders/curl
    id: publish
    secretEnv: ["COMMA_API_TOKEN"]
    entrypoint: bash
    args:
      - -c
      - |
        apt-get -qq update && apt-get -qq install -y jq
        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 htmlcov/index.html \
                --arg title "Coverage — $SHORT_SHA" \
                '{title: $title, html: $html}')"
        echo "Report → https://commareports.com/p/${_COMMA_REPORT_ID}"
```

Three details are load-bearing:

- **`allowFailure: true` on the test step.** Without it, Cloud Build halts at
  the failing step and the publish never runs — so the only builds that produce
  a report are the ones nobody needed one for. If you want the build to end red
  anyway, check `$?` in a final step and exit non-zero there.
- **`secretEnv` with `$$COMMA_API_TOKEN`.** The doubled `$` escapes the
  substitution so the shell, not Cloud Build, expands it — the token stays out
  of the build log.
- **The steps share `/workspace`**, which is why the publish step can read
  `htmlcov/index.html` that the test step wrote.

## What the published copy adds

- **A URL that renders, with no bucket configuration.** The HTML is stored
  verbatim and served inside a sandboxed iframe with scripts enabled, so an
  interactive report stays interactive.
- **One address across every build.** Revisions accumulate at the same URL and
  any two can be diffed.
- **Readers without a Google Cloud identity.** Visibility is
  [private, team, domain-gated, or link](/docs/sharing), decided per report —
  not by an IAM binding that outlives the reason for it.
- **Comments anchored to the content.** A reviewer highlights the line that
  regressed and pins a thread there — see
  [commenting on HTML](/comment-on-html).

## Limits

- **HTML body: 5 MB.** Larger files go in as [assets](/docs/api) at 25 MB per
  file, 250 MB per report.
- **A report that fetches sibling data files at view time** can't, from the
  sandbox — publish a static digest with the archive attached, as in
  [sharing an Allure report](/share-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 →](https://commareports.com/)**

### Related

- [Publish from CI](/docs/ci) — the general pipeline pattern
- [AWS CodeBuild HTML reports](/ci/aws-codebuild-html-report) — the same shape,
  the other cloud
- [Share a pytest report](/share-pytest-report) ·
  [Share a coverage report](/share-coverage-report)
