This page contains full installation and setup flows. For fast onboarding, use
the scenario quickstarts in README.md. For language-specific single-service
and multi-service onboarding, use docs/Language_Onboarding.md.
In your MODULE.bazel:
bazel_dep(name = "datadog-rules-test-optimization", version = "1.2.0")
git_override(
module_name = "datadog-rules-test-optimization",
remote = "https://github.com/DataDog/rules_test_optimization.git",
commit = "<commit-sha>",
)
# Optional companion module (only needed if you use dd_topt_go_test)
bazel_dep(name = "datadog-rules-test-optimization-go", version = "1.2.0")
git_override(
module_name = "datadog-rules-test-optimization-go",
remote = "https://github.com/DataDog/rules_test_optimization.git",
commit = "<commit-sha>",
strip_prefix = "modules/go",
)
# Only needed when using dd_topt_go_test
bazel_dep(name = "rules_go", version = "0.60.0")
# Optional companion module (only needed if you use dd_topt_py_test)
bazel_dep(name = "datadog-rules-test-optimization-python", version = "1.2.0")
git_override(
module_name = "datadog-rules-test-optimization-python",
remote = "https://github.com/DataDog/rules_test_optimization.git",
commit = "<commit-sha>",
strip_prefix = "modules/python",
)
# Optional companion module (only needed if you use dd_topt_java_test)
bazel_dep(name = "datadog-rules-test-optimization-java", version = "1.2.0")
git_override(
module_name = "datadog-rules-test-optimization-java",
remote = "https://github.com/DataDog/rules_test_optimization.git",
commit = "<commit-sha>",
strip_prefix = "modules/java",
)
# Optional companion module (only needed if you use dd_topt_nodejs_test)
bazel_dep(name = "datadog-rules-test-optimization-nodejs", version = "1.2.0")
git_override(
module_name = "datadog-rules-test-optimization-nodejs",
remote = "https://github.com/DataDog/rules_test_optimization.git",
commit = "<commit-sha>",
strip_prefix = "modules/nodejs",
)
# Optional companion module (only needed if you use dd_topt_dotnet_test)
bazel_dep(name = "datadog-rules-test-optimization-dotnet", version = "1.2.0")
git_override(
module_name = "datadog-rules-test-optimization-dotnet",
remote = "https://github.com/DataDog/rules_test_optimization.git",
commit = "<commit-sha>",
strip_prefix = "modules/dotnet",
)
# Optional companion module (only needed if you use dd_topt_ruby_test)
bazel_dep(name = "datadog-rules-test-optimization-ruby", version = "1.2.0")
git_override(
module_name = "datadog-rules-test-optimization-ruby",
remote = "https://github.com/DataDog/rules_test_optimization.git",
commit = "<commit-sha>",
strip_prefix = "modules/ruby",
)Use the same full commit SHA (40 chars) for core and companion modules.
For mirrored/archive installs, also pin and verify archive sha256 values (see
"Archive mirror installation" below) so the fetched source is integrity-checked
in CI and local builds.
For v1.2.0, use commit
69953536d4ef1252c8181c267d16c61263f0aa4c.
Before copying Go/Orchestrion pins into a consumer repository, generate them
from a squash-merged commit that is already reachable from origin/main.
From a rules_test_optimization checkout:
./bazelw run //tools/dev:print_go_onboarding_pins -- \
--commit "$(git rev-parse origin/main)" \
--variant complete \
--verify-main-reachableThe command prints the full tuple used by WORKSPACE archive mode:
RTO_COMMIT, RTO_REMOTE, RTO_ARCHIVE_URL, RTO_ARCHIVE_SHA256,
RTO_ARCHIVE_PREFIX, RTO_ARCHIVE_TYPE, RULES_GO_VARIANT,
RULES_GO_STRIP_PREFIX, DD_TRACE_GO_VERSION, and
ORCHESTRION_VERSION. Published GitHub codeload pins are tar.gz; use a
separate repository-owned mirror process for any other archive format.
RTO_COMMIT="69953536d4ef1252c8181c267d16c61263f0aa4c"
RTO_REMOTE="https://github.com/DataDog/rules_test_optimization.git"
RTO_ARCHIVE_URL="https://codeload.github.com/DataDog/rules_test_optimization/tar.gz/69953536d4ef1252c8181c267d16c61263f0aa4c"
RTO_ARCHIVE_SHA256="fd54d1871fc01ff0bb3db190dfaadaa8256edd68a4f3bb85ecc08b315fbf5bd4"
RTO_ARCHIVE_PREFIX="rules_test_optimization-69953536d4ef1252c8181c267d16c61263f0aa4c"
RTO_ARCHIVE_TYPE="tar.gz"
RULES_GO_VARIANT="complete"
RULES_GO_STRIP_PREFIX="third_party/rules_go_orchestrion_complete"
DD_TRACE_GO_VERSION="v2.9.0-rc.2"
ORCHESTRION_VERSION="v1.9.0"The archive URL, SHA256, and prefix are tied to the repository commit. Use the
same values with RULES_GO_VARIANT="base" and
RULES_GO_STRIP_PREFIX="third_party/rules_go_orchestrion_base" when a
consumer should use the base variant instead of the complete variant.
From a consumer that already has the Go companion available, the bootstrap can print the same tuple or write a checked-in Markdown summary:
bazel run @datadog-rules-test-optimization-go//:dd_topt_go_bootstrap -- \
--print-published-pins \
--rto-commit <published-origin-main-sha> \
--rules-go-variant complete
bazel run @datadog-rules-test-optimization-go//:dd_topt_go_bootstrap -- \
--write-onboarding-summary=TEST_OPTIMIZATION_GUIDE.md \
--rto-commit <published-origin-main-sha> \
--rules-go-variant completeThe bootstrap summary command does not inspect MODULE.bazel or go.mod; it
validates that the commit is a full SHA, hashes the published archive, and
writes a Datadog-managed Markdown file. If you run it from a checkout that has
the rules_test_optimization Git history, add --verify-main-reachable for
the same origin/main reachability check as the dev helper. Existing unmanaged
files are preserved unless --force is passed.
local_path_override(
module_name = "datadog-rules-test-optimization",
path = "/absolute/path/to/datadog-rules-test-optimization",
)
local_path_override(
module_name = "datadog-rules-test-optimization-go",
path = "/absolute/path/to/datadog-rules-test-optimization/modules/go",
)
local_path_override(
module_name = "datadog-rules-test-optimization-python",
path = "/absolute/path/to/datadog-rules-test-optimization/modules/python",
)
local_path_override(
module_name = "datadog-rules-test-optimization-java",
path = "/absolute/path/to/datadog-rules-test-optimization/modules/java",
)
local_path_override(
module_name = "datadog-rules-test-optimization-nodejs",
path = "/absolute/path/to/datadog-rules-test-optimization/modules/nodejs",
)
local_path_override(
module_name = "datadog-rules-test-optimization-dotnet",
path = "/absolute/path/to/datadog-rules-test-optimization/modules/dotnet",
)
local_path_override(
module_name = "datadog-rules-test-optimization-ruby",
path = "/absolute/path/to/datadog-rules-test-optimization/modules/ruby",
)test_optimization_sync = use_extension(
"@datadog-rules-test-optimization//tools/core:test_optimization_sync.bzl",
"test_optimization_sync_extension",
)
# Minimal usage: defaults to writing under .testoptimization and creating
# @test_optimization_data//:test_optimization_files
test_optimization_sync.test_optimization_sync(
name = "test_optimization_data",
)
use_repo(test_optimization_sync, "test_optimization_data")Core module note: datadog-rules-test-optimization is runtime-agnostic and
does not declare language-rule dependencies. Language-specific orchestration
lives in companion modules:
datadog-rules-test-optimization-go(depends onrules_goproviders),datadog-rules-test-optimization-python,datadog-rules-test-optimization-java,datadog-rules-test-optimization-nodejs,datadog-rules-test-optimization-dotnet,datadog-rules-test-optimization-ruby.
For a fresh single-service Go workspace, the recommended path is:
- add the core + Go companion dependency/override block
- run guided bootstrap
- use the generated local wrapper
Guided bootstrap command:
bazel run @datadog-rules-test-optimization-go//:dd_topt_go_bootstrap -- \
--guided \
--service go-service \
--runtime-version 1.25.0 \
--dd-trace-go-version v2.9.0-rc.2 \
--write-bazelrcIf the Go module lives below the workspace root:
bazel run @datadog-rules-test-optimization-go//:dd_topt_go_bootstrap -- \
--guided \
--service go-service \
--runtime-version 1.25.0 \
--dd-trace-go-version v2.9.0-rc.2 \
--go-module-dir path/to/go-module \
--write-bazelrc--dd-trace-go-version is optional. If omitted, the workspace uses the default
v2.9.0-rc.2. It accepts a tag, pseudo-version,
branch, or commit SHA. Bootstrap resolves that input to exact tracer versions,
keeps the local Go module pins on those same versions, and prevents Bazel and
the Go module from silently drifting apart.
Bootstrap uses --go-mod-sync=targeted by default. Targeted sync updates the
Orchestrion and dd-trace-go tool requirements, resolves only the packages
needed by the generated orchestrion.tool.go, and verifies those packages with
go list -mod=readonly. It intentionally does not run go mod tidy, so large
workspaces avoid unrelated module rewrites. Use --go-mod-sync=tidy only when
you explicitly want bootstrap to tidy the whole module, or --go-mod-sync=off
when another repository-owned process manages go.mod and go.sum.
Bootstrap runs those Go module commands with go by default. Use
--go-binary=/path/to/go when the repository must sync with a specific Go SDK,
for example the same SDK Bazel uses in a monorepo. The value must be a single
executable path named go or go.exe; do not include shell arguments.
Guided bootstrap is intentionally for single-service Go workspaces. If the workspace already uses conflicting or multi-service sync wiring:
test_optimization_sync_extensiontest_optimization_multi_sync_extension- a conflicting
test_optimization_go_extensionsetup
use the manual/advanced Go setup path instead.
If the workspace already has a matching single-service
test_optimization_go_extension plus use_repo(...), guided bootstrap can
reuse that wiring and continue.
For WORKSPACE monorepos, use --workspace-mode instead of --guided.
WORKSPACE mode deliberately does not edit WORKSPACE; it prints the repository
wiring for manual placement and writes only local managed files:
bazel run @datadog-rules-test-optimization-go//:dd_topt_go_bootstrap -- \
--workspace-mode \
--print-workspace-snippet \
--service go-service \
--runtime-version 1.25.0 \
--sync-repo-name test_optimization_data \
--rto-commit <commit-sha> \
--rules-go-variant complete \
--rules-go-repo-name io_bazel_rules_goAfter placing the WORKSPACE snippet, generate the safe local scaffolding:
bazel run @datadog-rules-test-optimization-go//:dd_topt_go_bootstrap -- \
--workspace-mode \
--service go-service \
--runtime-version 1.25.0 \
--sync-repo-name test_optimization_data \
--rules-go-variant complete \
--rules-go-repo-name io_bazel_rules_go \
--write-bazelrc \
--write-root-targets \
--write-orchestrion-files \
--write-wrapper-template \
--expected-target //pkg:go_default_testThe generated wrapper template creates a plain local wrapper and an optimized
local wrapper. Keep repository-specific scheduling, tags, flaky behavior,
Docker defaults, and platform constraints in the local policy helper; the
optimized wrapper owns only topt_data, orchestrion_mode = "test_optimization",
and orchestrion_pin_files.
WORKSPACE mode does not run Go module commands unless --go-mod-sync is passed
explicitly, so large repos can review generated files before changing
go.mod/go.sum.
If the repo also has checked-in go_repository(...) declarations, validate
them immediately after targeted sync:
bazel run @datadog-rules-test-optimization-go//:dd_topt_go_bootstrap -- \
--workspace-mode \
--write-orchestrion-files \
--go-mod-sync=targeted \
--check-go-repositories \
--go-repositories-file repositories.bzl \
--go-repositories-refresh-command './tools/update-go-repositories.sh'The refresh command is repository-owned. Bootstrap never edits
repositories.bzl directly; it checks the Orchestrion and dd-trace-go module
versions, runs the refresh command only after targeted sync succeeds, and then
checks the file again. Use --print-go-repository-updates when you want the
expected versions printed for manual repair.
Generate a repeatable validation script when onboarding needs several control and instrumented targets:
bazel run @datadog-rules-test-optimization-go//:dd_topt_go_bootstrap -- \
--workspace-mode \
--write-validation-script \
--validation-script-path tools/test_optimization/validate_go_pilot.sh \
--bazel-command bazel \
--bazel-config test-optimization \
--sync-repo-name test_optimization_data \
--control-target //pkg/plain:go_default_test \
--expected-target //pkg:go_default_test \
--large-monorepo \
--min-free-disk-gb 25 \
--shutdown-bazel-on-exitThe generated script runs sync -> controls -> instrumented tests -> doctor.
It uploads only when called with --upload; the default is --no-upload. It
does not delete caches, print secrets, use BES/BEP, proxy payloads, or pass
DD_GIT_* through --test_env.
Use --write-bazelrc to insert or replace the managed
# BEGIN Datadog Test Optimization Bazelrc block. Use
--print-bazelrc-snippet when you want to review or copy the block manually.
The generated config is named test-optimization by default:
common:test-optimization --repo_env=DD_API_KEY
common:test-optimization --repo_env=DD_SITE
common:test-optimization --repo_env=DD_GIT_REPOSITORY_URL
common:test-optimization --repo_env=DD_GIT_BRANCH
common:test-optimization --repo_env=DD_GIT_TAG
common:test-optimization --repo_env=DD_GIT_COMMIT_SHA
common:test-optimization --repo_env=DD_PR_NUMBER
test:test-optimization --remote_download_outputs=all
The full generated block includes all sync metadata inputs from the repository
rule. It intentionally does not include --test_env=DD_GIT_*,
--test_env=DD_TEST_OPTIMIZATION_AGENT_URL, or
--test_env=DD_TEST_OPTIMIZATION_AGENTLESS_URL. Git metadata belongs to the
sync metadata fetch through --repo_env, and uploader credentials/endpoints are
read later by bazel run.
FETCH_SALT is intentionally not part of the generated default config. Use it
only in a separate force-refresh bazel sync --only=<repo> command when you
deliberately want fresh backend metadata.
Run Go onboarding commands with this config:
bazel test --config=test-optimization //...
bazel run --config=test-optimization //:dd_test_optimization_doctor
bazel run --config=test-optimization //:dd_upload_payloads -- --dry-run --validate-enrichment
DD_API_KEY="$DD_API_KEY" DD_SITE="$DD_SITE" bazel run --config=test-optimization //:dd_upload_payloadsDo not run the real uploader if the doctor or dry-run enrichment step fails.
For manual Go extension wiring, set module_path to the Go module path from
go.mod:
go_topt.test_optimization_go(
name = "test_optimization_data",
service = "go-service",
runtime_version = "1.25.0",
module_path = "github.com/example/service",
)GO_MODULE_PATH remains an env override and wins when set, but new workspaces
should prefer the attr so CI does not need an extra repo-env passthrough.
The generated package-facing API is:
load("//tools/build:dd_go_test.bzl", "dd_go_test")load("@datadog-rules-test-optimization-python//:topt_py_test.bzl", "dd_topt_py_test")Use the default runner_mode = "managed_pytest" when the Datadog macro should
own pytest execution. Use runner_mode = "consumer_runner" when a repository
already has a Python test wrapper and must keep control of main, imports,
and internal test policy. In consumer_runner mode, pass a custom
py_test_rule or an explicit main that runs pytest with ddtrace enabled, and
prefer module_identifier for payload selection.
Python consumers can generate copy/paste onboarding snippets from the companion without running tests or changing lockfiles:
bazel run @datadog-rules-test-optimization-python//tools/dd_topt_py_bootstrap:dd_topt_py_bootstrap -- \
--mode=workspace \
--service py-service \
--runtime-version 3.12 \
--runtime-module-path example.python.pkg \
--rto-commit <commit-sha> \
--bazel-command bazelAdd --write-bazelrc or --write-targets only when you want the tool to
insert managed blocks. The normal generated flow does not include
FETCH_SALT; use --print-refresh-snippet only for an explicit one-off
metadata refresh.
load("@datadog-rules-test-optimization-java//:topt_java_test.bzl", "dd_topt_java_test")load("@datadog-rules-test-optimization-nodejs//:topt_nodejs_test.bzl", "dd_topt_nodejs_test")load("@datadog-rules-test-optimization-dotnet//:topt_dotnet_test.bzl", "dd_topt_dotnet_test")load("@datadog-rules-test-optimization-ruby//:topt_ruby_test.bzl", "dd_topt_ruby_test")If your repository needs sync + uploader only (including non-Go languages), depend on core only:
bazel_dep(name = "datadog-rules-test-optimization", version = "1.2.0")
git_override(
module_name = "datadog-rules-test-optimization",
remote = "https://github.com/DataDog/rules_test_optimization.git",
commit = "<commit-sha>",
)
test_optimization_sync = use_extension(
"@datadog-rules-test-optimization//tools/core:test_optimization_sync.bzl",
"test_optimization_sync_extension",
)
test_optimization_sync.test_optimization_sync(name = "test_optimization_data")
use_repo(test_optimization_sync, "test_optimization_data")Fetch multiple services with one extension and select per-service data by label:
# MODULE.bazel
topt_multi = use_extension(
"@datadog-rules-test-optimization//tools/core:test_optimization_multi_sync.bzl",
"test_optimization_multi_sync_extension",
)
topt_multi.test_optimization_multi_sync(
name = "test_optimization_data",
services = ["service-a", "service-b"],
runtime_name = "python",
runtime_version = "3.12",
debug = True,
)
use_repo(
topt_multi,
# Aggregator repo
"test_optimization_data",
# Per-service repos (auto-created, names include sanitized service key)
"test_optimization_data_service_a",
"test_optimization_data_service_b",
)
# Consuming labels (aggregator):
# - All files for one service
# @test_optimization_data//:test_optimization_files_service_a
# - One module for one service (service + module label in the aggregator repo)
# @test_optimization_data//:module_service_a_core
# Per-service repos are primarily used for per-service exports like:
# load("@test_optimization_data_service_a//:export.bzl", "topt_data")
# Macros that expect "topt_data" can use either:
# 1) Select explicitly:
# load("@test_optimization_data//:export.bzl", "topt_data_by_service")
# dd_topt_py_test(..., topt_data = topt_data_by_service["service_a"])
# 2) Pass the mapping and choose via topt_service (keeps BUILD simpler):
# dd_topt_py_test(..., topt_data = topt_data_by_service, topt_service = "service_a")
# When service names sanitize to the same key, pass the deduped key shown in
# the available list (for example "service_a_2").Mixed-runtime note: keep runtime-specific sync repositories separate (for
example one sync for Go services and another sync for Python services). A single
test_optimization_multi_sync call currently models one runtime per invocation.
Additional helper file exported by the generated repository:
export.bzlwith a single dictionarytopt_datacontaining:repo_name: external repository name created by the sync rule (for example,test_optimization_data)manifest_path: path tomanifest.txtinside the generated repolabels: list of available per-module sanitized labelsset: dict-as-set keyed by sanitized labels for fast membership checksruntimes["go"]: nested object withmodule_path,sanitized_module_path,module_includedruntimes["python"]: nested object withmodule_path,sanitized_module_path,module_includedruntimes["java"]: nested object withmodule_path,sanitized_module_path,module_includedruntimes["nodejs"]: nested object withmodule_path,sanitized_module_path,module_includedruntimes["dotnet"]: nested object withmodule_path,sanitized_module_path,module_includedruntimes["ruby"]: nested object withmodule_path,sanitized_module_path,module_included
Then in any BUILD file:
filegroup(
name = "dd_test_opt_files",
srcs = ["@test_optimization_data//:test_optimization_files"],
)
# Access context.json separately (for the uploader)
filegroup(
name = "dd_test_opt_context",
srcs = ["@test_optimization_data//:test_optimization_context"],
)WORKSPACE mode is supported for v1 when Bzlmod is disabled.
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
name = "datadog-rules-test-optimization",
remote = "https://github.com/DataDog/rules_test_optimization.git",
# Use an immutable commit SHA.
commit = "<commit-sha>",
)
# Or:
# local_repository(
# name = "datadog-rules-test-optimization",
# path = "/absolute/path/to/rules_test_optimization",
# )Pin an immutable commit SHA (or internal mirrored archive) for reproducibility.
For WORKSPACE Go usage, declare the core repository first, then use the public
helper in step 8 to declare the Go companion and the Orchestrion-enabled
rules_go fork at the same revision:
datadog-rules-test-optimizationfor sync and uploader rulesdatadog-rules-test-optimization-gofordd_topt_go_test
Load the Go macro from @datadog-rules-test-optimization-go//:topt_go_test.bzl,
not from the root repository.
For WORKSPACE Python usage, declare the core repository and rules_python
first, then use the public helper in step 6 to declare the Python companion at
the same Datadog revision:
datadog-rules-test-optimizationfor sync and uploader rulesrules_pythonfor Python toolchains,py_test, andpip_parsedatadog-rules-test-optimization-pythonfordd_topt_py_test
Load the Python macro from
@datadog-rules-test-optimization-python//:topt_py_test.bzl, not from the root
repository.
For WORKSPACE Java usage, declare the core repository and rules_java first,
then use the public helper in step 7 to declare the Java companion at the same
Datadog revision:
datadog-rules-test-optimizationfor sync and uploader rulesrules_javafor Java rules and toolchainsdatadog-rules-test-optimization-javafordd_topt_java_test
Load the Java macro from
@datadog-rules-test-optimization-java//:topt_java_test.bzl, not from the root
repository.
If your environment requires http_archive, use an internal mirror and pin all
three values (urls, strip_prefix, and sha256):
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "datadog-rules-test-optimization",
urls = [
"https://artifacts.example.internal/bazel-mirror/datadog/rules_test_optimization/<commit-sha>.tar.gz",
],
# Match your mirrored archive layout. For commit archives this is typically:
# "rules_test_optimization-<full_commit_sha>".
strip_prefix = "rules_test_optimization-<commit-sha>",
sha256 = "<sha256-for-archive>",
)If your mirror repackages archives, adjust strip_prefix to the archive's
actual top-level directory.
load("@datadog-rules-test-optimization//tools/core:test_optimization_sync.bzl", "test_optimization_sync")
test_optimization_sync(
name = "test_optimization_data",
service = "my-service", # recommended; otherwise falls back to DD_SERVICE or unnamed-service
# Optional:
# runtime_name = "go",
# runtime_version = "1.25.0",
# known_tests = True,
# test_management = True,
)filegroup(
name = "dd_test_opt_files",
srcs = ["@test_optimization_data//:test_optimization_files"],
)
filegroup(
name = "dd_test_opt_context",
srcs = ["@test_optimization_data//:test_optimization_context"],
)# In root BUILD.bazel
load("@datadog-rules-test-optimization//tools/core:test_optimization_doctor.bzl", "dd_test_optimization_doctor")
load("@datadog-rules-test-optimization//tools/core:test_optimization_uploader.bzl", "dd_payload_uploader")
dd_test_optimization_doctor(
name = "dd_test_optimization_doctor",
data = ["@test_optimization_data//:test_optimization_context"],
)
dd_payload_uploader(
name = "dd_upload_payloads",
# Provide context.json via runfiles so enrichment can occur
data = ["@test_optimization_data//:test_optimization_context"],
)After tests and doctor pass, you can validate the exact enriched outbound test payload without uploading or deleting files:
bazel run --config=test-optimization //:dd_upload_payloads -- --dry-run --validate-enrichmentMulti-service aggregator variant:
dd_test_optimization_doctor(
name = "dd_test_optimization_doctor",
data = [
"@test_optimization_data//:test_optimization_context_service_a",
"@test_optimization_data//:test_optimization_context_service_b",
],
)
dd_payload_uploader(
name = "dd_upload_payloads",
data = [
"@test_optimization_data//:test_optimization_context_service_a",
"@test_optimization_data//:test_optimization_context_service_b",
],
)# Repository rule (module/repo phase) — affects refetch
common:test-optimization --repo_env=DD_API_KEY
common:test-optimization --repo_env=DD_SITE
common:test-optimization --repo_env=DD_TEST_OPTIMIZATION_AGENTLESS_URL # Optional sync/uploader agentless URL override
common:test-optimization --repo_env=DD_TEST_OPTIMIZATION_HTTP_CONNECT_TIMEOUT_SECONDS # Optional sync HTTP connect-timeout override
common:test-optimization --repo_env=DD_TEST_OPTIMIZATION_HTTP_MAX_TIME_SECONDS # Optional sync HTTP max-time override
common:test-optimization --repo_env=DD_TEST_OPTIMIZATION_HTTP_RETRY_ATTEMPTS # Optional sync HTTP retry-attempt override
common:test-optimization --repo_env=DD_TEST_OPTIMIZATION_HTTP_RETRY_DELAY_SECONDS # Optional sync HTTP retry-delay override
common:test-optimization --repo_env=DD_TEST_OPTIMIZATION_HTTP_EXECUTE_TIMEOUT_BUFFER_SECONDS # Optional sync execute-timeout buffer override
common:test-optimization --repo_env=DD_SERVICE
common:test-optimization --repo_env=DD_ENV
common:test-optimization --repo_env=DD_GIT_REPOSITORY_URL
common:test-optimization --repo_env=DD_GIT_BRANCH
common:test-optimization --repo_env=DD_GIT_TAG
common:test-optimization --repo_env=DD_GIT_COMMIT_SHA
common:test-optimization --repo_env=DD_GIT_HEAD_COMMIT
common:test-optimization --repo_env=DD_GIT_COMMIT_MESSAGE
common:test-optimization --repo_env=DD_GIT_HEAD_MESSAGE
common:test-optimization --repo_env=DD_GIT_COMMIT_AUTHOR_NAME
common:test-optimization --repo_env=DD_GIT_COMMIT_AUTHOR_EMAIL
common:test-optimization --repo_env=DD_GIT_COMMIT_AUTHOR_DATE
common:test-optimization --repo_env=DD_GIT_COMMIT_COMMITTER_NAME
common:test-optimization --repo_env=DD_GIT_COMMIT_COMMITTER_EMAIL
common:test-optimization --repo_env=DD_GIT_COMMIT_COMMITTER_DATE
common:test-optimization --repo_env=DD_GIT_HEAD_AUTHOR_NAME
common:test-optimization --repo_env=DD_GIT_HEAD_AUTHOR_EMAIL
common:test-optimization --repo_env=DD_GIT_HEAD_AUTHOR_DATE
common:test-optimization --repo_env=DD_GIT_HEAD_COMMITTER_NAME
common:test-optimization --repo_env=DD_GIT_HEAD_COMMITTER_EMAIL
common:test-optimization --repo_env=DD_GIT_HEAD_COMMITTER_DATE
common:test-optimization --repo_env=DD_GIT_PR_BASE_BRANCH
common:test-optimization --repo_env=DD_GIT_PR_BASE_BRANCH_SHA
common:test-optimization --repo_env=DD_GIT_PR_BASE_BRANCH_HEAD_SHA
common:test-optimization --repo_env=DD_PR_NUMBER
test:test-optimization --remote_download_outputs=all
# Optional: override detected Go module path for export.bzl
common:test-optimization --repo_env=GO_MODULE_PATH
# Optional: provide Python module path hint for export.bzl
common:test-optimization --repo_env=PYTHON_MODULE_PATH
# Optional: provide Java module path hint for export.bzl
common:test-optimization --repo_env=JAVA_MODULE_PATH
# Optional: provide NodeJS module path hint for export.bzl
common:test-optimization --repo_env=NODEJS_MODULE_PATH
# Optional: provide .NET module path hint for export.bzl
common:test-optimization --repo_env=DOTNET_MODULE_PATH
# Optional: provide Ruby module path hint for export.bzl
common:test-optimization --repo_env=RUBY_MODULE_PATH
# Uploader (bazel run, pass credentials inline or export before run)
# DD_API_KEY and DD_SITE are passed when running the uploader:
# DD_API_KEY="$DD_API_KEY" DD_SITE="$DD_SITE" bazel run --config=test-optimization //:dd_upload_payloads
# PowerShell equivalent:
# # Set once per shell session before first run:
# # $env:DD_API_KEY = "<your-api-key>"
# # $env:DD_SITE = "datadoghq.com"
# bazel run --config=test-optimization //:dd_upload_payloads
# Tests (runtime)
# Keep uploader credentials out of test runtime by default.
# Do not pass DD_GIT_* through --test_env. Git metadata belongs to the
# repository-rule phase through --repo_env so it cannot invalidate test actions.
# Do not pass DD_TEST_OPTIMIZATION_AGENT_URL or
# DD_TEST_OPTIMIZATION_AGENTLESS_URL through --test_env for Go/Orchestrion.
Security note: keep secret values out of .bazelrc. Forward variable names
with --repo_env=DD_API_KEY and provide values via shell/CI secret stores.
In Bazel file-mode workflows, tests do not require DD_API_KEY/DD_SITE;
those credentials are only needed for the post-test uploader step.
Git metadata note: wrappers in this repository and the sibling fixture repo can
fill in current commit author and committer fields automatically when a CI
provider does not expose them. Explicit DD_GIT_* values still win over both
provider-derived metadata and wrapper synthesis.
Repository policy note: this repository intentionally has no root .bazelrc.
Consumer repos should keep their own .bazelrc and follow CI-maintainer flags
from README.md and docs/Maintainers.md.
Python WORKSPACE onboarding keeps ownership of Python toolchains and Python
dependencies in the consumer repository. The Datadog helper declares only the
Python companion repository and maps its internal @rules_python dependency to
the repository name the consumer already uses.
Declare rules_python with the version and mirror policy approved by the
consumer repository. For a direct public pin:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "rules_python",
sha256 = "f609f341d6e9090b981b3f45324d05a819fd7a5a56434f849c761971ce2c47da",
strip_prefix = "rules_python-1.7.0",
urls = ["https://github.com/bazel-contrib/rules_python/releases/download/1.7.0/rules_python-1.7.0.tar.gz"],
)Then declare the Datadog Python companion:
load("@datadog-rules-test-optimization//tools/python:workspace_repositories.bzl", "datadog_python_test_optimization_workspace_repositories")
datadog_python_test_optimization_workspace_repositories(
rto_commit = "<commit-sha>",
rules_python_repo_name = "rules_python",
)Internal/private consumers should use SSH git fetch when anonymous archives are not available:
git_repository(
name = "datadog-rules-test-optimization",
commit = "<commit-sha>",
remote = "ssh://git@github.com/DataDog/rules_test_optimization.git",
)If you use archive mode for a private repository, Bazel must have
authentication configured for that archive URL. A 404 from codeload usually
means missing auth rather than a missing commit.
Archive mode for mirrored Datadog repositories:
load("@datadog-rules-test-optimization//tools/python:workspace_repositories.bzl", "datadog_python_test_optimization_workspace_repositories")
datadog_python_test_optimization_workspace_repositories(
rto_commit = "",
datadog_fetch = "archive",
rules_python_repo_name = "rules_python",
rto_archive_url = "https://artifacts.example.internal/bazel-mirror/datadog/rules_test_optimization/<commit-sha>.tar.gz",
rto_archive_sha256 = "<sha256-for-archive>",
rto_archive_prefix = "rules_test_optimization-<commit-sha>",
)Next configure Python toolchains and Python package dependencies through the
consumer's normal rules_python flow:
load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains")
py_repositories()
python_register_toolchains(
name = "python_3_12",
python_version = "3.12",
)
load("@rules_python//python:pip.bzl", "pip_parse")
pip_parse(
name = "python_deps",
python_interpreter_target = "@python_3_12_host//:python",
requirements_lock = "//:requirements_lock.txt",
)
load("@python_deps//:requirements.bzl", "install_deps")
install_deps()Your lockfile should include pytest and ddtrace because Python dependency
ownership remains with the consumer repository. The helper does not declare
pytest, ddtrace, pip_parse, toolchains, or lockfiles.
Update the sync repository for Python metadata:
load("@datadog-rules-test-optimization//tools/core:test_optimization_sync.bzl", "test_optimization_sync")
test_optimization_sync(
name = "test_optimization_data",
service = "py-service",
runtime_name = "python",
runtime_version = "3.12",
)Then in package BUILD files, use either managed pytest mode:
load("@python_deps//:requirements.bzl", "requirement")
load("@datadog-rules-test-optimization-python//:topt_py_test.bzl", "dd_topt_py_test")
load("@test_optimization_data//:export.bzl", "topt_data")
dd_topt_py_test(
name = "pkg_py_test",
srcs = glob(["test_*.py"]),
deps = [
requirement("ddtrace"),
requirement("pytest"),
],
imports = ["example/python/pkg"],
topt_data = topt_data,
)or consumer-runner mode when the repository already owns a pytest wrapper:
load("@python_deps//:requirements.bzl", "requirement")
load("@datadog-rules-test-optimization-python//:topt_py_test.bzl", "dd_topt_py_test")
load("@test_optimization_data//:export.bzl", "topt_data")
load("//tools/build:py_test.bzl", "repo_py_test")
dd_topt_py_test(
name = "pkg_py_test",
py_test_rule = repo_py_test,
runner_mode = "consumer_runner",
module_identifier = "example.python.pkg",
srcs = glob(["test_*.py"]),
deps = [
requirement("ddtrace"),
requirement("pytest"),
],
topt_data = topt_data,
)In consumer_runner mode, the repository-owned wrapper must preserve the
environment passed by dd_topt_py_test and must actually execute pytest with
the ddtrace plugin enabled. Do not set main to a test file just to satisfy
Bazel; that can produce a false-green target that never runs pytest.
For monorepos, put doctor/uploader in a lightweight package:
load("@datadog-rules-test-optimization//tools/core:test_optimization_targets.bzl", "dd_test_optimization_targets")
dd_test_optimization_targets(
name = "test_optimization",
sync_repo_name = "test_optimization_data",
expected_targets = [
"//python/pkg:pkg_py_test",
],
)Run package-local labels such as
//tools/test_optimization:dd_test_optimization_doctor and
//tools/test_optimization:dd_upload_payloads. Root labels are still valid for
small repositories.
Java WORKSPACE onboarding keeps ownership of Java rules, Java toolchains, test
framework dependencies, and the dd-java-agent artifact in the consumer
repository. The Datadog helper declares only the Java companion repository and
maps its internal @rules_java dependency to the repository name the consumer
already uses.
Declare rules_java with the version and mirror policy approved by the
consumer repository. Then declare the Datadog Java companion:
load("@datadog-rules-test-optimization//tools/java:workspace_repositories.bzl", "datadog_java_test_optimization_workspace_repositories")
datadog_java_test_optimization_workspace_repositories(
rto_commit = "<commit-sha>",
rules_java_repo_name = "rules_java",
)Internal/private consumers should use SSH git fetch when anonymous archives are not available:
git_repository(
name = "datadog-rules-test-optimization",
commit = "<commit-sha>",
remote = "ssh://git@github.com/DataDog/rules_test_optimization.git",
)Archive mode for mirrored Datadog repositories:
load("@datadog-rules-test-optimization//tools/java:workspace_repositories.bzl", "datadog_java_test_optimization_workspace_repositories")
datadog_java_test_optimization_workspace_repositories(
rto_commit = "",
datadog_fetch = "archive",
rules_java_repo_name = "rules_java",
rto_archive_url = "https://artifacts.example.internal/bazel-mirror/datadog/rules_test_optimization/<commit-sha>.tar.gz",
rto_archive_sha256 = "<sha256-for-archive>",
rto_archive_prefix = "rules_test_optimization-<commit-sha>",
)After the companion is available, load the macro from the Java companion repo:
load("@datadog-rules-test-optimization-java//:topt_java_test.bzl", "dd_topt_java_test")For Bzlmod single-service Go workspaces, prefer guided bootstrap instead. For
WORKSPACE consumers, prefer this helper over hand-written companion and
rules_go declarations. It keeps the Go companion repo mapping and the selected
Orchestrion-enabled rules_go variant consistent.
The helper assumes the core datadog-rules-test-optimization repository has
already been declared in step 1.
Default Git fetch mode:
load("@datadog-rules-test-optimization//tools/go:workspace_repositories.bzl", "datadog_go_test_optimization_workspace_repositories")
datadog_go_test_optimization_workspace_repositories(
rto_commit = "<commit-sha>",
rules_go_repo_name = "io_bazel_rules_go",
rules_go_variant = "base", # or "complete" for extended monorepo compatibility
)Archive mode for mirrored environments:
load("@datadog-rules-test-optimization//tools/go:workspace_repositories.bzl", "datadog_go_test_optimization_workspace_repositories")
datadog_go_test_optimization_workspace_repositories(
rto_commit = "<commit-sha>",
datadog_fetch = "archive",
rules_go_fetch = "archive",
rules_go_repo_name = "io_bazel_rules_go",
rules_go_variant = "complete",
rto_archive_url = "https://artifacts.example.internal/bazel-mirror/datadog/rules_test_optimization/<commit-sha>.tar.gz",
rto_archive_sha256 = "<sha256-for-archive>",
rto_archive_prefix = "rules_test_optimization-<commit-sha>",
)Supported helper combinations are git/git, git/archive, and
archive/archive. Use rules_go_variant = "base" for normal consumers and
rules_go_variant = "complete" for repositories that need the declared extended
monorepo compatibility layer. The helper never applies patches, patch_tool,
or patch_args; both variants are complete rules_go trees.
Then configure Go, Gazelle, and the Orchestrion tool repository:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "bazel_gazelle",
urls = [
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.39.1/bazel-gazelle-v0.39.1.tar.gz",
],
sha256 = "<bazel_gazelle_sha256>",
)
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
load("@io_bazel_rules_go//go:orchestrion_workspace.bzl", "go_orchestrion_tool_repo")
go_rules_dependencies()
go_register_toolchains(version = "1.25.0")
gazelle_dependencies()
go_orchestrion_tool_repo(
version = "<orchestrion_version>",
# Optional. When omitted, the helper uses the fork's current default
# shared dd-trace-go version.
dd_trace_go_version = "<resolved_dd_trace_go_version>",
)Notes for the helper:
versionis required in WORKSPACE mode.dd_trace_go_versionanddd_trace_go_versionsare mutually exclusive.- Keep the default tool-repo name
rules_go_orchestrion_tool; the current fork resolves that name internally. - Do not configure
patches,patch_tool, orpatch_argsfor this integration; choose the complete variant instead when the base variant is not enough.
Then in your Go package BUILD.bazel:
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@datadog-rules-test-optimization-go//:topt_go_test.bzl", "dd_topt_go_test")
load("@test_optimization_data//:export.bzl", "topt_data")
go_library(
name = "pkg_lib",
srcs = ["*.go"],
)
dd_topt_go_test(
name = "pkg_go_test",
srcs = ["*_test.go"],
embed = [":pkg_lib"], # Enables provider-based importpath inference
orchestrion_mode = "test_optimization",
topt_data = topt_data,
)Use orchestrion_mode = "test_optimization" for standard Go testing Test
Optimization. general remains the default mode for broader generic
Orchestrion behavior; the full mode contract is summarized in
Configuration_Reference.md.
The test_optimization mode keeps the stdlib testing instrumentation and
synthetic testmain support required for payloads while leaving customer
package compiles on the normal rules_go path. It does not automatically
instrument testify/suite.
If the tracer needs runtime-visible source files for AST-derived metadata such
as test.source.end, enable source staging explicitly:
dd_topt_go_test(
name = "pkg_go_test",
srcs = ["*_test.go"],
embed = [":pkg_lib"],
orchestrion_mode = "test_optimization",
stage_sources = True,
topt_data = topt_data,
)stage_sources stages only the target's direct srcs and direct
embedsrcs. When enabled, it changes the default rundir to . only if the
caller did not already set rundir.
Note: in WORKSPACE mode, Go support uses two repositories:
datadog-rules-test-optimizationfor the core rulesdatadog-rules-test-optimization-gofor the Go companion
The repository bound to @io_bazel_rules_go must be an Orchestrion-enabled
rules_go fork or a consumer-owned merge that includes the Orchestrion
workspace helper. Add repo_mapping = {"@rules_go": "@io_bazel_rules_go"} on
the datadog-rules-test-optimization-go repository declaration so the Go
companion resolves that fork consistently.
Also note that Orchestrion-backed Go tests expect the local Go module files to
be pinned consistently for instrumentation. dd_topt_go_test auto-stages
package-local pin files when they live next to the BUILD file, but nested test
packages should pass the module-root labels explicitly through
orchestrion_pin_files, for example:
dd_topt_go_test(
name = "pkg_go_test",
srcs = ["*_test.go"],
embed = [":pkg_lib"],
orchestrion_mode = "test_optimization",
orchestrion_pin_files = [
"//:go.mod",
"//:go.sum",
"//:orchestrion.tool.go",
"//:orchestrion.yml",
],
topt_data = topt_data,
)For pure test_optimization mode, go.mod plus go.sum are the required module
pins and orchestrion.yml is included when the repository uses one. A generic
Orchestrion setup may still keep orchestrion.tool.go; the optimized mode uses
a reduced synthetic tool file for action-time module work.