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.

This is the per-task migration guide for aspect lint. See Migrating from legacy YAML-configured tasks for shared setup (CLI version pinning, the recommended two-step migration path, top-level workspaces:).
The legacy Rosetta lint task ran bazel lint with environment-specific flags injected automatically, parsed a proprietary JSON diagnostics file, and posted GitHub annotations directly from the task runner. aspect lint replaces it. aspect lint runs a standard Bazel build with rules_lint aspects enabled, reads SARIF output, and exposes lifecycle hooks for custom reporting.
GitHub PR annotations are no longer baked into the task — they are posted by the GithubLintComments feature, which authenticates via the Aspect Workflows GitHub App and is enabled by default on GitHub Actions.

What changed

AreaYAML-configured tasksAspect CLI tasks
Invocationbazel lint (legacy Aspect CLI command); aspects configured in .aspect/cli/config.yaml (lint.aspects:)aspect lint; aspects configured per-invocation via --aspect=//tools/lint:linters.bzl%eslint (repeatable) or in .aspect/config.axl (ctx.tasks["lint"].args.aspects = […])
Diagnostics formatProprietary JSON (--lint_diagnostics_file)SARIF (via rules_lint_machine output group)
GitHub annotationsBuilt into the taskGithubLintComments feature via the Aspect Workflows app (on by default)
Configuration.aspect/workflows/config.yaml task blockconfig.axl / CLI flags
Failure strategyfailure_strategy string--strategy CLI flag
DeduplicationBuilt-in (highest severity wins)Handled by rules_lint
Annotation / comment limit25 annotations, 10 suggestionsNo built-in limit; GithubLintComments enforces its own per-PR cap (configurable via --github-lint-comments:max-pr-comments)
Fix application--fix via task configaspect lint --fix
Diff basegit diff HEAD^..HEADGitHub PR Files API (with the Aspect Workflows app authenticated) or git diff against the merge-base of HEAD and --base-ref (default origin/main)
Workspacesworkspaces: top-level list (one or more directories)cd <dir> in your CI config; run aspect lint from there

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 lint --strategy=hard //...). 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 every aspect lint invocation picks it up. Good for settings that should apply to all invocations of a task type. AXL also lets you compute values programmatically (e.g. branching on CI host or environment), which is more expressive than shell logic wrapped around CLI flags.
Pick whichever fits — you only need one. Where both work, the sections below show them side-by-side under After.

Lint aspects (--aspect)

In the legacy Aspect CLI, the bazel lint command picked up its rules_lint aspects from the lint.aspects list in .aspect/cli/config.yaml:
lint:
  aspects:
    - //tools/lint:linters.bzl%buf
    - //tools/lint:linters.bzl%eslint
    - //tools/lint:linters.bzl%vale
    - //tools/lint:linters.bzl%tfsec
aspect lint makes the aspect list explicit at the task site. At least one --aspect=<label> is required; repeat the flag to run multiple aspects in a single invocation. Each --aspect=<label> becomes a Bazel --aspects=<label> on the underlying build. Recommended: declare aspects in .aspect/config.axl so the same aspect lint invocation runs the same aspects locally as in CI. Your CI step doesn’t need to enumerate the aspect list at all, and developers running aspect lint //... on their machines pick up the exact same set:
.aspect/config.axl
def config(ctx: ConfigContext):
    ctx.tasks["lint"].args.aspects = [
        "//tools/lint:linters.bzl%buf",
        "//tools/lint:linters.bzl%eslint",
        "//tools/lint:linters.bzl%vale",
        "//tools/lint:linters.bzl%tfsec",
    ]
The CLI flag is also fine — useful for one-off invocations, parallel CI jobs that need different aspect sets, or experimenting with a new linter before committing it:
aspect lint \
  --aspect=//tools/lint:linters.bzl%buf \
  --aspect=//tools/lint:linters.bzl%eslint \
  --aspect=//tools/lint:linters.bzl%vale \
  --aspect=//tools/lint:linters.bzl%tfsec \
  //...
CLI flags override .aspect/config.axl defaults, so a job that wants only the fast linters can pass --aspect=//tools/lint:linters.bzl%shellcheck and skip the rest. linters.bzl defines the aspects via rules_lint helpers (e.g. lint_shellcheck_aspect, lint_eslint_aspect). See the rules_lint setup docs for the canonical pattern, or the aspect-cli lint example for a minimal working setup.

Failure strategy

Before.aspect/workflows/config.yaml:
tasks:
  lint:
    failure_strategy: hold_the_line   # or: soft, hard
After — CLI flag or config.axl:
aspect lint --strategy=hold-the-line   # default
aspect lint --strategy=hard
aspect lint --strategy=soft
Strategy reference:
Legacy failure_strategyNew --strategyBehavior
hold_the_line (default)hold-the-line (default)Fail only on error-severity diagnostics in changed files. “Changed” comes from the GitHub PR Files API on PR builds, or git diff against the merge-base of HEAD and --base-ref (default origin/main) on local/non-PR builds.
hardhardFail on any error-severity diagnostic across all linted files; also fails if a linter exits non-zero
softsoftNever fail; diagnostics are surfaced but do not affect exit code

Lint targets

Before.aspect/workflows/config.yaml:
tasks:
  lint:
    targets:
      - //services/...
      - //libs/...
After — positional CLI args or config.axl:
aspect lint --aspect=//tools/lint:linters.bzl%eslint //services/... //libs/...
The default (no arguments) is ... — expands to all rule targets in the package at and beneath your current directory. To lint the entire workspace explicitly, run aspect lint //... from the repo root (equivalent to the legacy targets: ['//...']).

GitHub PR review comments

On GitHub Actions, the GithubLintComments feature posts lint findings to PRs as inline review comments. It is enabled by default, so no extra configuration is needed beyond authenticating the runner (see Authentication below). What it does:
  • Posts inline review comments on the lines of the PR diff that the linter flagged.
  • Includes fix suggestions as GitHub suggestion blocks where the linter provides them, so reviewers can apply the fix with one click.
  • Deduplicates comments across re-runs of the lint task on the same PR, and cleans up stale ones once a violation is fixed.
With the Aspect Workflows app authenticated on a PR build, GithubLintComments uses the GitHub PR Files API for exact per-line changed regions — more accurate than any local git diff. Outside a PR or without authentication, it falls back to git diff against the merge-base of HEAD and --base-ref (default origin/main); override with --merge-base=<sha> to skip the merge-base resolution.

Authentication

GithubLintComments needs:
  • ASPECT_API_TOKEN exposed to the runner.
  • The Aspect Workflows GitHub App (also known as Marvin) installed on the GitHub org/repository and linked to your Aspect account, so the CLI can use the App to post the review comments.
See Authenticating the Aspect CLI for the full setup walkthrough — installing the app, linking the installation, and generating the API token. When the workflow is running on a GitHub Actions PR but authentication is missing or misconfigured, the CLI logs one GitHub lint comments: authentication failed for <owner>/<repo> — <reason> line per aspect lint invocation and the run continues normally. The reason explains what’s missing and includes a link to the setup guide, for example:
GitHub lint comments: authentication failed for acme/widgets — no Aspect credentials — set ASPECT_API_TOKEN (client_id:secret) in the job env. Setup guide: https://docs.aspect.build/cli/authentication
Outside a GitHub Actions PR run (push events, non-GitHub CI, local development) the feature has nothing to post to and stays silent.

Disabling

aspect lint --github-lint-comments:enabled=false //...

CI integration examples

Post comments

Run aspect lint on pull requests so GithubLintComments can post annotations as review comments.
name: Lint

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

jobs:
  lint:
    runs-on: [self-hosted, aspect-workflows, aspect-default]
    permissions:
      id-token: write   # ArtifactUpload uses the runner's OIDC token to call the GitHub Actions artifact API
    env:
      ASPECT_API_TOKEN: ${{ secrets.ASPECT_API_TOKEN }}
    steps:
      - uses: actions/checkout@v6
      - name: Lint
        run: aspect lint --task-key lint //...

Auto commit fixes

Run aspect lint --fix on feature branches and push the resulting diff back so developers don’t have to re-run locally. Each platform needs a push credential with write access to the branch.
jobs:
  lint:
    runs-on: [self-hosted, aspect-workflows, aspect-default]
    permissions:
      id-token: write
    env:
      ASPECT_API_TOKEN: ${{ secrets.ASPECT_API_TOKEN }}
    steps:
      - uses: actions/checkout@v6
      - name: Lint with fix
        run: aspect lint --fix --task-key lint //...
      - name: Commit fixes
        uses: stefanzweifel/git-auto-commit-action@v5
        with:
          commit_message: "lint: apply automatic fixes"