github.com/bazelbuild/bazel-gazelle@v0.36.1-0.20240520142334-61b277ba6fed/internal/go_repository.bzl (about) 1 # Copyright 2014 The Bazel Authors. All rights reserved. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 15 load("@bazel_tools//tools/build_defs/repo:utils.bzl", "patch", "read_user_netrc", "use_netrc") 16 load("//internal:common.bzl", "env_execute", "executable_extension") 17 load("//internal:go_repository_cache.bzl", "read_cache_env") 18 19 _DOC = """ 20 `go_repository` downloads a Go project and generates build files with Gazelle 21 if they are not already present. This is the simplest way to depend on 22 external Go projects. 23 24 When `go_repository` is in module mode, it saves downloaded modules in a shared, 25 internal cache within Bazel's cache. It may be cleared with `bazel clean --expunge`. 26 By setting the environment variable `GO_REPOSITORY_USE_HOST_CACHE=1`, you can 27 force `go_repository` to use the module cache on the host system in the location 28 returned by `go env GOPATH`. Alternatively, by setting the environment variable 29 `GO_REPOSITORY_USE_HOST_MODCACHE=1`, you can force `go_repository` to use only 30 the module cache on the host system in the location returned by `go env GOMODCACHE`. 31 32 **Example** 33 34 ```starlark 35 load("@bazel_gazelle//:deps.bzl", "go_repository") 36 37 # Download using "go mod download" 38 go_repository( 39 name = "com_github_pkg_errors", 40 importpath = "github.com/pkg/errors", 41 sum = "h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=", 42 version = "v0.8.1", 43 ) 44 45 # Download automatically via git 46 go_repository( 47 name = "com_github_pkg_errors", 48 commit = "816c9085562cd7ee03e7f8188a1cfd942858cded", 49 importpath = "github.com/pkg/errors", 50 ) 51 52 # Download from git fork 53 go_repository( 54 name = "com_github_pkg_errors", 55 commit = "816c9085562cd7ee03e7f8188a1cfd942858cded", 56 importpath = "github.com/pkg/errors", 57 remote = "https://example.com/fork/github.com/pkg/errors", 58 vcs = "git", 59 ) 60 61 # Download via HTTP 62 go_repository( 63 name = "com_github_pkg_errors", 64 importpath = "github.com/pkg/errors", 65 urls = ["https://codeload.github.com/pkg/errors/zip/816c9085562cd7ee03e7f8188a1cfd942858cded"], 66 strip_prefix = "errors-816c9085562cd7ee03e7f8188a1cfd942858cded", 67 type = "zip", 68 ) 69 70 # Download major version suffixed via git 71 go_repository( 72 name = "com_github_thediveo_enumflag_v2", 73 commit = "0217df583bf3d37b92798602e5061b36556bcd38", 74 importpath = "github.com/thediveo/enumflag/v2", 75 remote = "https://github.com/thediveo/enumflag", 76 vcs = "git", 77 ) 78 ``` 79 80 """ 81 82 # copied from 83 # https://github.com/bazelbuild/bazel/blob/d273cb62f43ef8169415cf60fc96e503ea2ad823/tools/build_defs/repo/http.bzl#L76 84 _AUTH_PATTERN_DOC = """An optional dict mapping host names to custom authorization patterns. 85 86 If a URL's host name is present in this dict the value will be used as a pattern when 87 generating the authorization header for the http request. This enables the use of custom 88 authorization schemes used in a lot of common cloud storage providers. 89 90 The pattern currently supports 2 tokens: <code><login></code> and 91 <code><password></code>, which are replaced with their equivalent value 92 in the netrc file for the same host name. After formatting, the result is set 93 as the value for the <code>Authorization</code> field of the HTTP request. 94 95 Example attribute and netrc for a http download to an oauth2 enabled API using a bearer token: 96 97 <pre> 98 auth_patterns = { 99 "storage.cloudprovider.com": "Bearer <password>" 100 } 101 </pre> 102 103 netrc: 104 105 <pre> 106 machine storage.cloudprovider.com 107 password RANDOM-TOKEN 108 </pre> 109 110 The final HTTP request would have the following header: 111 112 <pre> 113 Authorization: Bearer RANDOM-TOKEN 114 </pre> 115 """ 116 117 # We can't disable timeouts on Bazel, but we can set them to large values. 118 _GO_REPOSITORY_TIMEOUT = 86400 119 120 def _go_repository_impl(ctx): 121 # TODO(#549): vcs repositories are not cached and still need to be fetched. 122 # Download the repository or module. 123 fetch_repo_args = None 124 gazelle_path = None 125 126 # Declare Label dependencies at the top of function to avoid unnecessary fetching: 127 # https://docs.bazel.build/versions/main/skylark/repository_rules.html#when-is-the-implementation-function-executed 128 go_env_cache = str(ctx.path(Label("@bazel_gazelle_go_repository_cache//:go.env"))) 129 if not ctx.attr.urls: 130 fetch_repo = str(ctx.path(Label("@bazel_gazelle_go_repository_tools//:bin/fetch_repo{}".format(executable_extension(ctx))))) 131 generate = ctx.attr.build_file_generation == "on" 132 _gazelle = "@bazel_gazelle_go_repository_tools//:bin/gazelle{}".format(executable_extension(ctx)) 133 if generate: 134 gazelle_path = ctx.path(Label(_gazelle)) 135 136 if ctx.attr.local_path: 137 pass 138 elif ctx.attr.urls: 139 # HTTP mode 140 for key in ("commit", "tag", "vcs", "remote", "version", "sum", "replace"): 141 if getattr(ctx.attr, key): 142 fail("cannot specifiy both urls and %s" % key, key) 143 result = ctx.download_and_extract( 144 url = ctx.attr.urls, 145 sha256 = ctx.attr.sha256, 146 canonical_id = ctx.attr.canonical_id, 147 stripPrefix = ctx.attr.strip_prefix, 148 type = ctx.attr.type, 149 auth = use_netrc(read_user_netrc(ctx), ctx.attr.urls, ctx.attr.auth_patterns), 150 ) 151 if not ctx.attr.sha256: 152 print("For Go module \"{path}\", integrity not specified, calculated sha256 = \"{sha256}\"".format( 153 path = ctx.attr.importpath, 154 sha256 = result.sha256, 155 )) 156 elif ctx.attr.commit or ctx.attr.tag: 157 # repository mode 158 if ctx.attr.commit: 159 rev = ctx.attr.commit 160 rev_key = "commit" 161 elif ctx.attr.tag: 162 rev = ctx.attr.tag 163 rev_key = "tag" 164 for key in ("urls", "strip_prefix", "type", "sha256", "version", "sum", "replace", "canonical_id"): 165 if getattr(ctx.attr, key): 166 fail("cannot specify both %s and %s" % (rev_key, key), key) 167 168 if ctx.attr.vcs and not ctx.attr.remote: 169 fail("if vcs is specified, remote must also be") 170 171 fetch_repo_args = ["-dest", ctx.path(""), "-importpath", ctx.attr.importpath] 172 if ctx.attr.remote: 173 fetch_repo_args.extend(["--remote", ctx.attr.remote]) 174 if rev: 175 fetch_repo_args.extend(["--rev", rev]) 176 if ctx.attr.vcs: 177 fetch_repo_args.extend(["--vcs", ctx.attr.vcs]) 178 elif ctx.attr.version: 179 # module mode 180 for key in ("urls", "strip_prefix", "type", "sha256", "commit", "tag", "vcs", "remote"): 181 if getattr(ctx.attr, key): 182 fail("cannot specify both version and %s" % key) 183 if ctx.attr.version and not ctx.attr.sum: 184 fail("if version is specified, sum must also be") 185 186 fetch_path = ctx.attr.replace if ctx.attr.replace else ctx.attr.importpath 187 fetch_repo_args = [ 188 "-dest=" + str(ctx.path("")), 189 "-importpath=" + fetch_path, 190 "-version=" + ctx.attr.version, 191 "-sum=" + ctx.attr.sum, 192 ] 193 else: 194 fail("one of urls, commit, tag, or version must be specified") 195 196 env = read_cache_env(ctx, go_env_cache) 197 env_keys = [ 198 # keep sorted 199 200 # Respect user proxy and sumdb settings for privacy. 201 # TODO(jayconrod): gazelle in go_repository mode should probably 202 # not go out to the network at all. This means *the build* 203 # goes out to the network. We tolerate this for downloading 204 # archives, but finding module roots is a bit much. 205 "GONOPROXY", 206 "GONOSUMDB", 207 "GOPRIVATE", 208 "GOPROXY", 209 "GOSUMDB", 210 211 # PATH is needed to locate git and other vcs tools. 212 "PATH", 213 214 # HOME is needed to locate vcs configuration files (.gitconfig). 215 "HOME", 216 217 # Settings below are used by vcs tools. 218 "GIT_CONFIG", 219 "GIT_CONFIG_COUNT", 220 "GIT_CONFIG_GLOBAL", 221 "GIT_CONFIG_NOSYSTEM", 222 "GIT_CONFIG_SYSTEM", 223 "GIT_SSH", 224 "GIT_SSH_COMMAND", 225 "GIT_SSL_CAINFO", 226 "HTTPS_PROXY", 227 "HTTP_PROXY", 228 "NO_PROXY", 229 "SSH_AUTH_SOCK", 230 "SSL_CERT_DIR", 231 "SSL_CERT_FILE", 232 "http_proxy", 233 "https_proxy", 234 "no_proxy", 235 ] 236 237 # Git allows passing configuration through environmental variables, this will be picked 238 # by go get properly: https://www.git-scm.com/docs/git-config/#Documentation/git-config.txt-GITCONFIGCOUNT 239 if "GIT_CONFIG_COUNT" in ctx.os.environ: 240 count = ctx.os.environ["GIT_CONFIG_COUNT"] 241 if count: 242 if not count.isdigit or int(count) < 1: 243 fail("GIT_CONFIG_COUNT has to be a positive integer") 244 count = int(count) 245 for i in range(count): 246 key = "GIT_CONFIG_KEY_%d" % i 247 value = "GIT_CONFIG_VALUE_%d" % i 248 for j in [key, value]: 249 if j not in ctx.os.environ: 250 fail("%s is not defined as an environment variable, but you asked for GIT_COUNT_COUNT=%d" % (j, count)) 251 env_keys = env_keys + [key, value] 252 253 env.update({k: ctx.os.environ[k] for k in env_keys if k in ctx.os.environ}) 254 255 if ctx.attr.local_path: 256 local_path_env = dict(env) 257 local_path_env["GOSUMDB"] = "off" 258 259 # Override external GO111MODULE, because it is needed by module mode, no-op in repository mode 260 local_path_env["GO111MODULE"] = "on" 261 262 if hasattr(ctx, "watch_tree"): 263 # https://github.com/bazelbuild/bazel/commit/fffa0affebbacf1961a97ef7cd248be64487d480 264 ctx.watch_tree(ctx.attr.local_path) 265 else: 266 print(""" 267 WARNING: go.mod replace directives to module paths is only supported in bazel 7.1.0-rc1 or later, 268 Because of this changes to %s will not be detected by your version of Bazel.""" % ctx.attr.local_path) 269 270 command = [fetch_repo, "--path", ctx.attr.local_path, "--dest", ctx.path("")] 271 result = env_execute( 272 ctx, 273 command, 274 environment = local_path_env, 275 timeout = _GO_REPOSITORY_TIMEOUT, 276 ) 277 278 if result.return_code: 279 fail(command) 280 281 if fetch_repo_args: 282 # Disable sumdb in fetch_repo. In module mode, the sum is a mandatory 283 # attribute of go_repository, so we don't need to look it up. 284 fetch_repo_env = dict(env) 285 fetch_repo_env["GOSUMDB"] = "off" 286 287 # Override external GO111MODULE, because it is needed by module mode, no-op in repository mode 288 fetch_repo_env["GO111MODULE"] = "on" 289 290 result = env_execute( 291 ctx, 292 [fetch_repo] + fetch_repo_args, 293 environment = fetch_repo_env, 294 timeout = _GO_REPOSITORY_TIMEOUT, 295 ) 296 if result.return_code: 297 fail("%s: %s" % (ctx.name, result.stderr)) 298 299 # Repositories are fetched. Determine if build file generation is needed. 300 build_file_names = ctx.attr.build_file_name.split(",") 301 existing_build_file = "" 302 for name in build_file_names: 303 path = ctx.path(name) 304 if path.exists and not env_execute(ctx, ["test", "-f", path]).return_code: 305 existing_build_file = name 306 break 307 308 generate = generate or (not existing_build_file and ctx.attr.build_file_generation == "auto") 309 310 if generate: 311 # Build file generation is needed. Populate Gazelle directive at root build file 312 build_file_name = existing_build_file or build_file_names[0] 313 if len(ctx.attr.build_directives) > 0: 314 ctx.file( 315 build_file_name, 316 "\n".join(["# " + d for d in ctx.attr.build_directives]), 317 ) 318 319 # Run Gazelle 320 if gazelle_path == None: 321 gazelle_path = ctx.path(Label(_gazelle)) 322 323 # ctx.attr.name is the canonical name of this repository, which contains a '~' if and only 324 # if this repository is generated by a module extension rather than an invocation in 325 # WORKSPACE. 326 is_module_extension_repo = "~" in ctx.attr.name 327 if is_module_extension_repo: 328 # TODO: In Bazel 6.3.0 and earlier, there is no way to obtain a label referencing a repo 329 # generated by an extension from within that extension. We thus have to manually 330 # construct such a label pointing to the sibling `_go_repository_config` repo created by 331 # the `go_deps` extension. All extension-generated repos have names of the form 332 # `<prefix>~<name set by the extension>`. 333 extension_repo_prefix = ctx.attr.name.rpartition("~")[0] + "~" 334 repo_config = ctx.path(Label("@@" + extension_repo_prefix + "bazel_gazelle_go_repository_config//:WORKSPACE")) 335 else: 336 repo_config = ctx.path(ctx.attr.build_config) 337 cmd = [ 338 gazelle_path, 339 "-go_repository_mode", 340 "-go_prefix", 341 ctx.attr.importpath, 342 "-mode", 343 "fix", 344 "-repo_root", 345 ctx.path(""), 346 "-repo_config", 347 repo_config, 348 ] 349 if ctx.attr.version or ctx.attr.local_path: 350 cmd.append("-go_repository_module_mode") 351 if ctx.attr.build_file_name: 352 cmd.extend(["-build_file_name", ctx.attr.build_file_name]) 353 if ctx.attr.build_tags: 354 cmd.extend(["-build_tags", ",".join(ctx.attr.build_tags)]) 355 if ctx.attr.build_external: 356 cmd.extend(["-external", ctx.attr.build_external]) 357 if ctx.attr.build_file_proto_mode: 358 cmd.extend(["-proto", ctx.attr.build_file_proto_mode]) 359 if ctx.attr.build_naming_convention: 360 cmd.extend(["-go_naming_convention", ctx.attr.build_naming_convention]) 361 if is_module_extension_repo: 362 cmd.append("-bzlmod") 363 cmd.extend(ctx.attr.build_extra_args) 364 cmd.append(ctx.path("")) 365 ctx.report_progress("running Gazelle") 366 result = env_execute(ctx, cmd, environment = env, timeout = _GO_REPOSITORY_TIMEOUT) 367 if result.return_code: 368 fail("failed to generate BUILD files for %s: %s" % ( 369 ctx.attr.importpath, 370 result.stderr, 371 )) 372 if ctx.attr.debug_mode and result.stderr: 373 print("%s gazelle.stdout: %s" % (ctx.name, result.stdout)) 374 print("%s gazelle.stderr: %s" % (ctx.name, result.stderr)) 375 376 # Apply patches if necessary. 377 patch(ctx) 378 379 go_repository = repository_rule( 380 implementation = _go_repository_impl, 381 doc = _DOC, 382 attrs = { 383 # Fundamental attributes of a go repository 384 "importpath": attr.string( 385 doc = """The Go import path that matches the root directory of this repository. 386 387 In module mode (when `version` is set), this must be the module path. If 388 neither `urls` nor `remote` is specified, `go_repository` will 389 automatically find the true path of the module, applying import path 390 redirection. 391 392 If build files are generated for this repository, libraries will have their 393 `importpath` attributes prefixed with this `importpath` string. """, 394 mandatory = True, 395 ), 396 397 # Attributes for a repository that should be checked out from VCS 398 "commit": attr.string( 399 doc = """If the repository is downloaded using a version control tool, this is the 400 commit or revision to check out. With git, this would be a sha1 commit id. 401 `commit` and `tag` may not both be set.""", 402 ), 403 "tag": attr.string( 404 doc = """If the repository is downloaded using a version control tool, this is the 405 named revision to check out. `commit` and `tag` may not both be set.""", 406 ), 407 "vcs": attr.string( 408 default = "", 409 doc = """One of `"git"`, `"hg"`, `"svn"`, `"bzr"`. 410 411 The version control system to use. This is usually determined automatically, 412 but it may be necessary to set this when `remote` is set and the VCS cannot 413 be inferred. You must have the corresponding tool installed on your host.""", 414 values = [ 415 "", 416 "git", 417 "hg", 418 "svn", 419 "bzr", 420 ], 421 ), 422 "remote": attr.string( 423 doc = """The VCS location where the repository should be downloaded from. This is 424 usually inferred from `importpath`, but you can set `remote` to download 425 from a private repository or a fork.""", 426 ), 427 428 # Attributes for a repository that should be downloaded via HTTP. 429 "urls": attr.string_list( 430 doc = """A list of HTTP(S) URLs where an archive containing the project can be 431 downloaded. Bazel will attempt to download from the first URL; the others 432 are mirrors.""", 433 ), 434 "strip_prefix": attr.string( 435 doc = """If the repository is downloaded via HTTP (`urls` is set), this is a 436 directory prefix to strip. See [`http_archive.strip_prefix`].""", 437 ), 438 "type": attr.string( 439 doc = """One of `"zip"`, `"tar.gz"`, `"tgz"`, `"tar.bz2"`, `"tar.xz"`. 440 441 If the repository is downloaded via HTTP (`urls` is set), this is the 442 file format of the repository archive. This is normally inferred from the 443 downloaded file name.""", 444 ), 445 "sha256": attr.string( 446 doc = """If the repository is downloaded via HTTP (`urls` is set), this is the 447 SHA-256 sum of the downloaded archive. When set, Bazel will verify the archive 448 against this sum before extracting it. 449 450 **CAUTION:** Do not use this with services that prepare source archives on 451 demand, such as codeload.github.com. Any minor change in the server software 452 can cause differences in file order, alignment, and compression that break 453 SHA-256 sums.""", 454 ), 455 "canonical_id": attr.string( 456 doc = """If the repository is downloaded via HTTP (`urls` is set) and this is set, restrict cache hits to those cases where the 457 repository was added to the cache with the same canonical id.""", 458 ), 459 "auth_patterns": attr.string_dict( 460 doc = _AUTH_PATTERN_DOC, 461 ), 462 463 # Attributes for a module that should be loaded from the local file system. 464 "local_path": attr.string( 465 doc = """ If specified, `go_repository` will load the module from this local directory""", 466 ), 467 468 # Attributes for a module that should be downloaded with the Go toolchain. 469 "version": attr.string( 470 doc = """If specified, `go_repository` will download the module at this version 471 using `go mod download`. `sum` must also be set. `commit`, `tag`, 472 and `urls` may not be set. """, 473 ), 474 "sum": attr.string( 475 doc = """A hash of the module contents. In module mode, `go_repository` will verify 476 the downloaded module matches this sum. May only be set when `version` 477 is also set. 478 479 A value for `sum` may be found in the `go.sum` file or by running 480 `go mod download -json <module>@<version>`.""", 481 ), 482 "replace": attr.string( 483 doc = """A replacement for the module named by `importpath`. The module named by 484 `replace` will be downloaded at `version` and verified with `sum`. 485 486 NOTE: There is no `go_repository` equivalent to file path `replace` 487 directives. Use `local_repository` instead.""", 488 ), 489 490 # Attributes for a repository that needs automatic build file generation 491 "build_external": attr.string( 492 default = "static", 493 doc = """One of `"external"`, `"static"` or `"vendored"`. 494 495 This sets Gazelle's `-external` command line flag. In `"static"` mode, 496 Gazelle will not call out to the network to resolve imports. 497 498 **NOTE:** This cannot be used to ignore the `vendor` directory in a 499 repository. The `-external` flag only controls how Gazelle resolves 500 imports which are not present in the repository. Use 501 `build_extra_args = ["-exclude=vendor"]` instead.""", 502 values = [ 503 "", 504 "external", 505 "static", 506 "vendored", 507 ], 508 ), 509 "build_file_name": attr.string( 510 default = "BUILD.bazel,BUILD", 511 doc = """Comma-separated list of names Gazelle will consider to be build files. 512 If a repository contains files named `build` that aren't related to Bazel, 513 it may help to set this to `"BUILD.bazel"`, especially on case-insensitive 514 file systems.""", 515 ), 516 "build_file_generation": attr.string( 517 default = "auto", 518 doc = """One of `"auto"`, `"on"`, `"off"`. 519 520 Whether Gazelle should generate build files in the repository. In `"auto"` 521 mode, Gazelle will run if there is no build file in the repository root 522 directory.""", 523 values = [ 524 "on", 525 "auto", 526 "off", 527 ], 528 ), 529 "build_naming_convention": attr.string( 530 values = [ 531 "go_default_library", 532 "import", 533 "import_alias", 534 ], 535 default = "import_alias", 536 doc = """Sets the library naming convention to use when resolving dependencies against this external 537 repository. If unset, the convention from the external workspace is used. 538 Legal values are `go_default_library`, `import`, and `import_alias`. 539 540 See the `gazelle:go_naming_convention` directive in [Directives] for more information.""", 541 ), 542 "build_tags": attr.string_list( 543 doc = "This sets Gazelle's `-build_tags` command line flag.", 544 ), 545 "build_file_proto_mode": attr.string( 546 doc = """One of `"default"`, `"legacy"`, `"disable"`, `"disable_global"` or `"package"`. 547 548 This sets Gazelle's `-proto` command line flag. See [Directives] for more 549 information on each mode.""", 550 values = [ 551 "", 552 "default", 553 "package", 554 "disable", 555 "disable_global", 556 "legacy", 557 ], 558 ), 559 "build_extra_args": attr.string_list( 560 doc = "A list of additional command line arguments to pass to Gazelle when generating build files.", 561 ), 562 "build_config": attr.label( 563 default = "@bazel_gazelle_go_repository_config//:WORKSPACE", 564 doc = """A file that Gazelle should read to learn about external repositories before 565 generating build files. This is useful for dependency resolution. For example, 566 a `go_repository` rule in this file establishes a mapping between a 567 repository name like `golang.org/x/tools` and a workspace name like 568 `org_golang_x_tools`. Workspace directives like 569 `# gazelle:repository_macro` are recognized. 570 571 `go_repository` rules will be re-evaluated when parts of WORKSPACE related 572 to Gazelle's configuration are changed, including Gazelle directives and 573 `go_repository` `name` and `importpath` attributes. 574 Their content should still be fetched from a local cache, but build files 575 will be regenerated. If this is not desirable, `build_config` may be set 576 to a less frequently updated file or `None` to disable this functionality.""", 577 ), 578 "build_directives": attr.string_list( 579 default = [], 580 doc = """A list of directives to be written to the root level build file before 581 Calling Gazelle to generate build files. Each string in the list will be 582 prefixed with `#` automatically. A common use case is to pass a list of 583 Gazelle directives.""", 584 ), 585 586 # Patches to apply after running gazelle. 587 "patches": attr.label_list( 588 doc = "A list of patches to apply to the repository after gazelle runs.", 589 ), 590 "patch_tool": attr.string( 591 default = "", 592 doc = """The patch tool used to apply `patches`. If this is specified, Bazel will 593 use the specifed patch tool instead of the Bazel-native patch implementation.""", 594 ), 595 "patch_args": attr.string_list( 596 default = ["-p0"], 597 doc = "Arguments passed to the patch tool when applying patches.", 598 ), 599 "patch_cmds": attr.string_list( 600 default = [], 601 doc = "Commands to run in the repository after patches are applied.", 602 ), 603 604 # Attributes that affect the verbosity of logging: 605 "debug_mode": attr.bool( 606 default = False, 607 doc = """Enables logging of fetch_repo and Gazelle output during succcesful runs. Gazelle can be noisy 608 so this defaults to `False`. However, setting to `True` can be useful for debugging build failures and 609 unexpected behavior for the given rule. 610 """, 611 ), 612 }, 613 ) 614 """See repository.md#go-repository for full documentation."""