dx check, dx fix, And dx clean
bazel run @rules_dx//:dx -- check //...
bazel run @rules_dx//:dx -- fix //...
bazel run @rules_dx//:dx -- clean
dx check And dx fix
dx check [--here] [--affected] [--check] [--fail-on info|warning|error] [--report sarif=<dest>] [scope...] [-- bazel-options...]
dx fix [--here] [--affected] [--check] [--apply] [--fail-on info|warning|error] [--report sarif=<dest>] [scope...] [-- bazel-options...]
Before any phase, dx check and dx fix fail when your change adds build
output: a new file under target/, bazel-*, node_modules/, __pycache__/,
.gradle/, or a build/ directory outside a source tree, or a file over
1 MiB. The error names each file and exits 1.
- Your change is untracked unignored files, staged and unstaged edits, and
commits since the merge base with the default branch (
origin/HEAD,origin/main,main,origin/master,master). - Ignored files never count.
- A file that already exists at the merge base is only checked for size.
- List a path or a
dir/prefix you want to keep in.dx-large-files, one per line. Listed paths skip both rules. - Symlinks and Git LFS files are skipped.
- With no default branch or merge base (a shallow clone), only the working
tree is checked. In text output
dxprints a note on stderr. - Outside a Git checkout the check is skipped.
- If Git fails, the command exits
2with codebuild_output_git_failed.
Runs format, then lint, then typecheck, then generate in order.
--affected limits the first three to targets your git changes reach (see
Scope Defaults), runs generate on the packages of those
targets, or on the whole repo when the scope widens to //..., and makes
dx check run the affected tests as a last test phase. It skips that phase when no test is affected. With
--output=json, affected.tests on command_started lists the tests dx
chose. With nothing affected, dx check --affected and dx fix --affected
run no phase, generate included, and skip the build-output check. They print
no affected targets and exit 0. With --output=json they emit only
command_started (with affected) and command_finished; mode is check
unless --apply is given. Affected targets that do not fit the host platform
are skipped.
Every phase, including test, passes the same Bazel settings:
--@rules_dx//config:validate=false, --@rules_dx//config:clippy_output_diagnostics=true
and --@rules_dx//config:rustc_output_diagnostics=true. Another value for one of them,
or for the matching @rules_rust//rust/settings flag, fails before Bazel starts with exit 2.
dx spells them with the name your MODULE.bazel gives rules_dx, for example
--@my_dx//config:validate=false when repo_name = "my_dx".
--check passes through to every phase. --fail-on applies to format,
lint, and typecheck. --report sarif=<dest> merges the lint and
typecheck phases into one document. generate and test take neither. A
relative destination anchors at the workspace root; an absolute one writes as
given. Colliding destinations fail before anything runs, parents must exist,
and a failed write keeps the previous file bytes. dx check is always a check,
so --check is implied. - for stdout is rejected because the phases share
one document.
dx check and dx fix run every phase. A phase with findings or drift, a
failed build or tool, a target that does not converge, incomplete results, or
a report that cannot be written does not stop the next phase, so one run
reports every phase. The run still exits nonzero, and a later clean phase
never clears it. The run stops, and marks the remaining phases skipped, only
on a bad scope or configuration, when Bazel cannot run (it fails to launch, is
killed by a signal, or the disk is full), or on a cancel. A phase whose only
failures are compile errors does not stop dx check, but it stops dx fix,
generate included: the remaining phases are skipped with
<phase> skipped after <phase> failed to compile. The skipped phases are named
in the JSON umbrella_phase_skipped notice events. In text output, a run with a failed
phase ends with a dx: phases: line on stderr that says how each phase ended.
Every phase that ran and owed a capture must leave a readable SARIF document
behind. A missing, unreadable, or malformed capture is a collection_failed
error: the run fails and the report is marked incomplete. Findings from the
phases that did land are still merged. The written line names every phase
that failed, was skipped, or lost its capture.
A phase that fails still keeps the findings it wrote: its SARIF is merged and
the report is marked incomplete. A phase that only reports findings leaves the
report complete. The run exits with the code of the phase that stopped it, or
of the first failed phase, even when the report cannot be written. A
failed phase that wrote nothing adds no collection_failed error.
Output: --output text|diff|json. JSON keeps one command_started and one
command_finished for the run. Each phase sits between a phase_started and
a phase_finished, and its events carry command, phase, and a
correlation such as check/format. dx fix --apply verification phases use
verify/<phase>. A verify/<phase> that writes events dx cannot read adds a
correlated collection_failed error and fails the run. A phase that reported findings adds a correlated notice
(umbrella_phase_findings), a skipped phase adds a correlated notice
(umbrella_phase_skipped), and a capture the run could not collect adds a
correlated error. --include-edits adds full edits to JSON change events
and needs --output json.
Findings keep the tool's labels, notes, help, and related locations. Text
prints them under the finding, JSON adds an ordered related list, and SARIF
adds relatedLocations. They are never counted as findings or applied as
edits.
SARIF results carry partialFingerprints (dx/v1), ruleIndex, and fixes for machine-applicable replacements. Runs set columnKind to unicodeCodePoints.
dx check only reports. dx fix checks by default; dx fix --apply
writes validated fixes, then re-checks read-only every phase up to the last
one that changed or refused a file. The re-check runs only when every phase
passed. When no phase changed anything, no re-check runs. dx fix --apply succeeds only when that re-check passes;
remaining findings, a target that did not converge, or a failed verification
stay visible and fail the run.
When a phase finds changes, text prints
N file(s) need changes. Apply them with: dx fix --apply ... with the scope
you passed, --affected included. next: lines name dx check or dx fix
with that scope.
Exit codes: 0 success, 2 usage or scope errors, 1 a phase failed or
reported findings, a capture could not be collected, the post-apply
verification failed, or a report could not be written. A phase that stopped
the run keeps its code, so a generate phase keeps Bazel's code. Otherwise the
first failed phase sets the code.
The test phase also keeps Bazel's code. 3 with every test result collected
means some affected tests failed: the run counts that as findings and its
results are complete. 3 or 1 with results incomplete is an incomplete
phase, not findings: the reason is test failed and the results are
incomplete. Results are incomplete when the build failed, a result has no
test.xml, a test.xml is missing, truncated or invalid, Bazel announces a
result it never reports, a target has a summary but no result, or the build
events end before Bazel's last event. 2 and 4 mean the scope selected no
runnable tests.
bazel run @rules_dx//:dx -- check //...
bazel run @rules_dx//:dx -- fix --here
bazel run @rules_dx//:dx -- check --affected
bazel run @rules_dx//:dx -- fix --apply //...
dx clean
dx clean [--check] [--apply] [--prune-unobserved]
Reports unselected managed state under .dx by default and deletes
nothing. --check is that default: it reports and deletes nothing. Pass --apply to prune it. A generation a live reader still
holds is never pruned. When process observation is unavailable, dx keeps
unobserved state and reports it; pass --prune-unobserved to prune it
anyway; this never overrides a held lease. Never touches Bazel outputs; run bazel clean for those. Takes no scopes.
Output: --output text|json. --quiet silences text output.
Text, check mode, when something can be pruned or is preserved:
dx clean: reclaimable managed stateprocess observation unavailable: unobserved state is preserved, never assumed idleprune setup record: .dx/setups/<hex> (<n> bytes)prune generation: .dx/<environments|generated>/<hex> (<n> bytes)preserve current: .dx/setups/<hex>, orno current selectionpreserve unobserved setup record: .dx/setups/<hex>andpreserve unobserved generation: .dx/<environments|generated>/<hex>refuse unmanaged path: <path>reclaimable total: <n> bytesrun `dx clean --apply` to prune it, orrun `dx clean --apply --prune-unobserved` to prune it anywaywhen only preserved state is listed
When nothing can be pruned or preserved it prints dx clean: nothing to prune.
Text, --apply: dx clean: pruned <n> setup records and <m> generations (<b> bytes reclaimed), followed by ; preserved <k> leased generations
when a live reader holds one. When process observation is unavailable it
prints dx clean: preserved <n> unobserved setup records and <m> unobserved generations (process observation unavailable) and
run `dx clean --apply --prune-unobserved` to prune it anyway. With
nothing to prune it prints dx clean: nothing to prune.
JSON: command_started has mode check, or default with --apply.
Then one operation event, collect. Then one info notice per path.
Each notice has a path under .dx/ and the byte size in message:
clean_planned: would be pruned. Check mode.clean_preserved_unobserved: kept because process observation is unavailable. Check mode and--apply, when process observation is unavailable.clean_pruned: pruned.--apply.clean_preserved_leased: kept because a live reader holds it.--apply.
A failure emits an error event with code clean_failed.
command_finished ends the stream.
Exit codes: 0 success, 2 usage errors including any scope,
1 drift or a prune failure. State kept only because process observation
is unavailable exits 0.
bazel run @rules_dx//:dx -- clean --check
bazel run @rules_dx//:dx -- clean --apply
bazel run @rules_dx//:dx -- clean --apply --prune-unobserved