skip to content

How can you enrich a Build Scan with custom tags, values, and links, and why is that useful?

level: seniorimportance: should knowfreq 28%

answer

  1. tag() / value() / link()
  2. git SHA, branch, CI build number
  3. background { } to stay off critical path
  4. searchable dimensions on Develocity
  5. scans as observability not one-offs

basics

~20 s

Through the buildScan API you can attach tag(...), value(key, val), and link(name, url) to each scan — e.g. tag CI vs local, record the git commit, or link to the CI build. This makes scans searchable and self-documenting.

solid answer

~50 s

The Develocity `buildScan` extension exposes an API to annotate each scan with metadata: `tag("CI")` / `tag("local")` for coarse filtering, `value("Git Commit", sha)` for searchable key/value pairs, and `link("CI Build", url)` to jump from a scan back to the pipeline that produced it. You compute these in `settings.gradle.kts` from the environment — git SHA, branch, CI build number, JDK vendor — and attach them inside the `buildScan { ... }` block, often guarded by `background { }` so the work doesn't slow the build. On a Develocity server these tags and values become **searchable dimensions**: you can list all failed CI scans on `main` from the last week, or compare every scan tagged with a given JDK. Without enrichment, scans are isolated; with it, they form a queryable history that turns ad-hoc debugging into trend analysis. It's the foundation for using scans as observability rather than one-off reports.

code

kotlin · 7 lines
kotlin
develocity { buildScan {
  tag(if (System.getenv("CI") != null) "CI" else "LOCAL")
  System.getenv("GITHUB_SHA")?.let { value("Git Commit", it) }
  System.getenv("GITHUB_RUN_ID")?.let {
    link("CI Build", "https://github.com/acme/app/actions/runs/$it")
  }
} }

go deeper

for a junior

Awareness that scans can carry custom labels is enough; details are senior-level.

for a middle

Name tag/value/link and a use case like recording the git commit.

for a senior

Design an enrichment scheme (CI vs local, commit, branch, build link) and explain background { } and searchability.

for a principal

Standardize a tagging taxonomy org-wide for observability and address PII/obfuscation governance for shared scans.

## The enrichment API A raw scan already captures a lot, but it has no idea about *your* world — which CI job, which git commit, which feature branch. The `buildScan` extension lets you inject that context. The three core methods: - **`tag(String)`** — a boolean label for filtering. Common tags: `CI`, `LOCAL`, `main`, `dirty` (uncommitted changes). - **`value(name, value)`** — a searchable key/value pair, e.g. `value("Git Commit", sha)`, `value("Git Branch", branch)`, `value("CI Build Number", n)`. - **`link(name, url)`** — a clickable link out of the scan, e.g. back to the CI build, the PR, or the commit on your SCM host. ## Where and how You attach them in **`settings.gradle.kts`**, computing values from environment variables and git: ```kotlin develocity { buildScan { val ci = System.getenv("CI") != null tag(if (ci) "CI" else "LOCAL") System.getenv("GITHUB_SHA")?.let { value("Git Commit", it) } System.getenv("GITHUB_RUN_ID")?.let { link("CI Build", "https://github.com/acme/app/actions/runs/$it") } // run anything slow (e.g. a git command) off the critical path: background { val branch = providers.exec { commandLine("git", "rev-parse", "--abbrev-ref", "HEAD") } .standardOutput.asText.get().trim() value("Git Branch", branch) tag(branch) } } } ``` The **`background { }`** block runs the enrichment work asynchronously so computing values (e.g. shelling out to git) doesn't add to build time. ## Why it pays off On the **public** server, tags/values/links make a single scan self-documenting — anyone you share the URL with sees the commit and can jump to the CI run. On a **Develocity** server, they become **first-class searchable dimensions**. You can run queries like: - all `CI` scans on branch `main` that `FAILED` this week, - every scan with `Git Commit = <sha>` to compare a flaky build across runs, - builds grouped by JDK vendor to spot a toolchain regression. This is the difference between scans as **one-off reports** and scans as **build observability**: a longitudinal dataset you can mine for regressions, flaky tasks, and cache-effectiveness trends. ## Custom values vs. obfuscation Because values can carry environment data, Develocity also offers **obfuscation** hooks (e.g. for usernames/IP/hostnames) so you don't leak PII into shared scans — worth configuring when publishing broadly.

  • Why wrap git lookups in a `background { }` block?
    Computing values can mean shelling out (e.g. `git rev-parse`), which adds latency. `background { }` runs that work asynchronously so enrichment never extends the critical path of the build.
  • What's the practical benefit of `value()` over `tag()`?
    Tags are boolean labels good for filtering; values are key/value pairs you can search and compare on (e.g. group all scans by a specific commit or JDK), enabling longitudinal analysis on a Develocity server.
  • What risk comes with attaching custom values, and how do you mitigate it?
    You can leak PII or sensitive environment data into shared scans. Develocity provides obfuscation hooks for usernames/IPs/hostnames; scrub or whitelist what you attach when publishing broadly.

saying these in an interview costs you the question

  • Computing expensive values synchronously and inflating build time instead of using `background { }`.
  • Treating tags and values as interchangeable — values are searchable key/value data; tags are boolean filters.

context