Skip to content

Commit

Permalink
Create a licence_test rule
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
cfrantz committed Sep 21, 2022
1 parent b32bbe9 commit 5d6bf81
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 42 deletions.
12 changes: 10 additions & 2 deletions rules/licence-checker-runner.template.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

if ! cd "$BUILD_WORKSPACE_DIRECTORY"; then
echo "Unable to change to workspace (BUILD_WORKSPACE_DIRECTORY: ${BUILD_WORKSPACE_DIRECTORY})"
WORKSPACE="@@WORKSPACE@@"

if [[ ! -z "${WORKSPACE}" ]]; then
REPO="$(dirname "$(realpath ${WORKSPACE})")"
cd ${REPO} || exit 1
elif [[ ! -z "${BUILD_WORKSPACE_DIRECTORY+is_set}" ]]; then
cd ${BUILD_WORKSPACE_DIRECTORY} || exit 1
else
echo "Neither WORKSPACE nor BUILD_WORKSPACE_DIRECTORY were set."
echo "If this is a test rule, add 'workspace = \"//:WORKSPACE\"' to your rule."
exit 1
fi

Expand Down
105 changes: 65 additions & 40 deletions rules/rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def _licence_check_impl(ctx):
substitutions = {
"@@LICENCE@@": "'''" + ctx.attr.licence + "'''",
"@@MATCH_REGEX@@": "true" if ctx.attr.match_regex else "false",
"@@EXCLUDE_PATHS@@": ', '.join(['"{}"'.format(pat) for pat in ctx.attr.exclude_patterns]),
"@@EXCLUDE_PATHS@@": ", ".join(['"{}"'.format(pat) for pat in ctx.attr.exclude_patterns]),
},
)

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

workspace = ctx.file.workspace.path if ctx.file.workspace else ""
script = ctx.actions.declare_file(ctx.label.name + ".bash")
ctx.actions.expand_template(
template = ctx.file._runner,
output = script,
substitutions = {
"@@LICENCE_CHECKER@@": ctx.executable.licence_check.path,
"@@CONFIG@@": config.path,
"@@WORKSPACE@@": workspace,
},
is_executable = True,
)

runfiles = ctx.runfiles(files = [config, checker], transitive_files = ctx.attr.licence_check.files)
files = [config, checker]
if ctx.file.workspace:
files.append(ctx.file.workspace)

runfiles = ctx.runfiles(files = files, transitive_files = ctx.attr.licence_check.files)
runfiles = runfiles.merge(
ctx.attr.licence_check.default_runfiles,
ctx.attr.licence_check.default_runfiles,
)

return DefaultInfo(
runfiles = runfiles,
executable = script,
)

licence_check_attrs = {
"config": attr.label(
allow_single_file = True,
doc = "HJSON configuration file override for the licence checker",
),
"licence": attr.string(
mandatory = True,
doc = "Text of the licence header to use",
),
"match_regex": attr.bool(
default = False,
doc = "Whether to use regex-matching for the licence text",
),
"exclude_patterns": attr.string_list(
default = [],
doc = "File patterns to exclude from licence enforcement",
),
"licence_check": attr.label(
default = "//licence-checker",
cfg = "host",
executable = True,
doc = "The licence checker executable",
),
"workspace": attr.label(
allow_single_file = True,
doc = "Label of the WORKSPACE file",
),
"_runner": attr.label(
default = "//rules:licence-checker-runner.template.sh",
allow_single_file = True,
),
"_config": attr.label(
default = "//rules:licence-checker-config.template.hjson",
allow_single_file = True,
),
}

licence_check = rule(
implementation = _licence_check_impl,
attrs = {
"config": attr.label(
allow_single_file = True,
doc = "HJSON configuration file override for the licence checker",
),
"licence": attr.string(
mandatory = True,
doc = "Text of the licence header to use",
),
"match_regex": attr.bool(
default = False,
doc = "Whether to use regex-matching for the licence text",
),
"exclude_patterns": attr.string_list(
default = [],
doc = "File patterns to exclude from licence enforcement",
),
"licence_check": attr.label(
default = "//licence-checker",
cfg = "host",
executable = True,
doc = "The licence checker executable",
),
"_runner": attr.label(
default = "//rules:licence-checker-runner.template.sh",
allow_single_file = True,
),
"_config": attr.label(
default = "//rules:licence-checker-config.template.hjson",
allow_single_file = True,
),
"_sh_runfiles": attr.label(
default = "@bazel_tools//tools/bash/runfiles",
allow_single_file = True,
),
},
attrs = licence_check_attrs,
executable = True,
)

_licence_test = rule(
implementation = _licence_check_impl,
attrs = licence_check_attrs,
test = True,
)

def _ensure_tag(tags, *tag):
for t in tag:
if t not in tags:
tags.append(t)
return tags

def licence_test(**kwargs):
# Note: the "external" tag is a workaround for bazelbuild#15516.
tags = kwargs.get("tags", [])
kwargs["tags"] = _ensure_tag(tags, "no-sandbox", "no-cache", "external")
_licence_test(**kwargs)

def _yapf_check_impl(ctx):
# Hack to make Bazel build the checker correctly.
#
Expand Down Expand Up @@ -173,4 +199,3 @@ yapf_check = rule(
},
executable = True,
)

0 comments on commit 5d6bf81

Please sign in to comment.