Documentation Index
Fetch the complete documentation index at: https://docs.aspect.build/llms.txt
Use this file to discover all available pages before exploring further.
This is the per-task migration guide for
aspect format. See Migrating from legacy YAML-configured tasks for shared setup (CLI version pinning, the recommended two-step migration path, top-level workspaces:).format task ran a rules_lint format_multirun target against changed files, archived a diff, and surfaced an annotation if the formatter modified anything. aspect format replaces it.
aspect format builds your formatter target, determines the changed file set, and runs the formatter against it. Formatters edit files in place, so a non-zero git status after the run signals that formatting was required. Whether to fail the CI step on that condition is up to your CI script.
What changed
| Area | YAML-configured tasks | Aspect CLI tasks |
|---|---|---|
| Invocation | bazel format (legacy Aspect CLI command) | aspect format |
| Formatter target | target: (default //:format) | --formatter-target (default //tools/format:format) |
| Scope | format_changed: true formats changed files only | --scope=changed (default) formats changed files only; pass --scope=all for every file the formatter handles |
| Changed-file detection | Local git diff-tree / git diff-index against the head commit, with a GitHub PR Files API fallback | GitHub PR Files API when in a PR + authenticated; otherwise local git diff <merge-base> |
| Detection | Checked git diff after the formatter to detect “formatting required” | aspect format snapshots the tree pre-run via git stash create, then diffs against that snapshot — non-destructive, robust to pre-existing dirty state |
| Diff archival | Archived to artifacts, plus a CI annotation pointing to it | --upload-format-diff (off by default) uploads the patch as a CI artifact via the same uploader build/test use; download URL is recorded on ArtifactsTrait.artifact_urls["format_diff"] |
| Soft-fail | soft_fail: true downgraded the failure to a warning | --soft-fail (off by default) — same semantics: WARNING + exit 0 instead of failure. The formatter binary’s own non-zero exit still fails the task regardless |
| Workspaces | respect_workspaces: true filtered changed files to the current workspace | --ignore-pattern='nested/**' (or in .aspect/config.axl) filters nested Bazel workspaces. Combine with cd <dir> in CI when you want different formatter targets per workspace |
| Ignore patterns | ignore_patterns: [glob, …] excluded matching files from the diff outcome | --ignore-pattern (repeatable) — same effect, plus also drops the matched files from the formatter’s input in changed-files mode so it never runs on them. Pattern syntax: *, **, ?; case-sensitive |
Configuration migration
Many of the settings below can be applied in either of two ways:- CLI flag — pass the flag at invocation time (e.g.
aspect format --scope=all //...). Good for overrides on individual task invocations, or experimenting with a setting before committing it. .aspect/config.axl— declare it once in your repo’s AXL config so everyaspect formatinvocation picks it up. Good for settings that should apply to all invocations of a task type.
Formatter target
Before —.aspect/workflows/config.yaml:
config.axl (only needed if your formatter target isn’t at the new default //tools/format:format):
The default formatter target moved from
//:format to //tools/format:format. Putting format_multirun in a sibling package keeps its load(...) out of your root BUILD.bazel — loads in the root package fire on every invocation that touches it (any wildcard, query, or rule that resolves a root-package label), so keeping format-only machinery out of that path saves fetch and analysis overhead on commands that have nothing to do with formatting.If your formatter still lives at the root, set --formatter-target=//:format (or pin it in config.axl). Repos that already have their formatter at //tools/format:format don’t need to set the flag at all.Scope: changed files vs. the whole tree
Before —.aspect/workflows/config.yaml:
--scope=all to run on every file the formatter handles:
aspect format detects changed files in this order:
- GitHub PR Files API — when running on a PR (any CI host) with the Aspect Workflows GitHub App authenticated. Most accurate.
- Local
git diff <merge-base>— fallback. Defaults to--base-ref=origin/main; override with--base-refor pass an explicit--merge-base=<sha>.
Detection: when does aspect format decide formatting is required?
Most rules_lint formatters rewrite files in place and exit 0 even when they made changes. So “did the formatter exit non-zero?” isn’t a useful signal. aspect format instead takes a tree snapshot before running the formatter, then diffs against that snapshot afterward:
git stash create is non-destructive — it writes a commit object to the object store and returns its SHA without touching the working tree, the index, or the stash list. As a result, the detection works correctly on a dirty local clone: any pre-existing changes are absorbed into the snapshot and don’t false-positive as “formatter modified”.
Soft-fail
Before —.aspect/workflows/config.yaml:
--soft-fail (default false):
--soft-fail is set and the formatter modified files, the task prints a WARNING listing the affected files and exits 0. Useful for teams introducing automated formatting incrementally so the CI step doesn’t block merges. The formatter binary’s own non-zero exit (e.g. config error) still fails the task regardless.
Diff archival
Before —.aspect/workflows/config.yaml: the legacy task auto-archived format.diff as a CI artifact and pointed an annotation at it.
After — --upload-format-diff (default false):
format.patch via the same uploader build/test use for testlogs. Works on GitHub Actions, Buildkite, CircleCI, and GitLab. The download URL (where the CI provider returns one) lands on ArtifactsTrait.artifact_urls["format_diff"] so future status-check features can link to it.
No-op when the working tree is clean post-format, or when not running on a recognized CI host.
Ignore patterns / workspace awareness
The legacyignore_patterns: [glob, …] excluded matching files from the diff outcome; respect_workspaces: true filtered changed files to the current Bazel workspace. Both map to --ignore-pattern in the new task:
* (one segment), ** (zero or more segments), ? (one char). Patterns are case-sensitive and matched against repo-relative file paths.
In --scope=changed (default), ignored paths are dropped from the file list passed to the formatter, so it never runs on them.
In --scope=all, the formatter walks the tree itself, so ignored files may still be rewritten on disk; ignored paths are excluded only from the post-format diff used to decide whether the task fails. The legacy format task had the same constraint — ignore_patterns filtered the failure-decision diff but couldn’t stop the formatter from rewriting files it discovered itself — so this isn’t a regression. If you need a hard guarantee the formatter never touches a directory in --scope=all, configure exclusion at the formatter level too (most rules_lint helpers accept include/exclude lists).
The “nested Bazel workspace” case (where
aspect format from the parent would otherwise stomp the child’s files) is a common motivator for --ignore-pattern. List each nested workspace’s directory and the parent’s formatter leaves them untouched.Examples
Standard format check on PRs
Before —.aspect/workflows/config.yaml:
Soft-fail (annotate but don’t fail)
For teams introducing automated formatting incrementally, downgrade the failure to a warning so the CI step doesn’t block merges:Format the whole tree (--scope=all)
Useful for nightly maintenance jobs or when bringing a new formatter into a repo for the first time:
Archive the diff as a CI artifact (--upload-format-diff)
--upload-format-diff writes the formatter’s patch to a tmpfile and uploads it as format.patch via the same uploader build/test use, so reviewers can apply it locally without re-running the formatter:
ArtifactsTrait.artifact_urls["format_diff"] for downstream status-check or annotation features to surface.
