RFC: Custom Build Metadata for Tuist Insights
Summary
This RFC proposes adding support for custom metadata (tags and key-value pairs) to Tuist’s build insights feature. Teams will be able to attach arbitrary metadata to builds, enabling better filtering, categorization, and correlation with external systems.
Motivation
Build insights become significantly more valuable when teams can attach context specific to their workflows. Common use cases include:
- Categorizing builds: Tag builds by feature team, project area, or build type (nightly, release candidate, PR validation)
- Correlating with external systems: Link builds to Jira tickets, Linear issues, GitHub PRs, or internal dashboards
- Tracking experiments: Attach A/B test identifiers, feature flag states, or configuration variants
- Environment context: Capture CI runner labels, machine pools, or deployment targets
- Performance baselines: Mark baseline builds for regression comparisons
Prior Art
Gradle Enterprise (Develocity)
Develocity provides three mechanisms for extending build scans:
- Tags — Simple labels for categorization (e.g.,
CI,LOCAL,dirty,release) - Links — Hyperlinks to external resources (CI builds, tickets, source commits)
- Custom Values — Key-value pairs for metrics and computed data
Example Gradle DSL:
buildScan {
tag("CI")
link("CI Build", System.getenv("BUILD_URL"))
value("Git Commit ID", commitId)
value("Git Branch Name", branchName)
}
Gradle also provides the Common Custom User Data plugin which automatically captures common metadata like Git info, IDE vs CLI invocation, and CI-specific data. Tuist already captures similar CI metadata automatically — this RFC focuses on enabling user-defined custom metadata.
Bazel
Bazel uses the --build_metadata flag to attach key-value pairs:
bazel build //... --build_metadata=REPO_URL=https://github.com/org/repo
bazel build //... --build_metadata=BRANCH_NAME=main
bazel build //... --build_metadata=TAG_ENV=production
Metadata flows through the Build Event Protocol as BuildMetadata events, which tools like BuildBuddy consume for display and filtering.
Bazel also supports a workspace status command — a script that outputs key-value pairs, enabling dynamic metadata computation at build time.
Proposed Solution
Primary Mechanism: Environment Variables
Environment variables are the recommended approach for attaching custom metadata. This choice is driven by how build insights are integrated: the primary integration point is the post-action scheme that runs tuist inspect build after each build. Environment variables are naturally inherited by post-action scripts, making them the most practical mechanism.
# Tags (comma-separated or multiple prefixed variables)
export TUIST_BUILD_TAGS="nightly,ios-team,release-candidate"
# Or using prefixed individual tags
export TUIST_BUILD_TAG_TEAM="ios-team"
export TUIST_BUILD_TAG_TYPE="nightly"
# Custom key-value pairs
export TUIST_BUILD_METADATA_TICKET="PROJ-1234"
export TUIST_BUILD_METADATA_RUNNER="macos-14-xlarge"
export TUIST_BUILD_METADATA_JIRA="https://jira.company.com/browse/PROJ-1234"
export TUIST_BUILD_METADATA_PR="https://github.com/org/repo/pull/123"
The dashboard will automatically detect URL values in metadata and render them as clickable links.
Why environment variables?
- Post-action compatibility: Environment variables are inherited by post-action scripts, where
tuist inspect buildruns - Works seamlessly with all CI systems: Set variables in your CI workflow and they flow through to the post-action
- No code changes required: No need to modify schemes or project configuration
- Easy to set conditionally: CI workflows can set different metadata based on branch, trigger, etc.
- Familiar pattern: Developers already use environment variables for CI configuration
- Cross-platform: Environment variables work the same way across Apple and Android/Gradle builds
Android/Gradle Support
The initial implementation will focus on Apple platforms (via tuist inspect build post-actions). However, the environment variable approach is designed to be cross-platform.
For Android/Gradle projects, custom metadata will work the same way — Gradle plugins can read environment variables via System.getenv(). When Tuist adds build insights for Gradle projects, a Tuist Gradle plugin would:
- Hook into Gradle build events
- Read
TUIST_BUILD_*environment variables - Send build data + custom metadata to the Tuist server
This means teams with mixed Apple/Android codebases can use the same TUIST_BUILD_* environment variables in their CI workflows, and metadata will flow to both platforms’ build insights.
Metadata Types
| Type | Purpose | Example |
|---|---|---|
| Tags | Simple labels for filtering and grouping | nightly, release, ios-team, flaky-test-retry |
| Metadata | Key-value pairs for structured data (URLs are auto-linked) | ticket=PROJ-1234, runner=macos-14-xlarge, jira=https://... |
Dashboard Integration
Build List View
- Display tags as colored chips/badges next to each build
- Filter builds by tags via multi-select dropdown
- Filter by metadata via a filter control that allows specifying both key and value (e.g., key:
ticket, value:PROJ-1234)
Build Detail View
- Show tags prominently at the top (as chips/badges)
- Display custom metadata in a dedicated “Custom Metadata” section, showing key-value pairs in a simple table format
- Auto-detect URL values and render them as clickable links
API Changes
Create Build Run (existing endpoint extension)
{
"build": {
"duration": 45000,
"status": "success",
"scheme": "App",
"custom_metadata": {
"tags": ["nightly", "release-candidate"],
"values": {
"ticket": "PROJ-1234",
"runner": "macos-14-xlarge",
"jira": "https://jira.company.com/browse/PROJ-1234",
"pr": "https://github.com/org/repo/pull/123"
}
}
}
}
Alternatives Considered
1. Command-Line Flags
Adding --tag and --metadata flags to tuist inspect build:
tuist inspect build \
--tag "nightly" \
--metadata "ticket=PROJ-1234" \
--metadata "jira=https://jira.company.com/browse/PROJ-1234"
Not recommended as primary mechanism because:
- Post-action scheme limitation: The primary integration for build insights is via post-action schemes that run
tuist inspect buildafter each build. Post-action scripts are defined in the Xcode scheme and cannot easily accept dynamic command-line arguments. - Requires scheme modification: To use flags, teams would need to modify their scheme’s post-action, which defeats the purpose of the seamless auto-generated scheme integration.
- Environment variables solve the same problem: Any metadata that could be passed via flags can be set as environment variables, which are inherited by post-actions automatically.
Command-line flags could be added later for users who invoke tuist inspect build directly (outside of post-actions), but this is a minority use case.
