aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/BUILD10
-rw-r--r--tools/checker_demo.py132
-rwxr-xr-xtools/diff_test.sh36
-rw-r--r--tools/test_helpers.bzl40
4 files changed, 218 insertions, 0 deletions
diff --git a/tools/BUILD b/tools/BUILD
new file mode 100644
index 0000000..d3a5658
--- /dev/null
+++ b/tools/BUILD
@@ -0,0 +1,10 @@
+# License declaration and compliance checking rules.
+
+py_binary(
+ name = "checker_demo",
+ srcs = ["checker_demo.py"],
+ python_version = "PY3",
+ visibility = ["//visibility:public"],
+)
+
+exports_files(["diff_test.sh"])
diff --git a/tools/checker_demo.py b/tools/checker_demo.py
new file mode 100644
index 0000000..0b57cee
--- /dev/null
+++ b/tools/checker_demo.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python3
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Proof of concept license checker.
+
+This is only a demonstration. It will be replaced with other tools.
+"""
+
+import argparse
+import codecs
+import json
+
+# Conditions allowed for all applications
+_ALWAYS_ALLOWED_CONDITIONS = frozenset(['notice', 'permissive', 'unencumberd'])
+
+
+def _get_licenses(licenses_info):
+ with codecs.open(licenses_info, encoding='utf-8') as licenses_file:
+ # TODO(aiuto): Bazel is not parsing the BUILD file as utf-8, so it is
+ # double encoding characters. We should use the line below, but we have
+ # to hack up a double utf-8 decode.
+ # return json.loads(licenses_file.read())
+ b = bytearray([ord(c) for c in licenses_file.read()])
+ return json.loads(b.decode('utf-8'))
+
+
+def _do_report(out, licenses):
+ """Produce a report showing the set of licenses being used.
+
+ Args:
+ out: file object to write to
+ licenses: list of LicenseInfo objects
+
+ Returns:
+ 0 for no restricted licenses.
+ """
+ for lic in licenses: # using strange name lic because license is built-in
+ rule = lic['rule']
+ for kind in lic['license_kinds']:
+ out.write('= %s\n kind: %s\n' % (rule, kind['target']))
+ out.write(' conditions: %s\n' % kind['conditions'])
+
+
+def _check_conditions(out, licenses, allowed_conditions):
+ """Check that the application does not use any disallowed licenses.
+
+ Args:
+ out: file object to write to
+ licenses: list of LicenseInfo objects
+ allowed_conditions: list of allowed condition names
+
+ Returns:
+ 0 for no licenses from outside allowed_conditions.
+ """
+ err = 0
+ for lic in licenses: # using strange name lic because license is built-in
+ rule = lic['rule']
+ for kind in lic['license_kinds']:
+ disallowed = []
+ for condition in kind['conditions']:
+ if condition not in allowed_conditions:
+ disallowed.append(condition)
+ if disallowed:
+ out.write('ERROR: %s\n' % rule)
+ out.write(' kind: %s\n' % kind['target'])
+ out.write(' conditions: %s\n' % kind['conditions'])
+ out.write(' disallowed condition: %s\n' % ','.join(disallowed))
+ err += 1
+ return err
+
+
+def _do_copyright_notices(out, licenses):
+ for l in licenses:
+ # IGNORE_COPYRIGHT: Not a copyright notice. It is a variable holding one.
+ out.write('package(%s), copyright(%s)\n' % (l.get('package_name') or '<unknown>',
+ l['copyright_notice']))
+
+
+def _do_licenses(out, licenses):
+ for lic in licenses:
+ path = lic['license_text']
+ with codecs.open(path, encoding='utf-8') as license_file:
+ out.write('= %s\n' % path)
+ out.write(license_file.read())
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description='Demonstraton license compliance checker')
+
+ parser.add_argument('--licenses_info',
+ help='path to JSON file containing all license data')
+ parser.add_argument('--report', default='report', help='Summary report')
+ parser.add_argument('--copyright_notices',
+ help='output file of all copyright notices')
+ parser.add_argument('--license_texts', help='output file of all license files')
+ parser.add_argument('--check_conditions', action='store_true',
+ help='check that the dep only includes allowed license conditions')
+ args = parser.parse_args()
+
+ licenses = _get_licenses(args.licenses_info)
+ err = 0
+ with codecs.open(args.report, mode='w', encoding='utf-8') as rpt:
+ _do_report(rpt, licenses)
+ if args.check_conditions:
+ # TODO(aiuto): Read conditions from a file of allowed conditions for
+ # a specified application deployment environment.
+ err = _check_conditions(rpt, licenses, _ALWAYS_ALLOWED_CONDITIONS)
+ if args.copyright_notices:
+ with codecs.open(
+ args.copyright_notices, mode='w', encoding='utf-8') as out:
+ _do_copyright_notices(out, licenses)
+ if args.license_texts:
+ with codecs.open(args.license_texts, mode='w', encoding='utf-8') as out:
+ _do_licenses(out, licenses)
+ return err
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tools/diff_test.sh b/tools/diff_test.sh
new file mode 100755
index 0000000..ee06790
--- /dev/null
+++ b/tools/diff_test.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Diff two files and PASS if they are equal, FAIL otherwise.
+# Usage:
+# diff_test.sh path_to_expected path_to_got
+
+# Find input files
+declare -r EXPECTED="$1"
+declare -r GOT="$2"
+
+diff_out=$(mktemp /tmp/diff_test.XXXXXXXXX)
+diff -cB "$EXPECTED" "$GOT" >"$diff_out"
+err=0
+if [[ -s "$diff_out" ]] ; then
+ cat "$diff_out"
+ err=1
+ echo 'To update:'
+ echo ' cp bazel-bin/'"$GOT" "$EXPECTED"
+ echo FAIL
+else
+ echo PASS
+fi
+exit $err
diff --git a/tools/test_helpers.bzl b/tools/test_helpers.bzl
new file mode 100644
index 0000000..30f1980
--- /dev/null
+++ b/tools/test_helpers.bzl
@@ -0,0 +1,40 @@
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Compare rule output to a golden version."""
+
+def golden_test(
+ name,
+ golden,
+ subject):
+ """Check that output from a rule matches the expected output.
+
+ Args:
+ name: test name
+ golden: expected content of subect
+ subject: build target
+ """
+ native.sh_test(
+ name = name,
+ size = "medium",
+ srcs = ["@rules_license//tools:diff_test.sh"],
+ args = [
+ "$(location %s)" % golden,
+ "$(location %s)" % subject,
+ ],
+ data = [
+ subject,
+ golden,
+ ],
+ )