Skip to main content

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.

aspect gazelle runs Gazelle (or aspect_gazelle_prebuilt, for Starlark-defined extensions) to generate and synchronize your repository’s BUILD files. In CI it detects whether BUILD files are out of sync with source code and fails the step if so — preventing drift before it accumulates into a bigger cleanup. Running aspect gazelle locally applies fixes in place. Same command, different behavior based on context — --check-only defaults to true on CI and false locally.

Incremental mode: only touch changed directories

For large repos, running Gazelle over the entire tree on every PR is slow. --scope=changed (available when --scope-all-on-change patterns aren’t matched) restricts Gazelle to directories containing changed files:
aspect gazelle --scope=changed   # only dirs with PR-changed files
aspect gazelle --scope=all       # full workspace (default)
Smart escalation: certain file changes require a full-repo re-run. By default, changes to BUILD.bazel or MODULE.bazel escalate to --scope=all because those files can affect dependency resolution across the entire repo. Configure which patterns trigger escalation:
.aspect/config.axl
def config(ctx: ConfigContext):
    ctx.tasks["gazelle"].args.scope_all_on_change = [
        "BUILD.bazel",
        "MODULE.bazel",
        "go.sum",           # Go module changes require a full re-index
    ]

How drift detection works

aspect gazelle runs Gazelle with -mode=diff internally regardless of other flags. This is the key:
  1. Gazelle runs once with -mode=diff — it produces a unified diff without writing any files
  2. The task parses the diff to determine if BUILD files are out of sync (exit code from Gazelle isn’t reliable — the task uses stdout content)
  3. On CI (--check-only=true): if the diff is non-empty, the task exits 1
  4. Locally (--check-only=false): the task applies the diff via git apply -p0
Why single-run? Running Gazelle twice (once to detect, once to apply) would be expensive on a large monorepo. The diff-mode approach gets both the verdict and the patch from one Gazelle invocation. Applying the captured diff is much faster than a second Gazelle run.

Configuration

Gazelle target

aspect gazelle --gazelle-target=//tools/gazelle:gazelle
.aspect/config.axl
def config(ctx: ConfigContext):
    ctx.tasks["gazelle"].args.gazelle_target = "//tools/gazelle:gazelle"
Default: //tools/gazelle:gazelle.

Reacting to drift

aspect gazelle --on-change=fail    # default on CI
aspect gazelle --on-change=warn    # warn but don't block
aspect gazelle --on-change=silent  # detect-only, no output

Additional Gazelle flags

Pass extra flags to the Gazelle binary (any -mode flag is stripped internally since the task controls that):
aspect gazelle --gazelle-flag=-index=lazy //...
-index=lazy pairs well with --scope=changed for the best incremental performance: Gazelle only indexes the packages it visits rather than the whole repo.

Patch upload

.aspect/config.axl
def config(ctx: ConfigContext):
    ctx.tasks["gazelle"].args.upload_gazelle_diff = True
Uploads the BUILD diff as gazelle.patch when drift is detected, so developers can apply it locally.

CI examples

on:
  pull_request:
    branches: [main]

jobs:
  gazelle:
    runs-on: [self-hosted, aspect-workflows, aspect-default]
    permissions:
      id-token: write
    steps:
      - uses: actions/checkout@v6
      - uses: aspect-build/setup-aspect@c22a8f64fb38f82f59ce809cd7eb9f8ae096da44 # v2026.23.2
        with:
          aspect-api-token: ${{ secrets.ASPECT_API_TOKEN }}
      - run: aspect gazelle --task-key gazelle