blob: a79591e96b77ee2befd6776b744e2b2354dd85f7 [file] [log] [blame]
Tim Windelschmidta0684402025-02-25 11:32:40 +01001From f5a801460e8408c075c4654f33bc0c395b9265de Mon Sep 17 00:00:00 2001
2From: Fabian Meumertzheim <fabian@meumertzhe.im>
3Date: Sun, 16 Feb 2025 23:26:59 +0100
4Subject: [PATCH] Introduce `["all"]` scope for nogo
5
6---
7 go/private/extensions.bzl | 53 +++++++++++++++++++++++----------------
8 1 file changed, 32 insertions(+), 21 deletions(-)
9
10diff --git a/go/private/extensions.bzl b/go/private/extensions.bzl
11index a5c8fc9bbd..ea46dec35f 100644
12--- a/go/private/extensions.bzl
13+++ b/go/private/extensions.bzl
14@@ -74,16 +74,15 @@ _nogo_tag = tag_class(
15 ),
16 "includes": attr.label_list(
17 default = NOGO_DEFAULT_INCLUDES,
18- # The special include "all" is undocumented on purpose: With it, adding a new transitive
19- # dependency to a Go module can cause a build failure if the new dependency has lint
20- # issues.
21 doc = """
22 A Go target is checked with nogo if its package matches at least one of the entries in 'includes'
23 and none of the entries in 'excludes'. By default, nogo is applied to all targets in the main
24 repository.
25
26 Uses the same format as 'visibility', i.e., every entry must be a label that ends with ':__pkg__' or
27-':__subpackages__'.
28+':__subpackages__'. As an exception to this rule, the special value ["all"] is allowed for 'includes'
29+and means that nogo should be applied to all Go targets, including those in all external
30+repositories.
31 """,
32 ),
33 "excludes": attr.label_list(
34@@ -111,11 +110,9 @@ _MAX_NUM_TOOLCHAINS = 9999
35 _TOOLCHAIN_INDEX_PAD_LENGTH = len(str(_MAX_NUM_TOOLCHAINS))
36
37 def _go_sdk_impl(ctx):
38- nogo_tag = struct(
39- nogo = DEFAULT_NOGO,
40- includes = NOGO_DEFAULT_INCLUDES,
41- excludes = NOGO_DEFAULT_EXCLUDES,
42- )
43+ nogo = DEFAULT_NOGO
44+ nogo_includes = NOGO_DEFAULT_INCLUDES
45+ nogo_excludes = NOGO_DEFAULT_EXCLUDES
46 for module in ctx.modules:
47 if not module.is_root or not module.tags.nogo:
48 continue
49@@ -126,22 +123,26 @@ def _go_sdk_impl(ctx):
50 *[t for p in zip(module.tags.nogo, len(module.tags.nogo) * ["\n"]) for t in p]
51 )
52 nogo_tag = module.tags.nogo[0]
53- for scope in nogo_tag.includes + nogo_tag.excludes:
54- # Validate that the scope references a valid, visible repository.
55- # buildifier: disable=no-effect
56- scope.workspace_name
57- if scope.name != "__pkg__" and scope.name != "__subpackages__":
58- fail(
59- "go_sdk.nogo: all entries in includes and excludes must end with ':__pkg__' or ':__subpackages__', got '{}' in".format(scope.name),
60- nogo_tag,
61- )
62+ nogo = nogo_tag.nogo
63+ nogo_includes = nogo_tag.includes
64+ nogo_excludes = nogo_tag.excludes
65+
66+ # "all" is still processed into a Label instance, so we just check its name.
67+ if len(nogo_includes) == 1 and nogo_includes[0].name == "all":
68+ nogo_includes = ["all"]
69+ else:
70+ for scope in nogo_includes:
71+ _check_nogo_scope(scope, nogo_tag)
72+ for scope in nogo_excludes:
73+ _check_nogo_scope(scope, nogo_tag)
74+
75 go_register_nogo(
76 name = "io_bazel_rules_nogo",
77- nogo = str(nogo_tag.nogo),
78+ nogo = str(nogo),
79 # Go through canonical label literals to avoid a dependency edge on the packages in the
80 # scope.
81- includes = [str(l) for l in nogo_tag.includes],
82- excludes = [str(l) for l in nogo_tag.excludes],
83+ includes = [str(l) for l in nogo_includes],
84+ excludes = [str(l) for l in nogo_excludes],
85 )
86
87 multi_version_module = {}
88@@ -300,6 +301,16 @@ def _go_sdk_impl(ctx):
89 else:
90 return None
91
92+def _check_nogo_scope(scope, nogo_tag):
93+ # Validate that the scope references a valid, visible repository.
94+ # buildifier: disable=no-effect
95+ scope.workspace_name
96+ if scope.name != "__pkg__" and scope.name != "__subpackages__":
97+ fail(
98+ "go_sdk.nogo: all entries in includes and excludes must end with ':__pkg__' or ':__subpackages__', got '{}' in".format(scope.name),
99+ nogo_tag,
100+ )
101+
102 def _default_go_sdk_name(*, module, multi_version, tag_type, index, suffix = ""):
103 # Keep the version out of the repository name if possible to prevent unnecessary rebuilds when
104 # it changes.