Install
To start using this module, make sure you have set up Bzlmod according to the user guide, and add the following to your MODULE.bazel
file:
Read the Release Notes
Version history
Dependency graph
Direct (16) at version 1.10.2
Dev Dependencies (1)
About
Run static analysis tools with Bazel
Tested on
Platforms
Bazel versions
Maintainers
Starlark API Documentation
//format:defs.bzl
Produce a multi-formatter that aggregates formatter tools.
Some formatter tools are built-in to rules_lint and may be installed by multitool.
These are noted in the attributes for each language in 'languages' below.
Note: Under --enable_bzlmod
, rules_lint installs multitool automatically.
WORKSPACE
users must install it manually; see the snippet on the releases page.
Other formatter binaries may be declared in your repository, typically in tools/format/BUILD.bazel
.
You can test that they work by running them directly, with bazel run -- //tools/format:some-tool
.
Then use the label //tools/format:some-tool
as the value of whatever language attribute in format_multirun
.
See the example/tools/format/BUILD file in this repo for full examples of declaring formatters.
Functions & Macros
format_multirun
Create a multirun binary for the given languages.
Intended to be used with bazel run
to update source files in-place.
This macro produces a target named [name].check
which does not edit files,
rather it exits non-zero if any sources require formatting.
To check formatting with bazel test
, use format_test instead.
Parameters
*name | name of the resulting target, typically "format" |
jobs | how many language formatters to spawn in parallel, ideally matching how many CPUs are available Default: 4 |
print_command | whether to print a progress message before calling the formatter of each language. Default: False |
disable_git_attribute_checks | Set to True to disable honoring .gitattributes filters Default: False |
kwargs | attributes named for each language; see languages. |
format_test
Create test for the given formatters.
Intended to be used with bazel test
to verify files are formatted.
This is not recommended, because it is either non-hermetic or requires listing all source files.
To format with bazel run
, see format_multirun.
Parameters
*name | name of the resulting target, typically "format" |
srcs | list of files to verify formatting. Required when no_sandbox is False. Default: None |
workspace | a file in the root directory to verify formatting. Required when no_sandbox is True. Default: None |
no_sandbox | Set to True to enable formatting all files in the workspace. Default: False |
disable_git_attribute_checks | Set to True to disable honoring .gitattributes filters Default: False |
tags | tags to apply to generated targets. In 'no_sandbox' mode, Default: [] |
kwargs | attributes named for each language; see languages. |
Rules
languages
Language attributes that may be passed to format_multirun or format_test.
Files with matching extensions from GitHub Linguist will be formatted for the given language.
Some languages have dialects:
- javascript
includes TypeScript, TSX, and JSON.
- css
includes Less and Sass.
Do not call the languages
rule directly, it exists only to document the attributes.
Attribute | Type | Description |
---|---|---|
*name | name | A unique name for this target. |
javascript | label | a Default: None |
markdown | label | a Default: None |
css | label | a Default: None |
graphql | label | a Default: None |
html | label | a Default: None |
python | label | a Default: None |
starlark | label | a Default: None |
jsonnet | label | a Default: None |
terraform | label | a Default: None |
toml | label | a Default: None |
kotlin | label | a Default: None |
java | label | a Default: None |
html_jinja | label | a Default: None |
scala | label | a Default: None |
swift | label | a Default: None |
go | label | a Default: None |
sql | label | a Default: None |
shell | label | a Default: None |
protocol_buffer | label | a Default: None |
c | label | a Default: None |
cc | label | a Default: None |
cuda | label | a Default: None |
yaml | label | a Default: None |
rust | label | a Default: None |
xml | label | a Default: None |
gherkin | label | a Default: None |
//format:repositories.bzl
Support repos that aren't on bazel central registry.
Needed until Bazel 7 allows MODULE.bazel to directly call repository rules.
Functions & Macros
http_archive
Parameters
kwargs |
http_file
Parameters
kwargs |
http_jar
Parameters
kwargs |
rules_lint_dependencies
fetch_java_format
fetch_ktfmt
fetch_swiftformat
//lint:buf.bzl
API for calling declaring a buf lint aspect.
Typical usage:
load("@aspect_rules_lint//lint:buf.bzl", "lint_buf_aspect")
buf = lint_buf_aspect(
config = Label("//path/to:buf.yaml"),
)
Important: while using buf's allow_comment_ignores
functionality, the bazel flag --experimental_proto_descriptor_sets_include_source_info
is required.
Functions & Macros
buf_lint_action
Runs the buf lint tool as a Bazel action.
Parameters
*ctx | Rule OR Aspect context |
*buf | the buf-lint executable |
*protoc | the protoc executable |
*target | the proto_library target to run on |
*stderr | output file containing the stderr of protoc |
exit_code | output file to write the exit code. Default: None |
lint_buf_aspect
A factory function to create a linter aspect.
Parameters
*config | label of the the buf.yaml file |
toolchain | override the default toolchain of the protoc-gen-buf-lint tool Default: "@rules_buf//tools/protoc-gen-buf-lint:toolchain_type" |
rule_kinds | which kinds of rules should be visited by the aspect Default: ["proto_library"] |
//lint:checkstyle.bzl
API for declaring a checkstyle lint aspect that visits java_library rules.
Typical usage:
First, call the fetch_checkstyle
helper in WORKSPACE
to download the jar file.
Alternatively you could use whatever you prefer for managing Java dependencies, such as a Maven integration rule.
Next, declare a binary target for it, typically in tools/lint/BUILD.bazel
:
java_binary( name = "checkstyle", main_class = "com.puppycrawl.tools.checkstyle.Main", runtime_deps = ["@com_puppycrawl_tools_checkstyle//jar"], )
Finally, declare an aspect for it, typically in tools/lint/linters.bzl
:
load("@aspect_rules_lint//lint:checkstyle.bzl", "lint_checkstyle_aspect") checkstyle = lint_checkstyle_aspect( binary = Label("//tools/lint:checkstyle"), config = Label("//:checkstyle.xml"), )
Functions & Macros
checkstyle_action
Run Checkstyle as an action under Bazel.
Parameters
*ctx | Bazel Rule or Aspect evaluation context |
*executable | label of the the Checkstyle program |
*srcs | java files to be linted |
*config | label of the checkstyle.xml file |
*data | labels of additional xml files such as suppressions.xml |
*stdout | output file to generate |
exit_code | output file to write the exit code. Default: None |
options | additional command-line options, see https://checkstyle.sourceforge.io/cmdline.html Default: [] |
lint_checkstyle_aspect
A factory function to create a linter aspect.
Attrs:
binary: a Checkstyle executable. Can be obtained from rules_java like so:
```
java_binary(
name = "checkstyle",
main_class = "com.puppycrawl.tools.checkstyle.Main",
# Point to wherever you have the java_import rule defined, see our example
runtime_deps = ["@com_puppycrawl_tools_checkstyle"],
)
```
config: the Checkstyle XML file
Parameters
*binary | |
*config | |
data | Default: [] |
rule_kinds | Default: ["java_binary", "java_library"] |
fetch_checkstyle
//lint:clang_tidy.bzl
API for calling declaring a clang-tidy lint aspect.
Typical usage:
First, install clang-tidy with llvm_toolchain or as a native binary (llvm_toolchain
does not support Windows as of 06/2024, but providing a native clang-tidy.exe works)
Next, declare a binary target for it, typically in tools/lint/BUILD.bazel
:
e.g. using llvm_toolchain:
native_binary( name = "clang_tidy", src = "@llvm_toolchain_llvm//:bin/clang-tidy" out = "clang_tidy", )
e.g as native binary:
native_binary( name = "clang_tidy", src = "clang-tidy.exe" out = "clang_tidy", )
Finally, create the linter aspect, typically in tools/lint/linters.bzl
:
load("@aspect_rules_lint//lint:clang_tidy.bzl", "lint_clang_tidy_aspect") clang_tidy = lint_clang_tidy_aspect( binary = Label("//path/to:clang-tidy"), configs = [Label("//path/to:.clang-tidy")], )
Functions & Macros
is_parent_in_list
Parameters
*dir | |
*list |
clang_tidy_action
Create a Bazel Action that spawns a clang-tidy process.
Adapter for wrapping Bazel around
https://clang.llvm.org/extra/clang-tidy/
Parameters
*ctx | an action context OR aspect context |
*compilation_context | from target |
*executable | struct with a clang-tidy field |
*srcs | file objects to lint |
*stdout | output file containing the stdout or --output-file of clang-tidy |
*exit_code | output file containing the exit code of clang-tidy. |
clang_tidy_fix
Create a Bazel Action that spawns clang-tidy with --fix.
Parameters
*ctx | an action context OR aspect context |
*compilation_context | from target |
*executable | struct with a clang_tidy field |
*srcs | list of file objects to lint |
*patch | output file containing the applied fixes that can be applied with the patch(1) command. |
*stdout | output file containing the stdout or --output-file of clang-tidy |
*exit_code | output file containing the exit code of clang-tidy |
lint_clang_tidy_aspect
A factory function to create a linter aspect.
Parameters
*binary | the clang-tidy binary, typically a rule like
|
configs | labels of the .clang-tidy files to make available to clang-tidy's config search. These may be Default: [] |
global_config | label of a single global .clang-tidy file to pass to clang-tidy on the command line. This Default: [] |
header_filter | optional, set to a posix regex to supply to clang-tidy with the -header-filter option Default: "" |
lint_target_headers | optional, set to True to pass a pattern that includes all headers with the target's Default: False |
angle_includes_are_system | controls how angle includes are passed to clang-tidy. By default, Bazel Default: True |
verbose | print debug messages including clang-tidy command lines being invoked. Default: False |
//lint:eslint.bzl
API for calling declaring an ESLint lint aspect.
Typical usage:
First, install eslint using your typical npm package.json and rules_js rules.
Next, declare a binary target for it, typically in tools/lint/BUILD.bazel
:
load("@npm//:eslint/package_json.bzl", eslint_bin = "bin") eslint_bin.eslint_binary(name = "eslint")
Finally, create the linter aspect, typically in tools/lint/linters.bzl
:
load("@aspect_rules_lint//lint:eslint.bzl", "lint_eslint_aspect") eslint = lint_eslint_aspect( binary = Label("//tools/lint:eslint"), # We trust that eslint will locate the correct configuration file for a given source file. # See https://eslint.org/docs/latest/use/configure/configuration-files#cascading-and-hierarchy configs = [ Label("//:eslintrc"), ... ], )
With ts_project <=3.2.0
Prior to [commit 5e25e91]https://github.com/aspect-build/rules_ts/commit/5e25e91420947e3a81938d8eb076803e5cf51fe2)
the rule produced by the ts_project
macro and a custom transpiler
expanded the macro to
multiple targets, including changing the default target to js_library
.
Since you want to lint the original TypeScript source files, the ts_project
rule produced
by the macro is the one you want to lint, so when used with an eslint_test
you should use
the [name]_typings
label:
ts_project(
name = "my_ts",
transpiler = swc,
...
)
eslint_test(
name = "lint_my_ts",
srcs = [":my_ts_typings"],
)
See the react example
Functions & Macros
eslint_action
Create a Bazel Action that spawns an eslint process.
Adapter for wrapping Bazel around
https://eslint.org/docs/latest/use/command-line-interface
Parameters
*ctx | an action context OR aspect context |
*executable | struct with an eslint field |
*srcs | list of file objects to lint |
*stdout | output file containing the stdout or --output-file of eslint |
exit_code | output file containing the exit code of eslint. Default: None |
format | value for eslint Default: "stylish" |
env | environment variables for eslint Default: {} |
eslint_fix
Create a Bazel Action that spawns eslint with --fix.
Parameters
*ctx | an action context OR aspect context |
*executable | struct with an eslint field |
*srcs | list of file objects to lint |
*patch | output file containing the applied fixes that can be applied with the patch(1) command. |
*stdout | output file containing the stdout or --output-file of eslint |
*exit_code | output file containing the exit code of eslint |
format | value for eslint Default: "stylish" |
env | environment variaables for eslint Default: {} |
lint_eslint_aspect
A factory function to create a linter aspect.
Parameters
*binary | the eslint binary, typically a rule like
|
*configs | label(s) of the eslint config file(s) |
rule_kinds | which kinds of rules should be visited by the aspect Default: ["js_library", "ts_project", "ts_project_rule"] |
//lint:flake8.bzl
API for declaring a flake8 lint aspect that visits py_library rules.
Typical usage:
First, fetch the flake8 package via your standard requirements file and pip calls.
Then, declare a binary target for it, typically in tools/lint/BUILD.bazel
:
load("@rules_python//python/entry_points:py_console_script_binary.bzl", "py_console_script_binary") py_console_script_binary( name = "flake8", pkg = "@pip//flake8:pkg", )
Finally, create the linter aspect, typically in tools/lint/linters.bzl
:
load("@aspect_rules_lint//lint:flake8.bzl", "lint_flake8_aspect") flake8 = lint_flake8_aspect( binary = Label("//tools/lint:flake8"), config = Label("//:.flake8"), )
Functions & Macros
flake8_action
Run flake8 as an action under Bazel.
Based on https://flake8.pycqa.org/en/latest/user/invocation.html
Parameters
*ctx | Bazel Rule or Aspect evaluation context |
*executable | label of the the flake8 program |
*srcs | python files to be linted |
*config | label of the flake8 config file (setup.cfg, tox.ini, or .flake8) |
*stdout | output file containing stdout of flake8 |
exit_code | output file containing exit code of flake8 Default: None |
options | additional command-line options, see https://flake8.pycqa.org/en/latest/user/options.html Default: [] |
lint_flake8_aspect
A factory function to create a linter aspect.
Attrs:
binary: a flake8 executable. Can be obtained from rules_python like so:
load("@rules_python//python/entry_points:py_console_script_binary.bzl", "py_console_script_binary")
py_console_script_binary(
name = "flake8",
pkg = "@pip//flake8:pkg",
)
config: the flake8 config file (`setup.cfg`, `tox.ini`, or `.flake8`)
Parameters
*binary | |
*config | |
rule_kinds | Default: ["py_binary", "py_library"] |
//lint:keep_sorted.bzl
API for declaring a keep-sorted lint aspect that visits all source files.
Typical usage:
First, fetch the keep-sorted dependency via gazelle. We provide a convenient go.mod file.
To keep it isolated from your other go dependencies, we recommend adding to .bazelrc:
common --experimental_isolated_extension_usages
Next add to MODULE.bazel:
keep_sorted_deps = use_extension("@gazelle//:extensions.bzl", "go_deps", isolate = True)
keep_sorted_deps.from_file(go_mod = "@aspect_rules_lint//lint/keep-sorted:go.mod")
use_repo(keep_sorted_deps, "com_github_google_keep_sorted")
Finally, create the linter aspect, typically in tools/lint/linters.bzl
:
load("@aspect_rules_lint//lint:keep_sorted.bzl", "lint_keep_sorted_aspect") keep_sorted = lint_keep_sorted_aspect( binary = Label("@com_github_google_keep_sorted//:keep-sorted"), )
Now you can add // keep-sorted start
/ // keep-sorted end
lines to your library sources,
following the documentation at https://github.com/google/keep-sorted#usage.
Functions & Macros
keep_sorted_action
Run keep-sorted as an action under Bazel.
Parameters
*ctx | Bazel Rule or Aspect evaluation context |
*executable | label of the the keep-sorted program |
*srcs | files to be linted |
*stdout | output file containing stdout |
exit_code | output file containing exit code Default: None |
options | additional command-line options Default: [] |
keep_sorted_fix
Parameters
*ctx | |
*executable | |
*srcs | |
*patch | |
*stdout | |
exit_code | Default: None |
options | Default: [] |
lint_keep_sorted_aspect
A factory function to create a linter aspect.
Parameters
*binary | a keep-sorted executable |
//lint:ktlint.bzl
API for calling declaring an ktlint lint aspect.
Typical usage:
Make sure you have ktlint
pulled as a dependency into your WORKSPACE/module by pulling a version of it from here
https://github.com/pinterest/ktlint/releases and using a http_file
declaration for it like.
http_file(
name = "com_github_pinterest_ktlint",
sha256 = "2e28cf46c27d38076bf63beeba0bdef6a845688d6c5dccd26505ce876094eb92",
url = "https://github.com/pinterest/ktlint/releases/download/1.2.1/ktlint",
executable = True,
)
Then, create the linter aspect, typically in tools/lint/linters.bzl
:
load("@aspect_rules_lint//lint:ktlint.bzl", "lint_ktlint_aspect") ktlint = lint_ktlint_aspect( binary = Label("@com_github_pinterest_ktlint//file"), # rules can be enabled/disabled from with this file editorconfig = Label("//:.editorconfig"), # a baseline file with exceptions for violations baseline_file = Label("//:.ktlint-baseline.xml"), )
If you plan on using Ktlint custom rulesets, you can also declare
an additional ruleset_jar
attribute pointing to your custom ruleset jar like this
java_binary(
name = "my_ktlint_custom_ruleset",
...
)
ktlint = lint_ktlint_aspect(
binary = Label("@com_github_pinterest_ktlint//file"),
# rules can be enabled/disabled from with this file
editorconfig = Label("//:.editorconfig"),
# a baseline file with exceptions for violations
baseline_file = Label("//:.ktlint-baseline.xml"),
# Run your custom ktlint ruleset on top of standard rules
ruleset_jar = Label("//:my_ktlint_custom_ruleset_deploy.jar"),
)
If your custom ruleset is a third-party dependency and not a first-party dependency, you can also fetch it using http_file
and use it instead.
Functions & Macros
ktlint_action
Runs ktlint as build action in Bazel.
Adapter for wrapping Bazel around
https://pinterest.github.io/ktlint/latest/install/cli/
Parameters
*ctx | an action context or aspect context |
*executable | struct with ktlint field |
*srcs | A list of source files to lint |
*editorconfig | The file object pointing to the editorconfig file used by ktlint |
*stdout | :output: the stdout of ktlint containing any violations found |
*baseline_file | The file object pointing to the baseline file used by ktlint. |
*java_runtime | The Java Runtime configured for this build, pulled from the registered toolchain. |
ruleset_jar | An optional, custom ktlint ruleset jar. Default: None |
exit_code | output file to write the exit code. Default: None |
options | additional command-line arguments to ktlint, see https://pinterest.github.io/ktlint/latest/install/cli/#miscellaneous-flags-and-commands Default: [] |
lint_ktlint_aspect
A factory function to create a linter aspect.
Parameters
*binary | a ktlint executable, provided as file typically through http_file declaration or using fetch_ktlint in your WORKSPACE. |
*editorconfig | The label of the file pointing to the .editorconfig file used by ktlint. |
*baseline_file | An optional attribute pointing to the label of the baseline file used by ktlint. |
ruleset_jar | An optional, custom ktlint ruleset provided as a fat jar, and works on top of the standard rules. Default: None |
rule_kinds | which kinds of rules should be visited by the aspect Default: ["kt_jvm_library", "kt_jvm_binary", "kt_js_library"] |
fetch_ktlint
//lint:lint_test.bzl
Factory function to make lint test rules.
When the linter exits non-zero, the test will print the output of the linter and then fail.
To use this, in your linters.bzl
where you define the aspect, just create a test that references it.
For example, with flake8
:
load("@aspect_rules_lint//lint:lint_test.bzl", "lint_test") load("@aspect_rules_lint//lint:flake8.bzl", "lint_flake8_aspect") flake8 = lint_flake8_aspect( binary = Label("//:flake8"), config = Label("//:.flake8"), ) flake8_test = lint_test(aspect = flake8)
Now in your BUILD files you can add a test:
load("//tools/lint:linters.bzl", "flake8_test") py_library( name = "unused_import", srcs = ["unused_import.py"], ) flake8_test( name = "flake8", srcs = [":unused_import"], )
Functions & Macros
lint_test
Parameters
*aspect |
//lint:pmd.bzl
API for declaring a PMD lint aspect that visits java_library rules.
Typical usage:
First, call the fetch_pmd
helper in WORKSPACE
to download the zip file.
Alternatively you could use whatever you prefer for managing Java dependencies, such as a Maven integration rule.
Next, declare a binary target for it, typically in tools/lint/BUILD.bazel
:
java_binary( name = "pmd", main_class = "net.sourceforge.pmd.PMD", runtime_deps = ["@net_sourceforge_pmd"], )
Finally, declare an aspect for it, typically in tools/lint/linters.bzl
:
load("@aspect_rules_lint//lint:pmd.bzl", "lint_pmd_aspect") pmd = lint_pmd_aspect( binary = Label("//tools/lint:pmd"), rulesets = [Label("//:pmd.xml")], )
Functions & Macros
pmd_action
Run PMD as an action under Bazel.
Based on https://docs.pmd-code.org/latest/pmd_userdocs_installation.html#running-pmd-via-command-line
Parameters
*ctx | Bazel Rule or Aspect evaluation context |
*executable | label of the the PMD program |
*srcs | java files to be linted |
*rulesets | list of labels of the PMD ruleset files |
*stdout | output file to generate |
exit_code | output file to write the exit code. Default: None |
options | additional command-line options, see https://pmd.github.io/pmd/pmd_userdocs_cli_reference.html Default: [] |
lint_pmd_aspect
A factory function to create a linter aspect.
Attrs:
binary: a PMD executable. Can be obtained from rules_java like so:
```
java_binary(
name = "pmd",
main_class = "net.sourceforge.pmd.PMD",
# Point to wherever you have the java_import rule defined, see our example
runtime_deps = ["@net_sourceforge_pmd"],
)
```
rulesets: the PMD ruleset XML files
Parameters
*binary | |
*rulesets | |
rule_kinds | Default: ["java_binary", "java_library"] |
fetch_pmd
//lint:pylint.bzl
API for declaring a pylint lint aspect that visits Python rules.
Typical usage:
First, fetch the pylint package via your standard requirements file and pip calls.
Then, declare a binary target for it, typically in tools/lint/BUILD.bazel
:
load("@rules_python//python/entry_points:py_console_script_binary.bzl", "py_console_script_binary") py_console_script_binary( name = "pylint", pkg = "@pip//pylint:pkg", )
Finally, create the linter aspect, typically in tools/lint/linters.bzl
:
load("@aspect_rules_lint//lint:pylint.bzl", "lint_pylint_aspect") pylint = lint_pylint_aspect( binary = Label("//tools/lint:pylint"), config = Label("//:.pylintrc"), )
Functions & Macros
pylint_action
Run pylint as an action under Bazel.
Based on https://pylint.readthedocs.io/en/stable/user_guide/run.html
Parameters
*ctx | Bazel Rule or Aspect evaluation context |
*executable | label of the pylint program |
*srcs | python files to be linted |
*config | label of the pylint config file (pyproject.toml, .pylintrc, or setup.cfg) |
*stdout | output file containing stdout of pylint |
exit_code | output file containing exit code of pylint Default: None |
options | additional command-line options Default: [] |
lint_pylint_aspect
A factory function to create a linter aspect.
Attrs:
binary: a pylint executable. Can be obtained from rules_python like so:
load("@rules_python//python/entry_points:py_console_script_binary.bzl", "py_console_script_binary")
py_console_script_binary(
name = "pylint",
pkg = "@pip//pylint:pkg",
)
config: the pylint config file (`pyproject.toml`, `pylintrc`, or `.pylintrc`)
rule_kinds: which [kinds](https://bazel.build/query/language#kind) of rules should be visited by the aspect
filegroup_tags: filegroups tagged with these tags will also be visited by the aspect
Parameters
*binary | |
*config | |
rule_kinds | Default: ["py_binary", "py_library", "py_test"] |
filegroup_tags | Default: ["python", "lint-with-pylint"] |
//lint:ruff_versions.bzl
This file is automatically updated by mirror_ruff.sh
//lint:ruff.bzl
API for declaring a Ruff lint aspect that visits py_{binary|library|test} rules.
Typical usage:
Ruff is provided as a built-in tool by rules_lint. To use the built-in version,
create the linter aspect, typically in tools/lint/linters.bzl
:
load("@aspect_rules_lint//lint:ruff.bzl", "lint_ruff_aspect") ruff = lint_ruff_aspect( binary = Label("@aspect_rules_lint//lint:ruff_bin", configs = [Label("//:.ruff.toml")], )
Using a specific ruff version
In WORKSPACE
, fetch the desired version from https://github.com/astral-sh/ruff/releases
load("@aspect_rules_lint//lint:ruff.bzl", "fetch_ruff") # Specify a tag from the ruff repository fetch_ruff("v0.4.10")
In tools/lint/BUILD.bazel
, select the tool for the host platform:
# Note: this won't interact properly with the --platform flag, see # https://github.com/aspect-build/rules_lint/issues/389 alias( name = "ruff", actual = select({ "@bazel_tools//src/conditions:linux_x86_64": "@ruff_x86_64-unknown-linux-gnu//:ruff", "@bazel_tools//src/conditions:linux_aarch64": "@ruff_aarch64-unknown-linux-gnu//:ruff", "@bazel_tools//src/conditions:darwin_arm64": "@ruff_aarch64-apple-darwin//:ruff", "@bazel_tools//src/conditions:darwin_x86_64": "@ruff_x86_64-apple-darwin//:ruff", "@bazel_tools//src/conditions:windows_x64": "@ruff_x86_64-pc-windows-msvc//:ruff.exe", }), )
Finally, reference this tool alias rather than the one from @multitool
:
ruff = lint_ruff_aspect( binary = "@@//tools/lint:ruff", ... )
Functions & Macros
ruff_action
Run ruff as an action under Bazel.
Ruff will select the configuration file to use for each source file, as documented here:
https://docs.astral.sh/ruff/configuration/#config-file-discovery
Note: all config files are passed to the action.
This means that a change to any config file invalidates the action cache entries for ALL
ruff actions.
However this is needed because:
- ruff has an
extend
field, so it may need to read more than one config file - ruff's logic for selecting the appropriate config needs to read the file content to detect
a[tool.ruff]
section.
Parameters
*ctx | Bazel Rule or Aspect evaluation context |
*executable | label of the the ruff program |
*srcs | python files to be linted |
*config | labels of ruff config files (pyproject.toml, ruff.toml, or .ruff.toml) |
*stdout | output file of linter results to generate |
exit_code | output file to write the exit code. Default: None |
env | environment variaables for ruff Default: {} |
ruff_fix
Create a Bazel Action that spawns ruff with --fix.
Parameters
*ctx | an action context OR aspect context |
*executable | struct with _ruff and _patcher field |
*srcs | list of file objects to lint |
*config | labels of ruff config files (pyproject.toml, ruff.toml, or .ruff.toml) |
*patch | output file containing the applied fixes that can be applied with the patch(1) command. |
*stdout | output file of linter results to generate |
*exit_code | output file to write the exit code |
env | environment variaables for ruff Default: {} |
lint_ruff_aspect
A factory function to create a linter aspect.
Attrs:
binary: a ruff executable
configs: ruff config file(s) (pyproject.toml
, ruff.toml
, or .ruff.toml
)
rule_kinds: which kinds of rules should be visited by the aspect
filegroup_tags: filegroups tagged with these tags will be visited by the aspect in addition to Python rule kinds
Parameters
*binary | |
*configs | |
rule_kinds | Default: ["py_binary", "py_library", "py_test"] |
filegroup_tags | Default: ["python", "lint-with-ruff"] |
fetch_ruff
A repository macro used from WORKSPACE to fetch ruff binaries.
Allows the user to select a particular ruff version, rather than get whatever is pinned in the multitool.lock.json
file.
Parameters
*tag | a tag of ruff that we have mirrored, e.g. |
Repository Rules
ruff_workaround_20269
Workaround for https://github.com/bazelbuild/bazel/issues/20269
Attribute | Type | Description |
---|---|---|
*name | name | A unique name for this repository. |
repo_mapping | dictionary: String → String | In For example, an entry This attribute is not supported in |
build_file_content | string | Default: "" |
sha256 | string | Default: "" |
strip_prefix | string | unlike http_archive, any value causes us to pass --strip-components=1 to tar Default: "" |
url | string | Default: "" |
//lint:shellcheck.bzl
API for declaring a shellcheck lint aspect that visits sh_{binary|library|test} rules.
Typical usage:
Shellcheck is provided as a built-in tool by rules_lint. To use the built-in version,
create the linter aspect, typically in tools/lint/linters.bzl
:
load("@aspect_rules_lint//lint:shellcheck.bzl", "lint_shellcheck_aspect") shellcheck = lint_shellcheck_aspect( binary = Label("@aspect_rules_lint//lint:shellcheck_bin", config = Label("//:.shellcheckrc"), )
Functions & Macros
shellcheck_action
Run shellcheck as an action under Bazel.
Based on https://github.com/koalaman/shellcheck/blob/master/shellcheck.1.md
Parameters
*ctx | Bazel Rule or Aspect evaluation context |
*executable | label of the the shellcheck program |
*srcs | bash files to be linted |
*config | label of the .shellcheckrc file |
*stdout | output file containing stdout of shellcheck |
exit_code | output file containing shellcheck exit code. Default: None |
options | additional command-line options, see https://github.com/koalaman/shellcheck/blob/master/shellcheck.hs#L95 Default: [] |
lint_shellcheck_aspect
A factory function to create a linter aspect.
Attrs:
binary: a shellcheck executable.
config: the .shellcheckrc file
Parameters
*binary | |
*config | |
rule_kinds | Default: ["sh_binary", "sh_library", "sh_test"] |
//lint:spotbugs.bzl
API for declaring a spotbugs lint aspect that visits java_library and java_binary rules.
Typical usage:
First, call the fetch_spotbugs
helper in WORKSPACE
to download the jar file.
Alternatively you could use whatever you prefer for managing Java dependencies, such as a Maven integration rule.
Next, declare a binary target for it, typically in tools/lint/BUILD.bazel
:
java_binary( name = "spotbugs", main_class = "edu.umd.cs.findbugs.LaunchAppropriateUI", runtime_deps = [ "@spotbugs//:jar", ], )
Finally, declare an aspect for it, typically in tools/lint/linters.bzl
:
load("@aspect_rules_lint//lint:spotbugs.bzl", "lint_spotbugs_aspect") spotbugs = lint_spotbugs_aspect( binary = Label("//tools/lint:spotbugs"), exclude_filter = Label("//:spotbugs-exclude.xml"), )
Functions & Macros
spotbugs_action
Run Spotbugs as an action under Bazel.
Based on https://spotbugs.readthedocs.io/en/latest/index.html
Parameters
*ctx | Bazel Rule or Aspect evaluation context |
*executable | label of the the Spotbugs program |
*srcs | jar to be linted |
*target | target to be linted |
*exclude_filter | label of the spotbugs-exclude.xml file |
*stdout | output file to generate |
exit_code | output file to write the exit code. Default: None |
options | additional command-line options, see https://spotbugs.readthedocs.io/en/latest/running.html#command-line-options Default: [] |
lint_spotbugs_aspect
Parameters
*binary | |
*exclude_filter | |
rule_kinds | Default: ["java_library", "java_binary", "java_test"] |
fetch_spotbugs
//lint:stylelint.bzl
Configures Stylelint to run as a Bazel aspect
First, all CSS sources must be the srcs of some Bazel rule.
You can use a filegroup
with lint-with-stylelint
in the tags
:
filegroup( name = "css", srcs = glob(["*.css"]), tags = ["lint-with-stylelint"], )
See the filegroup_tags
and rule_kinds
attributes below to customize this behavior.
Usage
Add stylelint
as a devDependency
in your package.json
, and declare a binary target for Bazel to execute it.
For example in tools/lint/BUILD.bazel
:
load("@npm//:stylelint/package_json.bzl", stylelint_bin = "bin") stylelint_bin.stylelint_binary(name = "stylelint")
Then declare the linter aspect, typically in tools/lint/linters.bzl
:
load("@aspect_rules_lint//lint:stylelint.bzl", "lint_stylelint_aspect") stylelint = lint_stylelint_aspect( binary = Label("//tools/lint:stylelint"), config = Label("//:stylelintrc"), )
Finally, register the aspect with your linting workflow, such as in .aspect/cli/config.yaml
for aspect lint
.
Functions & Macros
stylelint_action
Spawn stylelint as a Bazel action
Parameters
*ctx | an action context OR aspect context |
*executable | struct with an _stylelint field |
*srcs | list of file objects to lint |
*stderr | output file containing the stderr or --output-file of stylelint |
exit_code | output file containing the exit code of stylelint. Default: None |
env | environment variables for stylelint Default: {} |
options | additional command-line arguments Default: [] |
format | a formatter to add as a command line argument Default: None |
stylelint_fix
Create a Bazel Action that spawns stylelint with --fix.
Parameters
*ctx | an action context OR aspect context |
*executable | struct with a _stylelint field |
*srcs | list of file objects to lint |
*patch | output file containing the applied fixes that can be applied with the patch(1) command. |
*stderr | output file containing the stderr or --output-file of stylelint |
*exit_code | output file containing the exit code of stylelint |
env | environment variables for stylelint Default: {} |
options | additional command line options Default: [] |
lint_stylelint_aspect
A factory function to create a linter aspect.
Parameters
*binary | the stylelint binary, typically a rule like
|
*config | label(s) of the stylelint config file |
rule_kinds | which kinds of rules should be visited by the aspect Default: ["css_library"] |
filegroup_tags | which tags on a Default: ["lint-with-stylelint"] |
//lint:vale_library.bzl
Vale styles library
Vendored from https://raw.githubusercontent.com/errata-ai/styles/master/library.json
Then the url fields are converted from latest to a format string, and sha256sums added.
Functions & Macros
fetch_styles
//lint:vale_versions.bzl
This file is automatically updated by mirror_vale.sh
//lint:vale.bzl
API for declaring a Vale lint aspect that visits markdown files.
First, all markdown sources must be the srcs of some Bazel rule.
Either use a filegroup
with markdown
in the tags
:
filegroup( name = "md", srcs = glob(["*.md"]), tags = ["markdown"], )
or use a markdown_library
rule such as the one in https://github.com/dwtj/dwtj_rules_markdown.
Aspect plans to provide support for Markdown in configure so these rules can be automatically
maintained rather than requiring developers to write them by hand.
Note that any Markdown files in the repo which aren't in the srcs
of one of these rules will not
be linted by Vale.
Styles
Vale is powered by Styles.
There is a built-in style and if this is
sufficient then it's not necessary to follow the rest of this section.
The styles from https://vale.sh/hub/ are already fetched by fetch_vale()
which has a Bazel-based
mirror of https://github.com/errata-ai/packages/blob/master/library.json.
It's possible to fetch more styles using a typical http_archive()
call.
At runtime, Vale requires the styles are "installed" into a folder together.
Use the copy_to_directory
rule to accomplish this, for example,
copy_to_directory( name = "vale_styles", srcs = ["@vale_write-good//:write-good"], include_external_repositories = ["vale_*"], )
Note that the .vale.ini
file may have a StylesPath
entry.
Under Bazel, we set VALE_STYLES_PATH
in the environment, so the StylesPath
is used
only when running Vale outside Bazel, such as in an editor extension.
See the example in rules_lint for a fully-working vale setup.
Usage
load("@aspect_rules_lint//lint:vale.bzl", "lint_vale_aspect") vale = lint_vale_aspect( binary = Label("//tools/lint:vale"), # A copy_to_bin rule that places the .vale.ini file into bazel-bin config = Label("//:.vale_ini"), # Optional. # A copy_to_directory rule that "installs" custom styles together into a single folder styles = Label("//tools/lint:vale_styles"), )
Functions & Macros
vale_action
Run Vale as an action under Bazel.
Parameters
*ctx | Bazel Rule or Aspect evaluation context |
*executable | label of the the Vale program |
*srcs | markdown files to be linted |
*styles | a directory containing vale extensions, following https://vale.sh/docs/topics/styles/ |
*config | label of the .vale.ini file, see https://vale.sh/docs/vale-cli/structure/#valeini |
*stdout | output file containing stdout of Vale |
exit_code | output file containing Vale exit code. Default: None |
output | the value for the --output flag Default: "CLI" |
env | environment variables for vale Default: {} |
lint_vale_aspect
A factory function to create a linter aspect.
Parameters
*binary | |
*config | |
styles | Default: Label("//lint:empty_styles") |
rule_kinds | Default: ["markdown_library"] |
filegroup_tags | Default: ["markdown", "lint-with-vale"] |
fetch_vale
A repository macro used from WORKSPACE to fetch vale binaries
Parameters
tag | a tag of vale that we have mirrored, e.g. Default: "v3.7.0" |
//lint:yamllint.bzl
Configures yamllint to run as a Bazel aspect.
Typical usage:
Create an executable target for yamllint, for example in tools/lint/BUILD.bazel
:
load("@rules_python//python/entry_points:py_console_script_binary.bzl", "py_console_script_binary") py_console_script_binary( name = "yamllint", pkg = "@pip//yamllint:pkg", )
Then declare the linter aspect, typically in tools/lint/linters.bzl
:
load("@aspect_rules_lint//lint:yamllint.bzl", "lint_yamllint_aspect") yamllint = lint_yamllint_aspect( binary = Label("//tools/lint:yamllint"), config = Label("//:.yamllint"), )
Finally, opt YAML sources into linting by tagging a filegroup
with lint-with-yamllint
, or by
providing a custom rule_kinds
list that matches your YAML rules.
Functions & Macros
yamllint_action
Run yamllint as an action under Bazel.
Parameters
*ctx | Bazel Rule or Aspect evaluation context |
*executable | File representing the yamllint program |
*srcs | YAML files to lint |
*config | yamllint configuration file |
*stdout | output file for yamllint stdout |
exit_code | optional output file for exit code. If absent, non-zero exits fail the build. Default: None |
format | optional formatter passed via Default: None |
options | additional command-line options Default: [] |
lint_yamllint_aspect
Create a yamllint aspect.
Parameters
*binary | |
*config | |
rule_kinds | Default: ["yaml_library"] |
filegroup_tags | Default: ["lint-with-yamllint"] |
extra_args | Default: [] |