Datadog Go Test Optimization onboarding
Use this skill when you need to instrument a Bazel Go repository with Datadog
Test Optimization. This skill is intentionally project-neutral: it is stored in
the repository as a Codex-compatible skill, but any agent can read it as a
normal implementation guide.
Non-negotiable contract
Keep the RFC contract intact:
- Tests write JSON payloads to
TEST_UNDECLARED_OUTPUTS_DIR.
- Bazel collects those files under
bazel-testlogs/<target>/test.outputs/.
- The doctor validates local files after
bazel test.
- The uploader runs after the doctor with
bazel run.
- Use the default Python 3.10+ uploader unless a temporary rollback explicitly
requires
use_python_uploader = False. Its coordinator prepares shared
CODEOWNERS, contexts, schemas, freshness, and telemetry once, then starts up
to eight independent file workers by default. Each worker owns enrichment,
validation, preventive splitting, retries, and cleanup for one test,
coverage, or telemetry source file.
- Run one uploader process. Use
--dry-run --validate-enrichment to prepare
requests without HTTP or deletion, --debug only for verbose redacted
diagnostics, and review the final file/type/split/request/cleanup totals.
- Test bodies are split before HTTP when they exceed
4_718_592 bytes. HTTP
413 is terminal and must not trigger a retry or adaptive split; coverage
and telemetry are not split.
- Do not add payload proxies or msgpack-only handoff paths.
- Do not pass
DD_GIT_* through --test_env; use --repo_env for sync metadata.
- Do not pass uploader endpoints or credentials into the test sandbox.
- Do not copy or apply
rules_go patch bundles manually.
- Put
--remote_download_minimal,
--remote_download_regex=.*test[.]outputs.*, and
--zip_undeclared_test_outputs in the active test .bazelrc config when
remote execution or remote cache can leave test outputs remote-only.
- Configure doctor/uploader with repeatable
--bep-json=<path> flags,
--freshness-source=bep, --freshness-mode=required,
--artifact-source=bep, and --artifact-staging-dir=<temp-dir>.
If BEP still points at HTTP/HTTPS outputs.zip artifacts, use
--remote-artifacts=download or required without a downloader. Use a
downloader only for bytestream/CAS/custom-auth artifact providers.
- Run pilot tests with a fresh
--build_event_json_file path per Bazel test
invocation; pass the same paths to doctor/uploader with --bep-json.
- In CI, keep a per-job diagnostic report directory with
DD_TEST_OPTIMIZATION_REPORT_DIR or wrapper --report-dir, and configure
wrapper --support-bundle or DD_TEST_OPTIMIZATION_SUPPORT_BUNDLE for
complete escalation artifacts. For first-pass customer troubleshooting after
tests have run, ask for
bazel run --config=test-optimization //<topt-package>:dd_test_optimization_doctor -- --support-bundle=<path>
with any matching BEP/artifact flags. Use //: for <topt-package> only in
a small repository whose targets intentionally live at the root.
For bundle triage, inspect summary.md, diagnostics.json,
reports/doctor-report.json, optional uploader reports, and
command/flags.json in that order.
First actions
- Read the consumer repository's Bazel shape before editing:
- Does it use
MODULE.bazel, WORKSPACE, or both?
- What command does the repository use for Bazel:
bazel, bazelw, bzl,
or a repo-local wrapper?
- What is the Bazel repository name for
rules_go?
- Is there a repo-local Go test wrapper?
- What Go SDK/toolchain version does Bazel use?
- What Test Optimization sync repository name will this service use?
- Which targets are runtime tests and which are build-only controls?
- Read this repository's current docs when details are needed:
README.md for quickstart and current command flow.
docs/Language_Onboarding.md for language-specific Go guidance.
docs/Installation_Reference.md for flags, helper APIs, and pinning.
docs/Uploader_Reference.md for doctor, dry-run, and upload behavior.
docs/Troubleshooting.md for failure diagnosis.
- Pick the correct path:
- Bzlmod fresh/simple Go repo: use the Go bootstrap guided flow.
- WORKSPACE repo: use the generic WORKSPACE helper.
- Large monorepo with an existing central wrapper: keep repo policy local
and route that same wrapper through
dd_topt_go_test; do not introduce a
second macro name for enabled tests.
- Large monorepo with a consumer-owned managed test command: use manifest
sync only when that command can expand exact labels and derive
service/runtime contexts. Do not create a checked-in target/service map.
Implementation paths
- WORKSPACE consumers: follow workspace-onboarding.md.
- Bzlmod consumers: follow bzlmod-onboarding.md.
- Validation: follow validation-checklist.md.
- Debugging: follow troubleshooting.md.
Universal shape
Every successful Go onboarding should end with these pieces:
- Repository resolution fetches Test Optimization metadata during Bazel
repository/module resolution.
- The Orchestrion tool repository normally derives its complete supported
dd-trace-go version map from the consumer's checked-in
go.mod and go.sum.
Explicit shared/per-module versions are escape hatches, not a second normal
pin-maintenance path.
- Guided bootstrap wires the repository's Bazel-managed Go SDK into
Orchestrion using the same version as the Go toolchain and sync runtime.
Enabled bootstrap must not depend on a host
go binary, and this SDK wiring
remains workspace-wide rather than per service or test.
- Orchestrion pin files exist and are exported when tests live below the
workspace root.
- Go tests use one central repo-local wrapper that delegates to
dd_topt_go_test. The named config, not a different BUILD macro, selects
enabled behavior.
- A
.topt clone preserves the source test's execution policy. Keep
no-remote-exec on the actual TestRunner, but do not let it constrain
deterministic stdlib, synthetic helper, compile, or link actions; those must
remain cacheable and remote-capable.
- The workspace has exactly one
dd_test_optimization_doctor target and one
dd_upload_payloads target. Root is acceptable for small repositories; use a
lightweight package such as //tools/test_optimization in monorepos.
.bazelrc or CLI commands provide sync metadata with --repo_env,
including the bootstrap-managed metadata key set and any runtime-specific
module path override, such as GO_MODULE_PATH, only when needed.
- Go module updates are deliberate: bootstrap uses targeted module sync by
default, large WORKSPACE repositories verify checked-in
go_repository
declarations when they exist, and agents do not run broad go mod tidy
unless the repository explicitly wants that behavior.
- Test commands use a named config such as
--config=test-optimization.
- Validation first runs an ordinary public test without that config, then the
enabled test with it on the same fresh Bazel output root. Disabled mode must
keep the test runnable without metadata requests, payload generation, or real
Orchestrion repository resolution.
- Remote-output-sensitive test configs include
--remote_download_minimal --remote_download_regex=.*test[.]outputs.*
and --zip_undeclared_test_outputs.
- Validation commands pass each matching BEP file with repeatable
--bep-json
flags and required BEP freshness/artifact flags. Use
DD_TEST_OPTIMIZATION_* environment variables only for single-invocation
manual flows where one BEP file is sufficient.
- CI wrappers write
doctor-report.json, one selected uploader report
(uploader-dry-run-report.json or uploader-upload-report.json), and
dd-test-optimization-support.zip under a per-job report directory.
Prefer the wrapper support bundle for full CI escalation; use the doctor-only
support bundle for the simplest initial customer request. Keep individual
reports for local inspection and manual fallback flows.
- A real upload processes every available fresh valid payload after validation
attempts. The wrapper preserves the earliest test, doctor, or uploader exit
code; uploader errors never replace an earlier test result.
For automatic managed Go/Python monorepos, the universal shape has these
additional constraints:
- declare one
test_optimization_manifest_sync aggregate repository, separate
from static multi-sync;
- keep target discovery, service naming, and managed orchestration in the
consumer repository;
- load
topt_data_by_target in the central wrapper and preserve the raw Go
path when the current full label is absent;
- wire doctor to aggregate context data and the generated
:expected_targets file;
- treat the invocation manifest as a private command handoff, never as
user-facing
.bazelrc configuration;
- reuse that exact manifest and resolved metadata snapshot for test, doctor,
dry-run, and optional upload; only a later managed invocation creates a new
manifest and fetches current backend state;
- preserve Bazel test-result cache hits when selected settings/module payloads
are unchanged, and keep variable telemetry timing facts out of test inputs;
- keep Java and other non-Python companions on their static onboarding paths.
Use the consumer's existing Bazel entrypoint in all commands. Do not switch a
repository from bzl or bazelw to raw bazel just because examples use the
generic binary name.
For large WORKSPACE repositories, prefer the Go bootstrap's --workspace-mode
scaffolding modes before writing boilerplate by hand. Use --print-* modes to
review snippets first. Use --write-root-targets only for a small repository
that intentionally owns doctor/uploader targets at the root. In a monorepo,
create those targets in its lightweight Test Optimization package, then use
--write-bazelrc, --write-orchestrion-files, --write-wrapper-template, and
--write-validation-script only when those generated files match local policy.
Large WORKSPACE Monorepo Policy
When applying this guide to a large WORKSPACE monorepo with a repository-local
Go wrapper, treat it as a consumer-specific integration:
- Use the WORKSPACE onboarding path, not the Bzlmod guided flow.
- Keep Test Optimization policy in the existing repo-local central Go wrapper
instead of changing every BUILD file or adding an optimized-only wrapper.
- The central Go wrapper should pass
orchestrion_mode = "test_optimization" for standard Go testing targets.
Do not rely on the public macro's default general mode for Test
Optimization onboarding. Use general only for explicit compatibility
validation.
- Preserve repository-local wrapper policy such as tags, scheduling, Docker
defaults, platform constraints, and flaky-test behavior in the local helper
layer.
- Validate with fresh
bazel-testlogs/<target>/test.outputs/, inspect
bazel_target_metadata.json for
bazel.go.orchestrion.mode = "test_optimization" on Go targets, then run
the doctor and one enrichment-validating uploader pass; use dry-run only
when real upload is disabled.
Branch and PR hygiene
Before making changes in a real repository, confirm whether to use the current
branch or create a new branch from the latest default branch. Keep onboarding
changes reviewable:
- Put reusable rule changes in
rules_test_optimization, not in a consumer
repository workaround.
- Put consumer-specific scheduling, Docker, tag, flaky, and wrapper policy in
the consumer repository.
- Put automatic target expansion and service-derivation policy in the
consumer's managed command. Do not move it into the Rule or Gazelle.
- If an issue requires changing this rule repository, add matching fixture
coverage in
rules_test_optimization_tests before declaring it solved.
Stop conditions
Stop and escalate instead of guessing when:
- The repository requires a new public rule behavior not covered by current docs.
- A target produces msgpack payloads instead of JSON.
- The doctor reports missing Git metadata after sync was configured.
- The doctor reports missing Bazel metadata.
- A known pilot that requires module selection reports
bazel.go.payload_selection = "full_bundle_no_match", or a generic fallback
reports it without an explicitly configured doctor exception.
- The only available fix would put
DD_GIT_*, credentials, or upload endpoints
into the test sandbox.
- Validation requires secrets that are not already available in the environment.
1---2name: datadog-go-test-optimization-onboarding3description: Use when instrumenting a Bazel Go repository or monorepo with Datadog Test Optimization and Orchestrion. Applies to WORKSPACE and Bzlmod consumers, large monorepos with local Go wrappers, doctor/uploader validation, and RFC-safe setup that avoids patches, payload proxies, DD_GIT_* test environment variables, and missing remote outputs.4---56<!--7Unless explicitly stated otherwise all files in this repository are licensed under8the Apache 2.0 License.910This product includes software developed at Datadog11(https://www.datadoghq.com/) Copyright 2025-Present Datadog, Inc.12-->131415# Datadog Go Test Optimization onboarding1617Use this skill when you need to instrument a Bazel Go repository with Datadog18Test Optimization. This skill is intentionally project-neutral: it is stored in19the repository as a Codex-compatible skill, but any agent can read it as a20normal implementation guide.2122## Non-negotiable contract2324Keep the RFC contract intact:2526- Tests write JSON payloads to `TEST_UNDECLARED_OUTPUTS_DIR`.27- Bazel collects those files under `bazel-testlogs/<target>/test.outputs/`.28- The doctor validates local files after `bazel test`.29- The uploader runs after the doctor with `bazel run`.30- Use the default Python 3.10+ uploader unless a temporary rollback explicitly31 requires `use_python_uploader = False`. Its coordinator prepares shared32 CODEOWNERS, contexts, schemas, freshness, and telemetry once, then starts up33 to eight independent file workers by default. Each worker owns enrichment,34 validation, preventive splitting, retries, and cleanup for one test,35 coverage, or telemetry source file.36- Run one uploader process. Use `--dry-run --validate-enrichment` to prepare37 requests without HTTP or deletion, `--debug` only for verbose redacted38 diagnostics, and review the final file/type/split/request/cleanup totals.39- Test bodies are split before HTTP when they exceed `4_718_592` bytes. HTTP40 `413` is terminal and must not trigger a retry or adaptive split; coverage41 and telemetry are not split.42- Do not add payload proxies or msgpack-only handoff paths.43- Do not pass `DD_GIT_*` through `--test_env`; use `--repo_env` for sync metadata.44- Do not pass uploader endpoints or credentials into the test sandbox.45- Do not copy or apply `rules_go` patch bundles manually.46- Put `--remote_download_minimal`,47 `--remote_download_regex=.*test[.]outputs.*`, and48 `--zip_undeclared_test_outputs` in the active test `.bazelrc` config when49 remote execution or remote cache can leave test outputs remote-only.50- Configure doctor/uploader with repeatable `--bep-json=<path>` flags,51 `--freshness-source=bep`, `--freshness-mode=required`,52 `--artifact-source=bep`, and `--artifact-staging-dir=<temp-dir>`.53 If BEP still points at HTTP/HTTPS `outputs.zip` artifacts, use54 `--remote-artifacts=download` or `required` without a downloader. Use a55 downloader only for bytestream/CAS/custom-auth artifact providers.56- Run pilot tests with a fresh `--build_event_json_file` path per Bazel test57 invocation; pass the same paths to doctor/uploader with `--bep-json`.58- In CI, keep a per-job diagnostic report directory with59 `DD_TEST_OPTIMIZATION_REPORT_DIR` or wrapper `--report-dir`, and configure60 wrapper `--support-bundle` or `DD_TEST_OPTIMIZATION_SUPPORT_BUNDLE` for61 complete escalation artifacts. For first-pass customer troubleshooting after62 tests have run, ask for63 `bazel run --config=test-optimization //<topt-package>:dd_test_optimization_doctor -- --support-bundle=<path>`64 with any matching BEP/artifact flags. Use `//:` for `<topt-package>` only in65 a small repository whose targets intentionally live at the root.66 For bundle triage, inspect `summary.md`, `diagnostics.json`,67 `reports/doctor-report.json`, optional uploader reports, and68 `command/flags.json` in that order.6970## First actions71721. Read the consumer repository's Bazel shape before editing:73 - Does it use `MODULE.bazel`, `WORKSPACE`, or both?74 - What command does the repository use for Bazel: `bazel`, `bazelw`, `bzl`,75 or a repo-local wrapper?76 - What is the Bazel repository name for `rules_go`?77 - Is there a repo-local Go test wrapper?78 - What Go SDK/toolchain version does Bazel use?79 - What Test Optimization sync repository name will this service use?80 - Which targets are runtime tests and which are build-only controls?812. Read this repository's current docs when details are needed:82 - `README.md` for quickstart and current command flow.83 - `docs/Language_Onboarding.md` for language-specific Go guidance.84 - `docs/Installation_Reference.md` for flags, helper APIs, and pinning.85 - `docs/Uploader_Reference.md` for doctor, dry-run, and upload behavior.86 - `docs/Troubleshooting.md` for failure diagnosis.873. Pick the correct path:88 - Bzlmod fresh/simple Go repo: use the Go bootstrap guided flow.89 - WORKSPACE repo: use the generic WORKSPACE helper.90 - Large monorepo with an existing central wrapper: keep repo policy local91 and route that same wrapper through `dd_topt_go_test`; do not introduce a92 second macro name for enabled tests.93 - Large monorepo with a consumer-owned managed test command: use manifest94 sync only when that command can expand exact labels and derive95 service/runtime contexts. Do not create a checked-in target/service map.9697## Implementation paths9899- **WORKSPACE consumers:** follow [workspace-onboarding.md](references/workspace-onboarding.md).100- **Bzlmod consumers:** follow [bzlmod-onboarding.md](references/bzlmod-onboarding.md).101- **Validation:** follow [validation-checklist.md](references/validation-checklist.md).102- **Debugging:** follow [troubleshooting.md](references/troubleshooting.md).103104## Universal shape105106Every successful Go onboarding should end with these pieces:107108- Repository resolution fetches Test Optimization metadata during Bazel109 repository/module resolution.110- The Orchestrion tool repository normally derives its complete supported111 dd-trace-go version map from the consumer's checked-in `go.mod` and `go.sum`.112 Explicit shared/per-module versions are escape hatches, not a second normal113 pin-maintenance path.114- Guided bootstrap wires the repository's Bazel-managed Go SDK into115 Orchestrion using the same version as the Go toolchain and sync runtime.116 Enabled bootstrap must not depend on a host `go` binary, and this SDK wiring117 remains workspace-wide rather than per service or test.118- Orchestrion pin files exist and are exported when tests live below the119 workspace root.120- Go tests use one central repo-local wrapper that delegates to121 `dd_topt_go_test`. The named config, not a different BUILD macro, selects122 enabled behavior.123- A `.topt` clone preserves the source test's execution policy. Keep124 `no-remote-exec` on the actual `TestRunner`, but do not let it constrain125 deterministic stdlib, synthetic helper, compile, or link actions; those must126 remain cacheable and remote-capable.127- The workspace has exactly one `dd_test_optimization_doctor` target and one128 `dd_upload_payloads` target. Root is acceptable for small repositories; use a129 lightweight package such as `//tools/test_optimization` in monorepos.130- `.bazelrc` or CLI commands provide sync metadata with `--repo_env`,131 including the bootstrap-managed metadata key set and any runtime-specific132 module path override, such as `GO_MODULE_PATH`, only when needed.133- Go module updates are deliberate: bootstrap uses targeted module sync by134 default, large WORKSPACE repositories verify checked-in `go_repository`135 declarations when they exist, and agents do not run broad `go mod tidy`136 unless the repository explicitly wants that behavior.137- Test commands use a named config such as `--config=test-optimization`.138- Validation first runs an ordinary public test without that config, then the139 enabled test with it on the same fresh Bazel output root. Disabled mode must140 keep the test runnable without metadata requests, payload generation, or real141 Orchestrion repository resolution.142- Remote-output-sensitive test configs include143 `--remote_download_minimal --remote_download_regex=.*test[.]outputs.*`144 and `--zip_undeclared_test_outputs`.145- Validation commands pass each matching BEP file with repeatable `--bep-json`146 flags and required BEP freshness/artifact flags. Use147 `DD_TEST_OPTIMIZATION_*` environment variables only for single-invocation148 manual flows where one BEP file is sufficient.149- CI wrappers write `doctor-report.json`, one selected uploader report150 (`uploader-dry-run-report.json` or `uploader-upload-report.json`), and151 `dd-test-optimization-support.zip` under a per-job report directory.152 Prefer the wrapper support bundle for full CI escalation; use the doctor-only153 support bundle for the simplest initial customer request. Keep individual154 reports for local inspection and manual fallback flows.155- A real upload processes every available fresh valid payload after validation156 attempts. The wrapper preserves the earliest test, doctor, or uploader exit157 code; uploader errors never replace an earlier test result.158159For automatic managed Go/Python monorepos, the universal shape has these160additional constraints:161162- declare one `test_optimization_manifest_sync` aggregate repository, separate163 from static multi-sync;164- keep target discovery, service naming, and managed orchestration in the165 consumer repository;166- load `topt_data_by_target` in the central wrapper and preserve the raw Go167 path when the current full label is absent;168- wire doctor to aggregate context data and the generated169 `:expected_targets` file;170- treat the invocation manifest as a private command handoff, never as171 user-facing `.bazelrc` configuration;172- reuse that exact manifest and resolved metadata snapshot for test, doctor,173 dry-run, and optional upload; only a later managed invocation creates a new174 manifest and fetches current backend state;175- preserve Bazel test-result cache hits when selected settings/module payloads176 are unchanged, and keep variable telemetry timing facts out of test inputs;177- keep Java and other non-Python companions on their static onboarding paths.178179Use the consumer's existing Bazel entrypoint in all commands. Do not switch a180repository from `bzl` or `bazelw` to raw `bazel` just because examples use the181generic binary name.182183For large WORKSPACE repositories, prefer the Go bootstrap's `--workspace-mode`184scaffolding modes before writing boilerplate by hand. Use `--print-*` modes to185review snippets first. Use `--write-root-targets` only for a small repository186that intentionally owns doctor/uploader targets at the root. In a monorepo,187create those targets in its lightweight Test Optimization package, then use188`--write-bazelrc`, `--write-orchestrion-files`, `--write-wrapper-template`, and189`--write-validation-script` only when those generated files match local policy.190191## Large WORKSPACE Monorepo Policy192193When applying this guide to a large WORKSPACE monorepo with a repository-local194Go wrapper, treat it as a consumer-specific integration:195196- Use the WORKSPACE onboarding path, not the Bzlmod guided flow.197- Keep Test Optimization policy in the existing repo-local central Go wrapper198 instead of changing every BUILD file or adding an optimized-only wrapper.199- The central Go wrapper should pass200 `orchestrion_mode = "test_optimization"` for standard Go `testing` targets.201 Do not rely on the public macro's default `general` mode for Test202 Optimization onboarding. Use `general` only for explicit compatibility203 validation.204- Preserve repository-local wrapper policy such as tags, scheduling, Docker205 defaults, platform constraints, and flaky-test behavior in the local helper206 layer.207- Validate with fresh `bazel-testlogs/<target>/test.outputs/`, inspect208 `bazel_target_metadata.json` for209 `bazel.go.orchestrion.mode = "test_optimization"` on Go targets, then run210 the doctor and one enrichment-validating uploader pass; use dry-run only211 when real upload is disabled.212213## Branch and PR hygiene214215Before making changes in a real repository, confirm whether to use the current216branch or create a new branch from the latest default branch. Keep onboarding217changes reviewable:218219- Put reusable rule changes in `rules_test_optimization`, not in a consumer220 repository workaround.221- Put consumer-specific scheduling, Docker, tag, flaky, and wrapper policy in222 the consumer repository.223- Put automatic target expansion and service-derivation policy in the224 consumer's managed command. Do not move it into the Rule or Gazelle.225- If an issue requires changing this rule repository, add matching fixture226 coverage in `rules_test_optimization_tests` before declaring it solved.227228## Stop conditions229230Stop and escalate instead of guessing when:231232- The repository requires a new public rule behavior not covered by current docs.233- A target produces msgpack payloads instead of JSON.234- The doctor reports missing Git metadata after sync was configured.235- The doctor reports missing Bazel metadata.236- A known pilot that requires module selection reports237 `bazel.go.payload_selection = "full_bundle_no_match"`, or a generic fallback238 reports it without an explicitly configured doctor exception.239- The only available fix would put `DD_GIT_*`, credentials, or upload endpoints240 into the test sandbox.241- Validation requires secrets that are not already available in the environment.