bb-insights

module
v0.0.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 20, 2026 License: Apache-2.0

README

bb-insights

CI License

bb-insights publishes software quality and security reports to Bitbucket Cloud Code Insights.

Bitbucket Cloud has an excellent pull request experience, but unlike competing platforms it lacks native integrations for many common report formats such as Go coverage or Trivy SARIF. bb-insights bridges that gap: it consumes reports already produced by other tools and publishes them to Bitbucket in a form the Code Insights UI understands.

bb-insights does not run any analysis itself. Its job starts after gotestsum, go test -coverprofile or trivy have already produced their reports.

Supported reports

Report Source Produced by
Go unit tests test-results/unit-tests.xml (JUnit XML) gotestsum --junitfile ...
Go coverage coverage.out go test -coverprofile=coverage.out
JaCoCo coverage jacoco.xml JaCoCo Maven/Gradle plugin
Trivy security scan testdata/sarif/trivy.sarif trivy image --format sarif ...
Generic SARIF report any SARIF 2.1.0 file e.g. golangci-lint, Semgrep, CodeQL
Aikido image scan testdata/aikido/aikido-sample.json Aikido local image scanner (JSON)

Installation

Download a prebuilt binary from the releases page, or build from source:

go install github.com/alapierre/bb-insights/cmd/bb-insights@latest

A Docker image is also published for use as a pipeline step:

docker run --rm -v "$PWD:/data" -w /data \
  lapierre/bb-insights:latest \
  publish tests --workspace myteam --repo myrepo --commit "$BITBUCKET_COMMIT" \
    --junit test-results/unit-tests.xml

Usage

bb-insights publish tests \
  --workspace myteam --repo myrepo --commit "$BITBUCKET_COMMIT" \
  --junit test-results/unit-tests.xml

bb-insights publish coverage \
  --workspace myteam --repo myrepo --commit "$BITBUCKET_COMMIT" \
  --input coverage.out

bb-insights publish trivy \
  --workspace myteam --repo myrepo --commit "$BITBUCKET_COMMIT" \
  --input trivy.sarif

bb-insights publish sarif \
  --workspace myteam --repo myrepo --commit "$BITBUCKET_COMMIT" \
  --input golangci-lint.sarif --title golangci-lint

bb-insights publish jacoco \
  --workspace myteam --repo myrepo --commit "$BITBUCKET_COMMIT" \
  --input jacoco.xml

bb-insights publish aikido \
  --workspace myteam --repo myrepo --commit "$BITBUCKET_COMMIT" \
  --input aikido-image-scan-results.json

--workspace, --repo and --commit also fall back to the BITBUCKET_WORKSPACE, BITBUCKET_REPO_SLUG and BITBUCKET_COMMIT environment variables that Bitbucket Pipelines sets automatically, so in a pipeline step you typically only need to pass the report path.

publish trivy and publish sarif both parse the same SARIF 2.1.0 format; trivy is a preset kept for backward compatibility (fixed title "Trivy Security Report", SECURITY report type, VULNERABILITY annotations), while sarif is generic and lets --title (env BB_INSIGHTS_TITLE) name whichever tool produced the report, publishing it as a BUG report with CODE_SMELL annotations instead. If you publish more than one SARIF-based report on the same commit (e.g. trivy together with sarif, or sarif for two different tools), give each a distinct --report-id, since sarif invocations share one default report ID otherwise and would overwrite each other:

bb-insights publish sarif \
  --workspace myteam --repo myrepo --commit "$BITBUCKET_COMMIT" \
  --input golangci-lint.sarif --title golangci-lint \
  --report-id bb-insights-golangci-lint

bb-insights publish sarif \
  --workspace myteam --repo myrepo --commit "$BITBUCKET_COMMIT" \
  --input semgrep.sarif --title semgrep \
  --report-id bb-insights-semgrep

publish aikido parses the JSON report produced by Aikido's local image scanner (a different format from Aikido's own SARIF export, which goes through publish sarif instead), publishing one annotation per finding with a SECURITY/VULNERABILITY report just like trivy.

trivy, sarif and aikido all mark the report as FAILED only if a finding at or above --fail-severity (default high; also accepts critical, medium or low, env BB_INSIGHTS_FAIL_SEVERITY) is present. Lower-severity findings are still published as metrics and annotations, they just don't fail the report on their own.

Quality gate (--exit-code)

By default bb-insights always exits with code 0 after successfully publishing, regardless of what the report contains. Use --exit-code (env BB_INSIGHTS_EXIT_CODE) together with --fail-severity to turn the publish step into a quality gate that fails the pipeline when findings are too severe:

bb-insights publish trivy \
  --input trivy.sarif \
  --fail-severity high \
  --exit-code 1

When --exit-code is non-zero and at least one finding at or above the --fail-severity threshold is found, bb-insights:

  1. publishes the report to Bitbucket (with result FAILED) as usual, and
  2. prints a message to stderr explaining the gate failure, then exits with the specified code.

This makes it straightforward to fail a Bitbucket Pipeline step — or any other CI system — without losing the report in Bitbucket Code Insights.

quality gate failed: 3 finding(s) at or above HIGH severity found

Using a code other than 1 (e.g. 2) lets you distinguish quality gate failures from real tool errors (which always exit 1) in calling scripts.

The default 0 preserves backwards compatibility: existing pipelines that don't set --exit-code keep working unchanged.

Authentication

Exactly one of the following must be configured:

  • --token (env BB_INSIGHTS_TOKEN): a Bitbucket repository, project or workspace access token, sent as a Bearer token. This is the recommended method for Bitbucket Pipelines.
  • --username + --app-password (env BB_INSIGHTS_USERNAME / BB_INSIGHTS_APP_PASSWORD): HTTP Basic Auth, for compatibility with setups that still rely on app passwords.
Other flags
Flag Env Description
--base-url BB_INSIGHTS_BASE_URL Bitbucket API base URL (default https://api.bitbucket.org/2.0).
--timeout BB_INSIGHTS_TIMEOUT HTTP request timeout (default 30s).
--link BB_INSIGHTS_LINK URL linking back to the CI build, shown on the report.
--report-id BB_INSIGHTS_REPORT_ID Override the default deterministic report ID.
--dry-run BB_INSIGHTS_DRY_RUN Print the JSON payload instead of calling the Bitbucket API.
--exit-code BB_INSIGHTS_EXIT_CODE (trivy/sarif/aikido only) Exit with this code when findings exceed --fail-severity. 0 (default) always exits cleanly.

Each subcommand's report path flag also has an env fallback: --junit reads BB_INSIGHTS_JUNIT, and --input (on coverage, trivy, sarif, jacoco and aikido) reads BB_INSIGHTS_INPUT. sarif's --title reads BB_INSIGHTS_TITLE; trivy, sarif and aikido's --fail-severity reads BB_INSIGHTS_FAIL_SEVERITY and --exit-code reads BB_INSIGHTS_EXIT_CODE.

Run bb-insights publish <command> --help for the full list.

Bitbucket Pipelines example

image: golang:1.26

pipelines:
  default:
    - step:
        name: Test, scan and report
        script:
          # BITBUCKET_WORKSPACE, BITBUCKET_REPO_SLUG and BITBUCKET_COMMIT are
          # injected by Bitbucket Pipelines automatically; bb-insights reads
          # them as fallbacks, so --workspace/--repo/--commit can be omitted
          # below. BB_INSIGHTS_TOKEN is NOT injected automatically: it must
          # be configured once as a secured repository variable (Repository
          # settings > Repository variables), see below.
          - go install gotest.tools/gotestsum@latest
          - gotestsum --format pkgname --junitfile test-results/unit-tests.xml -- -coverprofile=coverage.out ./...
          - curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
          - trivy fs --format sarif --output trivy.sarif .
          - curl -sfL https://github.com/alapierre/bb-insights/releases/latest/download/bb-insights_linux_amd64 -o /usr/local/bin/bb-insights
          - chmod +x /usr/local/bin/bb-insights
          - bb-insights publish tests --junit test-results/unit-tests.xml
          - bb-insights publish coverage --input coverage.out
          - bb-insights publish trivy --input trivy.sarif --exit-code 1

Set BB_INSIGHTS_TOKEN as a secured repository variable pointing at a repository access token with the repository:write scope (this is the scope Bitbucket Cloud requires for the Code Insights reports API; the pipeline-oriented pipeline:write scope, which explicitly covers uploading code insights, also works).

Instead of installing gotestsum, trivy and bb-insights by hand as above, you can use golang-docker-builder as the step's image: - it's a ready-to-use Go build image for Bitbucket Pipelines that already bundles bb-insights alongside gotestsum, golangci-lint, govulncheck and other common CI/CD tooling.

Use as a Bitbucket Pipe

The same Docker image published above can also be referenced directly as a pipe (pipe: docker://...), instead of installing the binary in the script. Unlike a step-level image: (which overrides the container's entrypoint so your script: commands can run inside it), a pipe: preserves the image's own ENTRYPOINT and only lets you configure it through environment variables - there's no way to pass extra CLI flags. When bb-insights is started with no arguments at all, it looks at BB_INSIGHTS_REPORT_TYPE to decide which subcommand to run, then resolves every flag (--junit, --input, --token, ...) from its usual env var, exactly as it would from the command line:

image: golang:1.26

pipelines:
  default:
    - step:
        name: Test, scan and report
        script:
          - go install gotest.tools/gotestsum@latest
          - gotestsum --format pkgname --junitfile test-results/unit-tests.xml -- -coverprofile=coverage.out ./...
          - curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
          - trivy fs --format sarif --output trivy.sarif .

          - pipe: docker://lapierre/bb-insights:latest
            variables:
              BB_INSIGHTS_REPORT_TYPE: tests
              BB_INSIGHTS_JUNIT: test-results/unit-tests.xml
              BB_INSIGHTS_TOKEN: $BB_INSIGHTS_TOKEN

          - pipe: docker://lapierre/bb-insights:latest
            variables:
              BB_INSIGHTS_REPORT_TYPE: coverage
              BB_INSIGHTS_INPUT: coverage.out
              BB_INSIGHTS_TOKEN: $BB_INSIGHTS_TOKEN

          - pipe: docker://lapierre/bb-insights:latest
            variables:
              BB_INSIGHTS_REPORT_TYPE: trivy
              BB_INSIGHTS_INPUT: trivy.sarif
              BB_INSIGHTS_EXIT_CODE: 1
              BB_INSIGHTS_TOKEN: $BB_INSIGHTS_TOKEN

          - pipe: docker://lapierre/bb-insights:latest
            variables:
              BB_INSIGHTS_REPORT_TYPE: sarif
              BB_INSIGHTS_INPUT: golangci-lint.sarif
              BB_INSIGHTS_TITLE: golangci-lint
              BB_INSIGHTS_REPORT_ID: bb-insights-golangci-lint
              BB_INSIGHTS_TOKEN: $BB_INSIGHTS_TOKEN

BITBUCKET_WORKSPACE, BITBUCKET_REPO_SLUG and BITBUCKET_COMMIT don't need to be listed under variables: - Bitbucket injects its own default variables into pipe containers automatically, same as any other step. BB_INSIGHTS_TOKEN does need to be listed explicitly (as shown above): only variables declared under a pipe's variables: are passed through from repository/workspace variables into the container.

BB_INSIGHTS_REPORT_TYPE: jacoco works the same way, with BB_INSIGHTS_INPUT pointing at the jacoco.xml report. Likewise, BB_INSIGHTS_REPORT_TYPE: aikido with BB_INSIGHTS_INPUT pointing at the Aikido image scan JSON report.

Verifying a release

Every release publishes, alongside the binary and Docker image:

  • a SBOM (Software Bill of Materials, SPDX format) for the binary, generated by Syft, and one embedded in the Docker image manifest via docker buildx's native SBOM support;
  • a build provenance attestation for both the binary and the Docker image, proving they were built by this repository's GitHub Actions workflow from a specific commit, not assembled or modified elsewhere.

Verify a downloaded binary with the GitHub CLI:

gh attestation verify bb-insights_linux_amd64 --owner alapierre

Verify the Docker image:

gh attestation verify oci://index.docker.io/lapierre/bb-insights:latest --owner alapierre

Design

The codebase separates three concerns, as required by the project's architecture (see CLAUDE.md):

  • Parsers (internal/parser/{junit,coverage,jacoco,sarif,aikido}) read an external report format and convert it into the internal model. Adding a new report format means adding a new parser package; existing parsers are never touched.
  • Internal model (internal/model) is the format-agnostic contract between parsers and the publisher: Report, Metric, Annotation, Severity, Location.
  • Publisher (internal/bitbucket, internal/publish) knows how to talk to the Bitbucket Cloud Code Insights REST API and nothing about coverage.out, JUnit XML or SARIF.

Report and annotation IDs are deterministic (a fixed ID per report kind, and a hash of stable identifying fields per annotation), so re-running a pipeline step on the same commit updates the existing report instead of duplicating it.

  • golang-docker-builder - a ready-to-use Docker build image for Go projects on Bitbucket Pipelines, bundling bb-insights together with other CI/CD tooling (gotestsum, golangci-lint, govulncheck, goreleaser, ...) so you don't have to install them step by step.

Development

go build ./...
go vet ./...
go test ./...

No integration tests require a real Bitbucket Cloud account; HTTP interactions are tested against httptest.Server.

Contributing

See CONTRIBUTING.md for how to propose changes, and CODE_OF_CONDUCT.md for community expectations.

AI assistance

This project is developed with AI assistance (code review and parts of the implementation) - see AI_USAGE.md for what that means and what stays human-driven.

Security

See SECURITY.md for how to report a vulnerability.

License

Apache License 2.0 - see LICENCE for the full text.

Directories

Path Synopsis
cmd
bb-insights command
Command bb-insights publishes Go test, Go coverage and Trivy security reports to Bitbucket Cloud Code Insights.
Command bb-insights publishes Go test, Go coverage and Trivy security reports to Bitbucket Cloud Code Insights.
internal
bitbucket
Package bitbucket implements a client for the Bitbucket Cloud Code Insights REST API.
Package bitbucket implements a client for the Bitbucket Cloud Code Insights REST API.
cli
Package cli wires the kong command-line interface: it resolves configuration, builds a bitbucket.Client and a publish.Publisher, and dispatches to each "publish" subcommand.
Package cli wires the kong command-line interface: it resolves configuration, builds a bitbucket.Client and a publish.Publisher, and dispatches to each "publish" subcommand.
model
Package model defines the internal representation shared by all report parsers and the Bitbucket Code Insights publisher.
Package model defines the internal representation shared by all report parsers and the Bitbucket Code Insights publisher.
parser/aikido
Package aikido parses the JSON report produced by Aikido's local image scanner (not to be confused with Aikido's SARIF export, which is already handled by the generic sarif parser) into the common internal report model.
Package aikido parses the JSON report produced by Aikido's local image scanner (not to be confused with Aikido's SARIF export, which is already handled by the generic sarif parser) into the common internal report model.
parser/coverage
Package coverage parses a Go coverage profile (coverage.out, produced by "go test -coverprofile=coverage.out") into the common internal report model.
Package coverage parses a Go coverage profile (coverage.out, produced by "go test -coverprofile=coverage.out") into the common internal report model.
parser/jacoco
Package jacoco parses a JaCoCo XML coverage report (jacoco.xml, produced by the JaCoCo Maven/Gradle plugin) into the common internal report model.
Package jacoco parses a JaCoCo XML coverage report (jacoco.xml, produced by the JaCoCo Maven/Gradle plugin) into the common internal report model.
parser/junit
Package junit parses the JUnit XML report produced by gotestsum (--junitfile) into the common internal report model.
Package junit parses the JUnit XML report produced by gotestsum (--junitfile) into the common internal report model.
parser/sarif
Package sarif parses a SARIF 2.1.0 report into the common internal report model.
Package sarif parses a SARIF 2.1.0 report into the common internal report model.
publish
Package publish maps the internal report model onto Bitbucket Code Insights payloads and publishes them through a bitbucket.Client.
Package publish maps the internal report model onto Bitbucket Code Insights payloads and publishes them through a bitbucket.Client.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL