1# Buildifier
2
3buildifier is a tool for formatting bazel BUILD and .bzl files with a standard convention.
4
5## Setup
6
7Build the tool:
8* Checkout the repo and then either via `go install` or `bazel build //buildifier`
9* If you already have 'go' installed, then build a binary via:
10
11`go install github.com/bazelbuild/buildtools/buildifier@latest`
12
13## Usage
14
15Use buildifier to create standardized formatting for BUILD and .bzl files in the
16same way that clang-format is used for source files.
17
18 $ buildifier path/to/file
19
20You can also process multiple files at once:
21
22 $ buildifier path/to/file1 path/to/file2
23
24You can make buildifier automatically find all Starlark files (i.e. BUILD, WORKSPACE, .bzl, or .sky)
25in a directory recursively:
26
27 $ buildifier -r path/to/dir
28
29Buildifier supports the following file types: `BUILD`, `WORKSPACE`, `.bzl`, and
30default, the latter is reserved for Starlark files buildifier doesn't know about
31(e.g. configuration files for third-party projects that use Starlark). The
32formatting rules for WORKSPACE files are the same as for BUILD files (both are
33declarative and have stricter formatting rules), and default files are formatted
34similarly to .bzl files, allowing more flexibility. Different linter warnings
35may be limited to any subset of these file types, e.g. a certain warning may be
36only relevant to Bazel files (i.e. `BUILD`, `WORKSPACE`, and `.bzl`) or to
37non-WORKSPACE files.
38
39Buildifier automatically detects the file type by its filename, taking into
40account optional prefixes and suffixes, e.g. `BUILD`, `BUILD.oss`, or
41`BUILD.bazel` will be detected as BUILD files, and `build_defs.bzl.oss` is a
42.bzl file. Files with unknown names (e.g. `foo.bar`) or files passed via stdin
43will be treated as default file type. To override the automatic file type
44detection use the `--type` flag explicitly:
45
46 $ cat foo.bar | buildifier --type=build
47 $ cat foo.bar | buildifier --type=bzl
48 $ cat foo.bar | buildifier --type=workspace
49 $ cat foo.bar | buildifier --type=default
50 $ cat foo.bar | buildifier --type=module
51
52## Linter
53
54Buildifier has an integrated linter that can point out and in some cases
55automatically fix various issues. To use it launch one of the following commands
56to show and to fix the issues correspondingly (note that some issues cannot be
57fixed automatically):
58
59 buildifier --lint=warn path/to/file
60 buildifier --lint=fix path/to/file
61
62By default, the linter searches for all known issues relevant for the given
63file type except those that are marked with
64"[Disabled by default](../WARNINGS.md)" in the documentation.
65
66You can specify the categories using the `--warnings` flag either by providing
67the categories explicitly:
68
69 buildifier --lint=warn --warnings=positional-args,duplicated-name
70
71or by modifying the default warnings set by using `+` or `-` modifiers before
72each warning category:
73
74 buildifier --lint=warn --warnings=-positional-args,+unsorted-dict-items
75
76It's also possible to provide `--warnings=all` to use all supported warnings
77categories (they will still be limited to relevant warnings for the given file
78type).
79
80See also the [full list](../WARNINGS.md) or the supported warnings.
81
82## Setup and usage via Bazel
83
84You can also invoke buildifier via the Bazel rule.
85`WORKSPACE` file:
86```bzl
87load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
88
89# buildifier is written in Go and hence needs rules_go to be built.
90# See https://github.com/bazelbuild/rules_go for the up to date setup instructions.
91http_archive(
92 name = "io_bazel_rules_go",
93 sha256 = "6dc2da7ab4cf5d7bfc7c949776b1b7c733f05e56edc4bcd9022bb249d2e2a996",
94 urls = [
95 "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.39.1/rules_go-v0.39.1.zip",
96 "https://github.com/bazelbuild/rules_go/releases/download/v0.39.1/rules_go-v0.39.1.zip",
97 ],
98)
99
100load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies")
101
102go_rules_dependencies()
103
104load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains")
105
106go_register_toolchains(version = "1.20.3")
107
108http_archive(
109 name = "bazel_gazelle",
110 sha256 = "727f3e4edd96ea20c29e8c2ca9e8d2af724d8c7778e7923a854b2c80952bc405",
111 urls = [
112 "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.30.0/bazel-gazelle-v0.30.0.tar.gz",
113 "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.30.0/bazel-gazelle-v0.30.0.tar.gz",
114 ],
115)
116
117load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
118
119# If you use WORKSPACE.bazel, use the following line instead of the bare gazelle_dependencies():
120# gazelle_dependencies(go_repository_default_config = "@//:WORKSPACE.bazel")
121gazelle_dependencies()
122
123http_archive(
124 name = "com_google_protobuf",
125 sha256 = "3bd7828aa5af4b13b99c191e8b1e884ebfa9ad371b0ce264605d347f135d2568",
126 strip_prefix = "protobuf-3.19.4",
127 urls = [
128 "https://github.com/protocolbuffers/protobuf/archive/v3.19.4.tar.gz",
129 ],
130)
131
132load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
133
134protobuf_deps()
135
136http_archive(
137 name = "com_github_bazelbuild_buildtools",
138 sha256 = "ae34c344514e08c23e90da0e2d6cb700fcd28e80c02e23e4d5715dddcb42f7b3",
139 strip_prefix = "buildtools-4.2.2",
140 urls = [
141 "https://github.com/bazelbuild/buildtools/archive/refs/tags/4.2.2.tar.gz",
142 ],
143)
144```
145
146`BUILD.bazel` typically in the workspace root:
147```bzl
148load("@com_github_bazelbuild_buildtools//buildifier:def.bzl", "buildifier")
149
150buildifier(
151 name = "buildifier",
152)
153```
154Invoke with
155```bash
156bazel run //:buildifier
157```
158
159## File diagnostics in json
160
161Buildifier supports diagnostics output in machine-readable format (json), triggered by
162`--format=json` (only works in combination with `--mode=check`). If used in combination with `-v`,
163the output json will be indented for better readability.
164
165The output format is the following:
166
167```jsonc
168{
169 "success": false, // true if all files are formatted and generate no warnings, false otherwise
170 "files": [ // list of all files processed by buildifier
171 {
172 "filename": "file_1.bzl",
173 "formatted": true, // whether the file is correctly formatted
174 "valid": true, // whether the file is a valid Starlark file. Can only be false if formatted = false
175 "warnings": [ // a list of warnings
176 {
177 "start": {
178 "line": 1,
179 "column": 5
180 },
181 "end": {
182 "line": 1,
183 "column": 10
184 },
185 "category": "integer-division",
186 "actionable": true,
187 "autoFixable": true,
188 "message": "The \"/\" operator for integer division is deprecated in favor of \"//\".",
189 "url": "https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md#integer-division"
190 }
191 ]
192 },
193 {
194 "filename": "file_2.bzl",
195 "formatted": false,
196 "valid": true,
197 "warnings": [],
198 "rewrites": { // technical information, a list of rewrites buildifier applies during reformatting
199 "editoctal": 1
200 }
201 },
202 {
203 "filename": "file_3.bzl",
204 "formatted": true,
205 "valid": true,
206 "warnings": []
207 },
208 {
209 "filename": "file_4.not_bzl",
210 "formatted": false,
211 "valid": false,
212 "warnings": []
213 }
214 ]
215}
216```
217
218When the `--format` flag is provided, buildifier always returns `0` unless there are internal
219failures or wrong input parameters, this means the output can be parsed as JSON, and its `success`
220field should be used to determine whether the diagnostics result is positive.
View as plain text