Scope Defaults
Most dx commands take Bazel scopes. This page lists what each command does
with a scope.
No Scope Means //...
dx build,dx test,dx coverage,dx lint,dx typecheck,dx format,dx check,dx fix,dx security,dx license,dx migrate,dx list-tests
No Scope Means The Repository
dx generate: runs Gazelle over the whole repo.dx docs: builds//tools/docs/site:user_site, or//tools/docs/site:user_site_checkin--check.
Repository-Wide Or One Exact Label
dx env,dx codegen
Patterns, paths, and multiple labels are usage errors.
Set Selectors
dx update: set,set:package, label, or path selectors. No selector checks every set;--applywrites.dx bump: exactly oneset:packageplus one version.dx add: exactly one undeclaredset:packageplus one version.
Required Arguments
dx run: needs a runnable scope.dx deploy: exactly one main-workspace label.dx watch: needs a watchable command plus its scopes.dx new: needs a language, plus an optional name.dx init: optional module name.dx completion: exactly one shell.
No Scopes
dx clean,dx status,dx version,dx upgrade,dx rollback,dx worktree
Scope Shapes
- Labels and patterns:
//...,//pkg:target,@repo//.... - Files and dirs: workspace-relative paths, also under
bazel run. A file resolves through onebazel queryof the workspace rules to the rules that use it directly. Owners in other packages are included. External repos are not loaded. A dir becomes//dir/.... - Paths with control characters in a file or directory name are refused.
--here: the current directory tree, orBUILD_WORKING_DIRECTORYunderbazel run(//path/...,//...at the root). Never combines with explicit scopes. Accepted bydx build,dx test,dx coverage,dx lint,dx typecheck,dx format,dx generate,dx check,dx fix,dx security,dx license,dx list-tests, anddx docs.--affected: the targets your changes reach, described below. Never combines with explicit scopes or--here.- Targets that do not fit the target platform are skipped in
dx build,dx test,dx coverage,dx lint,dx typecheck,dx format,dx check, anddx fix, even when named, reached through files, or picked by--affected. Skipped tests report the outcomeskipped. Pass-- --noskip_incompatible_explicit_targetsto fail on them instead.dx runstill fails on them.
bazel run @rules_dx//:dx -- lint --here
bazel run @rules_dx//:dx -- build //cli/...
--affected
--affected selects only what your changes can reach. It is accepted by
dx build, dx test, dx coverage, dx list-tests, dx lint,
dx typecheck, dx format, dx check, dx fix, dx security, and
dx license. dx generate and dx docs reject --affected (usage error,
exit 2).
- Changes are the diff from the merge-base with the default branch
(
origin/HEAD, elseorigin/main,main,origin/master,master), plus staged, unstaged, and untracked files. A rename counts both paths. - When the workspace is a subdirectory of the Git repo, paths are relative to
the workspace and changes outside it are ignored. A change under a
local_path_overridepath outside the workspace widens to//.... - Each changed file maps to its owning targets, then to their reverse
dependencies inside
//.... Targets taggedmanualare left out. dx test,dx coverage, anddx list-testskeep only test targets.dx securityanddx licensekeep only targets a dependency set owns.dx check --affectedruns format, lint, typecheck, and generate as usual, then the affected tests.dx fix --affectedruns the same phases without tests and only reports fixes;dx fix --apply --affectedwrites them. Generate and its re-check run Gazelle on the directories of the affected targets.- A change to
MODULE.bazel,MODULE.bazel.lock,WORKSPACE,WORKSPACE.bazel,.bazelversion, any*.MODULE.bazelfile, or any.bazelrc*file, at any depth, widens the scope to//.... So does a file the root.bazelrcreaches throughimportortry-import %workspace%/..., including nested imports. Other*.bazelrcfiles do not widen. So does a file thatMODULE.bazelor an included segment names by label in an extension tag, repo rule, or override, such aspnpm-lock.yaml,go.modand itsgo.sum,maven_install.json,requirements_lock.txt, or a patch, and the included segment itself. Acrate.from_cargolockfile in an included segment counts as a lock input. When dx cannot read every value inMODULE.bazel, anypnpm-lock.yaml,package-lock.json,go.mod,go.sum,go.work,go.work.sum,maven_install.json, orrequirements_lock.txt, at any depth, widens to//.... A deleted, removed, or renamed-from file selects the targets that still name it. If no target names it, it widens to its package (for example//pkg:all) plus that package's reverse dependencies. A.bzlfile follows the.bzlrule below. An unowned file, or one outside any package, widens to the package tree around it, such as//pkg/.... - A changed
BUILDorBUILD.bazelfile selects every target in its package, plus its reverse dependencies. An addedBUILDfile widens to//...; a deleted one, or a deleted file outside any package, widens to//.... - A change to a
Cargo.lockor crate_universelockfilenamed by acrate.from_cargocall inMODULE.bazelselects the targets that use the changed crates, plus the crates that depend on them, and their reverse dependencies. Any other*.lockfile, an added or deleted lock, a lock dx cannot read, or a crate_universe lockfile change outsidecrateswidens to//.... A changed crate_universe manifest such asCargo.tomldoes not widen; it selects its owners like any other file. - A changed
.bzlor.sclfile selects the packages whose BUILD files load it, directly or through other.bzlfiles, plus their reverse dependencies. dx reads the BUILD and.bzlfiles to find them. Targets that own the file, such as abzl_library, are selected too. It widens to//...when the file is used by aMODULE.bazelextension or repo rule, by an aspect named in.bazelrcor one dx runs, or by the BUILD file of a toolchain or platform package. Those packages are the ones named byregister_toolchainsorregister_execution_platformsinMODULE.bazel, or by--extra_toolchains,--extra_execution_platforms,--platforms, or--host_platformin.bazelrc. It also widens to//...when a BUILD or.bzlfile does not parse. A.bzlor.sclfile nothing loads selects nothing. A deleted.bzlor.sclfile selects the packages that still load it, or nothing. - dx prints each widening and its reason on stderr:
dx: affected: 12 targets from 3 changed files since 1a2b3c4d5e6f; widened to //... (workspace input MODULE.bazel)ordx: affected: 4 targets from 1 changed files since 1a2b3c4d5e6f; widened to //app:all (loads tools/defs.bzl)ordx: affected: 4 targets from 1 changed files since 1a2b3c4d5e6f; widened to //app:all (build file app/BUILD.bazel). The line lists//...first and names at most three scopes, thenand N more, for exampledx: affected: 0 targets from 1 changed files since 1a2b3c4d5e6f; widened to //p0:all (loads q/f.bzl), //p1:all (loads q/f.bzl), //p2:all (loads q/f.bzl) and 477 more.--output=jsonlists every widened scope. - Before the queries run, dx prints
dx: affected: resolving changes since 1a2b3c4d5e6fon stderr, then the summary.--quiet,--output=diff, and--output=jsonprint neither. An empty selection prints no summary. - No changes, or no affected targets, prints
no affected targetson stdout and exits0.dx securityis the exception: when any file changed, it runs the secrets scan. With--output=jsonit emitscommand_started(withaffected) andcommand_finished;modeischeckfordx check, and fordx fix,lint,typecheckandformatunless--applyis given;dx build,test,coverage,list-tests,securityandlicensereportdefault. --affectedtakes no value. It never combines with explicit scopes or--here: both are usage errors with exit2.--output=jsonaddsaffectedto thecommand_startedevent:{"base": "<sha>", "changed_files": [...], "targets": [...], "tests": [...], "widened": [{"scope": "//...", "reason": "..."}]}.baseis the merge-base commit,targetsis the selection, andwidenedis empty when nothing widened. A changed.bzlfile adds one//pkg:allentry per loading package. A lock file change adds one entry per lock withrepos, the changed crates:{"scope": "rdeps(//..., @crates//:serde)", "reason": "changed crates in Cargo.lock", "repos": ["@crates//:serde"]}. With more than five crates the scope readsrdeps(//..., <n> repos).testsappears only fordx check --affected. It lists the tests the last phase runs://...when widened, empty when no test is affected. dx writescommand_startedonly after planning finishes.- A checkout without a default branch exits
2withcannot find the default branch: expected origin/HEAD, main, or master. - A shallow checkout exits
2withgit history is shallow: fetch full history with `git fetch --unshallow` or pass explicit scopes. - A failed
bazel queryexits2. Theerrorevent has codequery_failedand keeps Bazel's exit status and output excerpt. A query that cannot start has codequery_launch_failed. - dx runs at most one
bazel query,kind('rule', //...), to find the owning targets of the changed files and their reverse dependencies.dx test,dx coverage,dx list-tests, anddx checkthen run onetests(set(...))query to find the affected tests. A change that widens to//...skips the tests query. dx security --affectedruns the secrets scan whenever a file changed. When no dependency set owns a reached target, it checks no set and printsRunning audit security for no dependency sets. With no changes it printsno affected targets.
bazel run @rules_dx//:dx -- test --affected
bazel run @rules_dx//:dx -- check --affected --output=json