Skip to content

Commit 5d6bf81

Browse files
committed
Create a licence_test rule
The `license_test` rule executes the licence checker as a bazel test (rather than an executable), thus allowing an upstream project to use the rule as part of a set of presubmit tests. Signed-off-by: Chris Frantz <cfrantz@google.com>
1 parent b32bbe9 commit 5d6bf81

File tree

2 files changed

+75
-42
lines changed

2 files changed

+75
-42
lines changed

rules/licence-checker-runner.template.sh

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,16 @@
33
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
44
# SPDX-License-Identifier: Apache-2.0
55

6-
if ! cd "$BUILD_WORKSPACE_DIRECTORY"; then
7-
echo "Unable to change to workspace (BUILD_WORKSPACE_DIRECTORY: ${BUILD_WORKSPACE_DIRECTORY})"
6+
WORKSPACE="@@WORKSPACE@@"
7+
8+
if [[ ! -z "${WORKSPACE}" ]]; then
9+
REPO="$(dirname "$(realpath ${WORKSPACE})")"
10+
cd ${REPO} || exit 1
11+
elif [[ ! -z "${BUILD_WORKSPACE_DIRECTORY+is_set}" ]]; then
12+
cd ${BUILD_WORKSPACE_DIRECTORY} || exit 1
13+
else
14+
echo "Neither WORKSPACE nor BUILD_WORKSPACE_DIRECTORY were set."
15+
echo "If this is a test rule, add 'workspace = \"//:WORKSPACE\"' to your rule."
816
exit 1
917
fi
1018

rules/rules.bzl

Lines changed: 65 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def _licence_check_impl(ctx):
1717
substitutions = {
1818
"@@LICENCE@@": "'''" + ctx.attr.licence + "'''",
1919
"@@MATCH_REGEX@@": "true" if ctx.attr.match_regex else "false",
20-
"@@EXCLUDE_PATHS@@": ', '.join(['"{}"'.format(pat) for pat in ctx.attr.exclude_patterns]),
20+
"@@EXCLUDE_PATHS@@": ", ".join(['"{}"'.format(pat) for pat in ctx.attr.exclude_patterns]),
2121
},
2222
)
2323

@@ -35,68 +35,94 @@ def _licence_check_impl(ctx):
3535
command = 'touch "{}"'.format(checker.path),
3636
)
3737

38+
workspace = ctx.file.workspace.path if ctx.file.workspace else ""
3839
script = ctx.actions.declare_file(ctx.label.name + ".bash")
3940
ctx.actions.expand_template(
4041
template = ctx.file._runner,
4142
output = script,
4243
substitutions = {
4344
"@@LICENCE_CHECKER@@": ctx.executable.licence_check.path,
4445
"@@CONFIG@@": config.path,
46+
"@@WORKSPACE@@": workspace,
4547
},
4648
is_executable = True,
4749
)
4850

49-
runfiles = ctx.runfiles(files = [config, checker], transitive_files = ctx.attr.licence_check.files)
51+
files = [config, checker]
52+
if ctx.file.workspace:
53+
files.append(ctx.file.workspace)
54+
55+
runfiles = ctx.runfiles(files = files, transitive_files = ctx.attr.licence_check.files)
5056
runfiles = runfiles.merge(
51-
ctx.attr.licence_check.default_runfiles,
57+
ctx.attr.licence_check.default_runfiles,
5258
)
5359

5460
return DefaultInfo(
5561
runfiles = runfiles,
5662
executable = script,
5763
)
5864

65+
licence_check_attrs = {
66+
"config": attr.label(
67+
allow_single_file = True,
68+
doc = "HJSON configuration file override for the licence checker",
69+
),
70+
"licence": attr.string(
71+
mandatory = True,
72+
doc = "Text of the licence header to use",
73+
),
74+
"match_regex": attr.bool(
75+
default = False,
76+
doc = "Whether to use regex-matching for the licence text",
77+
),
78+
"exclude_patterns": attr.string_list(
79+
default = [],
80+
doc = "File patterns to exclude from licence enforcement",
81+
),
82+
"licence_check": attr.label(
83+
default = "//licence-checker",
84+
cfg = "host",
85+
executable = True,
86+
doc = "The licence checker executable",
87+
),
88+
"workspace": attr.label(
89+
allow_single_file = True,
90+
doc = "Label of the WORKSPACE file",
91+
),
92+
"_runner": attr.label(
93+
default = "//rules:licence-checker-runner.template.sh",
94+
allow_single_file = True,
95+
),
96+
"_config": attr.label(
97+
default = "//rules:licence-checker-config.template.hjson",
98+
allow_single_file = True,
99+
),
100+
}
101+
59102
licence_check = rule(
60103
implementation = _licence_check_impl,
61-
attrs = {
62-
"config": attr.label(
63-
allow_single_file = True,
64-
doc = "HJSON configuration file override for the licence checker",
65-
),
66-
"licence": attr.string(
67-
mandatory = True,
68-
doc = "Text of the licence header to use",
69-
),
70-
"match_regex": attr.bool(
71-
default = False,
72-
doc = "Whether to use regex-matching for the licence text",
73-
),
74-
"exclude_patterns": attr.string_list(
75-
default = [],
76-
doc = "File patterns to exclude from licence enforcement",
77-
),
78-
"licence_check": attr.label(
79-
default = "//licence-checker",
80-
cfg = "host",
81-
executable = True,
82-
doc = "The licence checker executable",
83-
),
84-
"_runner": attr.label(
85-
default = "//rules:licence-checker-runner.template.sh",
86-
allow_single_file = True,
87-
),
88-
"_config": attr.label(
89-
default = "//rules:licence-checker-config.template.hjson",
90-
allow_single_file = True,
91-
),
92-
"_sh_runfiles": attr.label(
93-
default = "@bazel_tools//tools/bash/runfiles",
94-
allow_single_file = True,
95-
),
96-
},
104+
attrs = licence_check_attrs,
97105
executable = True,
98106
)
99107

108+
_licence_test = rule(
109+
implementation = _licence_check_impl,
110+
attrs = licence_check_attrs,
111+
test = True,
112+
)
113+
114+
def _ensure_tag(tags, *tag):
115+
for t in tag:
116+
if t not in tags:
117+
tags.append(t)
118+
return tags
119+
120+
def licence_test(**kwargs):
121+
# Note: the "external" tag is a workaround for bazelbuild#15516.
122+
tags = kwargs.get("tags", [])
123+
kwargs["tags"] = _ensure_tag(tags, "no-sandbox", "no-cache", "external")
124+
_licence_test(**kwargs)
125+
100126
def _yapf_check_impl(ctx):
101127
# Hack to make Bazel build the checker correctly.
102128
#
@@ -173,4 +199,3 @@ yapf_check = rule(
173199
},
174200
executable = True,
175201
)
176-

0 commit comments

Comments
 (0)