This is an automated email from the ASF dual-hosted git repository.
amaechler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new c0f38c242c2 build: read licenses.yaml versions as strings and fail on
unknown license names (#20764)
c0f38c242c2 is described below
commit c0f38c242c24abe9b49546e63ed178cb5a14cc4e
Author: Frank Chen <[email protected]>
AuthorDate: Fri Oct 30 05:58:58 2026 +0800
build: read licenses.yaml versions as strings and fail on unknown license
names (#20764)
* build: read licenses.yaml versions as strings and fail on unknown license
names
* build: ignore unknown licenses reported only by excluded modules
* build: fail on any unknown license from released modules and report all
license errors together
- Look up license names before skipping GPL ones, so mapped names such as
CDDL + GPLv2 with classpath exception match.
- Keep the first compatible license, so that later licenses no longer
override MIT No Attribution or CDDL 1.0.
- Replace the unsupported-name tracking with find_unknown_licenses(), which
flags released dependencies whose license is unset.
- Print unknown licenses with mismatched and missing ones and exit once.
- Register MIT No Attribution and CDDL 1.0 as names.
* Update distribution/bin/check-licenses.py
Co-authored-by: Andreas Maechler <[email protected]>
* Register org.tukaani:xz 1.12 under Zero-Clause BSD
xz-java switched from public domain to 0BSD in 1.10. The dependency report
now resolves 'Zero-Clause BSD', so check-licenses flagged the stale
'Public Domain' registration.
---------
Co-authored-by: Andreas Maechler <[email protected]>
---
distribution/bin/check-licenses.py | 93 +++++++++++++++++++++-------
distribution/bin/generate-binary-license.py | 4 +-
distribution/bin/generate-binary-notice.py | 4 +-
distribution/bin/licenses_yaml.py | 34 ++++++++++
distribution/bin/refresh-license-versions.py | 9 ++-
distribution/bin/test_check_licenses.py | 93 +++++++++++++++++++++++++++-
licenses.yaml | 20 +++---
licenses/bin/xz.0BSD | 13 ++++
8 files changed, 228 insertions(+), 42 deletions(-)
diff --git a/distribution/bin/check-licenses.py
b/distribution/bin/check-licenses.py
index dc28ebf77b7..8051266b40c 100755
--- a/distribution/bin/check-licenses.py
+++ b/distribution/bin/check-licenses.py
@@ -15,7 +15,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import yaml
+import licenses_yaml
import os
import sys
from html.parser import HTMLParser
@@ -50,6 +50,7 @@ class DependencyReportParser(HTMLParser):
def parse(self, f):
self.dep_to_license = {}
+ self.dep_to_license_names = {}
self.tables_started = 0
self.tables_finished = 0
self.feed(f.read())
@@ -162,7 +163,9 @@ class DependencyReportParser(HTMLParser):
self.state = "row_end"
# print(json.dumps({"groupId": self.group_id, "artifactId":
self.artifact_id, "version": self.version, "classifier": self.classifier,
"type": self.dep_type, "license": self.license}))
if self.group_id.find("org.apache.druid") < 0:
- self.dep_to_license[get_dep_key(self.group_id,
self.artifact_id, self.version)] = (self.license, self.druid_module_name)
+ key = get_dep_key(self.group_id, self.artifact_id,
self.version)
+ self.dep_to_license[key] = (self.license,
self.druid_module_name)
+ self.dep_to_license_names[key] = self.license_names
if self.state == "row_end":
if tag == "table":
@@ -183,6 +186,7 @@ class DependencyReportParser(HTMLParser):
self.classifier = None
self.dep_type = None
self.license = None
+ self.license_names = []
self.attr_index = 0
def set_attr(self, data):
@@ -212,20 +216,17 @@ class DependencyReportParser(HTMLParser):
raise Exception("Unknown attr_index [{}]".format(self.attr_index))
def set_license(self, data):
- if data.upper().find("GPL") < 0:
- # Check if the license assosciated with the component is acccepted
- # set_license() will pick the first acceptable license
- # this fixes issue where a multi-licensed component
- # could override accepted license with not accepted one
- # e.g., EPL / GPL for logback-core
- if self.license not in self.compatible_license_names:
- try:
- self.license = self.compatible_license_names[data]
- except KeyError:
- print("Unsupported license: " + data)
- print("For:" + self.group_id + " " + self.artifact_id +
" in: "+ self.druid_module_name)
- else:
- print(self.group_id + " " + self.artifact_id + " in: " +
self.druid_module_name + " with: " + self.license + " ignoring " + data)
+ # Skip separator text between license names, in case a report puts ",
" between the links.
+ if data.strip(", ") == "":
+ return
+ self.license_names.append(data)
+ # Pick the first compatible license, so that a multi-licensed
component does not override an accepted
+ # license with one that is not, e.g., EPL / LGPL for logback-core. A
license name missing from
+ # compatible_license_names leaves the license unset, which
find_unknown_licenses() reports.
+ if self.license is None:
+ self.license = self.compatible_license_names.get(data)
+ else:
+ print(self.group_id + " " + self.artifact_id + " in: " +
self.druid_module_name + " with: " + self.license + " ignoring " + data)
def print_log_to_stderr(string):
@@ -285,6 +286,7 @@ def build_compatible_license_names():
compatible_licenses['CDDL + GPLv2 with classpath exception'] = 'CDDL 1.1'
compatible_licenses['CDDL License'] = 'CDDL 1.1'
compatible_licenses['COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL)
Version 1.0'] = 'CDDL 1.0'
+ compatible_licenses['CDDL 1.0'] = 'CDDL 1.0'
compatible_licenses['Eclipse Public License 1.0'] = 'Eclipse Public
License 1.0'
compatible_licenses['The Eclipse Public License, Version 1.0'] = 'Eclipse
Public License 1.0'
@@ -330,6 +332,10 @@ def build_compatible_license_names():
compatible_licenses['MIT license'] = 'MIT License'
compatible_licenses['MIT-0'] = 'MIT No Attribution'
+ compatible_licenses['MIT No Attribution'] = 'MIT No Attribution'
+
+ compatible_licenses['Zero-Clause BSD'] = 'Zero-Clause BSD'
+ compatible_licenses['0BSD'] = 'Zero-Clause BSD'
compatible_licenses['The Go license'] = 'The Go license'
compatible_licenses['Go License'] = 'The Go license'
@@ -407,10 +413,24 @@ def find_missing_licenses(reported_dep_to_licenses,
reported_modules, registered
missing_licenses.append((", ".join(modules),) + key +
(reported_license_druid_module[0],))
return missing_licenses
+def find_unknown_licenses(reported_dep_to_licenses, reported_modules,
reported_license_names, skipping_licenses, exclude_module_prefixes):
+ # A dependency that ships in the release must report at least one license
in compatible_license_names.
+ unknown_licenses = []
+ for key, reported_license_druid_module in reported_dep_to_licenses.items():
+ if reported_license_druid_module[0] is not None or key in
skipping_licenses:
+ continue
+ shipped_modules = sorted(m for m in reported_modules[key] if not
is_excluded_module(m, exclude_module_prefixes))
+ if shipped_modules:
+ license_names = ", ".join(reported_license_names.get(key, [])) or
"<none>"
+ unknown_licenses.append((", ".join(shipped_modules),) + key +
(license_names,))
+ return unknown_licenses
+
def read_dependency_reports(dependency_reports_root, compatible_license_names):
- # Returns (group_id, artifact_id, version) -> (license, druid_module) and
(group_id, artifact_id, version) -> modules.
+ # Returns (group_id, artifact_id, version) -> (license, druid_module),
(group_id, artifact_id, version) -> modules,
+ # and (group_id, artifact_id, version) -> license names as reported.
reported_dep_to_licenses = {}
reported_modules = {}
+ reported_license_names = {}
for dirpath, dirnames, filenames in os.walk(dependency_reports_root):
for filename in filenames:
if filename == "dependencies.html":
@@ -422,23 +442,26 @@ def read_dependency_reports(dependency_reports_root,
compatible_license_names):
parser = DependencyReportParser(druid_module_name,
compatible_license_names)
dep_to_license = parser.parse(report_file)
reported_dep_to_licenses.update(dep_to_license)
+ reported_license_names.update(parser.dep_to_license_names)
for key in dep_to_license:
reported_modules.setdefault(key,
set()).add(druid_module_name)
if len(reported_dep_to_licenses) == 0:
raise Exception("No dependency reports are found")
- return reported_dep_to_licenses, reported_modules
+ return reported_dep_to_licenses, reported_modules, reported_license_names
def check_licenses(license_yaml, dependency_reports_root,
exclude_module_prefixes):
# Build a dictionary to facilitate comparing reported licenses and
registered ones.
# These dictionaries are the mapping of (group_id, artifact_id, version)
to license_name.
with open(license_yaml, encoding='utf-8') as registry_file:
- licenses_list = list(yaml.load_all(registry_file,
Loader=yaml.FullLoader))
+ licenses_list = licenses_yaml.load_all(registry_file)
check_license_files(license_yaml, licenses_list)
# Build reported license dictionary.
compatible_license_names = build_compatible_license_names()
- reported_dep_to_licenses, reported_modules =
read_dependency_reports(dependency_reports_root, compatible_license_names)
+ reported_dep_to_licenses, reported_modules, reported_license_names =
read_dependency_reports(
+ dependency_reports_root, compatible_license_names
+ )
print_log_to_stderr("Found {} reported
licenses\n".format(len(reported_dep_to_licenses)))
@@ -480,6 +503,18 @@ def check_licenses(license_yaml, dependency_reports_root,
exclude_module_prefixe
)
sys.exit(1)
+ unknown_license_name_entries = [
+ (license.get('name'), license.get('license_name'))
+ for license in licenses_list
+ if 'libraries' in license and license.get('license_name') not in
compatible_license_names
+ ]
+ if unknown_license_name_entries:
+ print_log_to_stderr("Error: found {} licenses.yaml entries with
unknown license names".format(len(unknown_license_name_entries)))
+ for name, license_name in unknown_license_name_entries:
+ print_log_to_stderr(" name: {}, license_name: {}".format(name,
license_name))
+ print_log_to_stderr("Every license_name must be one of the names in
build_compatible_license_names() in check-licenses.py.")
+ sys.exit(1)
+
for license in licenses_list:
if 'libraries' in license:
for library in license['libraries']:
@@ -539,6 +574,21 @@ def check_licenses(license_yaml, dependency_reports_root,
exclude_module_prefixe
print_log_to_stderr("druid_module: {}, groupId: {}, artifactId:
{}, version: {}, license: {}".format(missing_license[0], missing_license[1],
missing_license[2], missing_license[3], missing_license[4]))
print_log_to_stderr("")
+ # Let's find unknown licenses, which are reported by released modules but
not in compatible_license_names.
+ unknown_licenses = find_unknown_licenses(
+ reported_dep_to_licenses, reported_modules, reported_license_names,
skipping_licenses, exclude_module_prefixes
+ )
+
+ if len(unknown_licenses) > 0:
+ print_log_to_stderr("Error: found {} dependencies whose reported
licenses are unknown".format(len(unknown_licenses)))
+ for unknown_license in unknown_licenses:
+ print_log_to_stderr("druid_module: {}, groupId: {}, artifactId:
{}, version: {}, reported_license: {}".format(*unknown_license))
+ print_log_to_stderr(
+ "If the license is compatible, add its name to
build_compatible_license_names() in check-licenses.py "
+ "and register the dependency in licenses.yaml under that license."
+ )
+ print_log_to_stderr("")
+
# Let's find unchecked licenses, which are registered but missing in the
report.
# These licenses should be checked manually.
for key, registered_license in registered_dep_to_licenses.items():
@@ -554,9 +604,10 @@ def check_licenses(license_yaml, dependency_reports_root,
exclude_module_prefixe
print_log_to_stderr("groupId: {}, artifactId: {}, version: {},
reported_license: {}".format(unchecked_license[0], unchecked_license[1],
unchecked_license[2], unchecked_license[3]))
print_log_to_stderr("")
- if len(mismatched_licenses) > 0 or len(missing_licenses) > 0:
+ if len(mismatched_licenses) > 0 or len(missing_licenses) > 0 or
len(unknown_licenses) > 0:
print_log_to_stderr("Mismatched licenses:
{}".format(mismatched_licenses))
print_log_to_stderr("Missing licenses: {}".format(missing_licenses))
+ print_log_to_stderr("Unknown licenses: {}".format(unknown_licenses))
sys.exit(1)
diff --git a/distribution/bin/generate-binary-license.py
b/distribution/bin/generate-binary-license.py
index ecbeb9cf340..83990962e51 100755
--- a/distribution/bin/generate-binary-license.py
+++ b/distribution/bin/generate-binary-license.py
@@ -15,7 +15,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import yaml
+import licenses_yaml
import os
import re
import sys
@@ -156,7 +156,7 @@ def print_license_name_underbar(license_name):
def load_licenses(license_yaml, exclude_module_prefixes):
with open(license_yaml, encoding='utf-8') as registry_file:
- licenses_list = list(yaml.load_all(registry_file, Loader=yaml.Loader))
+ licenses_list = licenses_yaml.load_all(registry_file)
# Filter out entries whose module matches any of the excluded prefixes.
Used by the release build
# to skip contrib extension entries (module: extensions-contrib/*) since
contrib extensions are not
diff --git a/distribution/bin/generate-binary-notice.py
b/distribution/bin/generate-binary-notice.py
index 464ca28560b..c85561a903e 100755
--- a/distribution/bin/generate-binary-notice.py
+++ b/distribution/bin/generate-binary-notice.py
@@ -17,7 +17,7 @@
import argparse
import sys
-import yaml
+import licenses_yaml
from collections import defaultdict
@@ -68,7 +68,7 @@ def generate_notice(source_notice, dependences_yaml,
exclude_module_prefixes):
# Print Apache license first.
print_outfile(source_notice)
with open(dependences_yaml, encoding='utf-8') as registry_file:
- dependencies = list(yaml.load_all(registry_file, Loader=yaml.Loader))
+ dependencies = licenses_yaml.load_all(registry_file)
# Filter out entries whose module matches any of the excluded prefixes.
Used by the release build
# to skip contrib extension entries (module: extensions-contrib/*) since
contrib extensions are not
diff --git a/distribution/bin/licenses_yaml.py
b/distribution/bin/licenses_yaml.py
new file mode 100644
index 00000000000..c569e3c3f75
--- /dev/null
+++ b/distribution/bin/licenses_yaml.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
+#
+# http://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.
+
+import yaml
+
+
+class LicensesYamlLoader(yaml.SafeLoader):
+ # Loads plain scalars that look like numbers as strings, so that versions
such as 1.10 do not need to be
+ # quoted in licenses.yaml. With the default resolvers, 1.10 would be
loaded as the float 1.1.
+ pass
+
+
+LicensesYamlLoader.yaml_implicit_resolvers = {
+ first_char: [(tag, regexp) for tag, regexp in resolvers if tag not in
('tag:yaml.org,2002:int', 'tag:yaml.org,2002:float')]
+ for first_char, resolvers in
yaml.SafeLoader.yaml_implicit_resolvers.items()
+}
+
+
+def load_all(stream):
+ return list(yaml.load_all(stream, Loader=LicensesYamlLoader))
diff --git a/distribution/bin/refresh-license-versions.py
b/distribution/bin/refresh-license-versions.py
index 0988adbb4ac..46e450e16b0 100755
--- a/distribution/bin/refresh-license-versions.py
+++ b/distribution/bin/refresh-license-versions.py
@@ -23,6 +23,7 @@ import re
import sys
import types
+import licenses_yaml
import yaml
spec = importlib.util.spec_from_file_location(
@@ -59,9 +60,7 @@ def unquote(raw):
def format_version(version, quote):
- # Quote when the old value was quoted, or when YAML would not read the new
value back as a string (2.22 is a float).
- if quote is None and not isinstance(yaml.safe_load(version), str):
- quote = '"'
+ # Keep the old quotes. Unquoted versions need none: licenses_yaml reads
2.10 as the string "2.10".
return version if quote is None else quote + version + quote
@@ -86,7 +85,7 @@ def refresh_versions(text, reported_modules):
# A reported version that another entry already registers belongs to that
entry, not to a stale one.
registered = {}
for lines in documents:
- parsed = yaml.safe_load("".join(lines))
+ parsed = yaml.load("".join(lines),
Loader=licenses_yaml.LicensesYamlLoader)
line_index, match = find_version_line(lines)
if not isinstance(parsed, dict) or "libraries" not in parsed or match
is None or not match.group(1):
continue
@@ -178,7 +177,7 @@ def main():
# The report parser prints notes about multi-licensed libraries; keep
stdout for the changes below.
with contextlib.redirect_stdout(sys.stderr):
- _, reported_modules = check_licenses.read_dependency_reports(
+ _, reported_modules, _ = check_licenses.read_dependency_reports(
args.dependency_reports_root,
check_licenses.build_compatible_license_names()
)
diff --git a/distribution/bin/test_check_licenses.py
b/distribution/bin/test_check_licenses.py
index 3a6b9c16424..4eee01a8bee 100755
--- a/distribution/bin/test_check_licenses.py
+++ b/distribution/bin/test_check_licenses.py
@@ -16,6 +16,7 @@
# limitations under the License.
import importlib.util
+import io
import os
import unittest
@@ -57,6 +58,30 @@ class FindMissingLicensesTest(unittest.TestCase):
self.assertEqual([], find_missing([AZURE], [], skipping={GAV: {}}))
+def find_unknown(license, reporting_modules, skipping=None):
+ return check_licenses.find_unknown_licenses(
+ {GAV: (license, reporting_modules[0])}, {GAV: set(reporting_modules)},
{GAV: ["Some New License"]}, skipping or {}, EXCLUDED
+ )
+
+
+class FindUnknownLicensesTest(unittest.TestCase):
+ def test_reported_by_released_module(self):
+ self.assertEqual([(AZURE,) + GAV + ("Some New License",)],
find_unknown(None, [AZURE]))
+
+ def test_reported_only_by_excluded_modules_is_ignored(self):
+ self.assertEqual([], find_unknown(None, [TESTCONTAINERS, RANGER]))
+
+ def test_reported_by_released_and_excluded_modules(self):
+ self.assertEqual([(AZURE,) + GAV + ("Some New License",)],
find_unknown(None, [TESTCONTAINERS, AZURE]))
+
+ def test_known_and_unspecified_licenses_are_ignored(self):
+ self.assertEqual([], find_unknown(APACHE, [AZURE]))
+ self.assertEqual([], find_unknown("-", [AZURE]))
+
+ def test_skipped_dependency_is_ignored(self):
+ self.assertEqual([], find_unknown(None, [AZURE], skipping={GAV: {}}))
+
+
class FindDruidModuleNameTest(unittest.TestCase):
def test_maps_report_dirs_to_module_tags(self):
self.assertEqual("java-core",
check_licenses.find_druid_module_name("target/license-reports/core/reports"))
@@ -102,14 +127,14 @@ class RefreshVersionsTest(unittest.TestCase):
_, updated, _ = self.refresh(text, reports(("org.foo:a:1.0.1",
"java-core")))
self.assertEqual([("Foo", "java-core", "1.0.0", "1.0.1")], updated)
- def test_keeps_quotes_and_quotes_versions_yaml_would_read_as_numbers(self):
+ def
test_keeps_quotes_and_does_not_quote_versions_that_look_like_numbers(self):
text = licenses_yaml(
entry("Quoted", "java-core", "'2.21'", ["org.q: a"]),
entry("Plain", "java-core", "1.0.0", ["org.p: a"]),
)
- new_text, _, _ = self.refresh(text, reports(("org.q:a:2.22",
"java-core"), ("org.p:a:2", "java-core")))
+ new_text, _, _ = self.refresh(text, reports(("org.q:a:2.22",
"java-core"), ("org.p:a:2.10", "java-core")))
self.assertIn("version: '2.22'\n", new_text)
- self.assertIn('version: "2"\n', new_text)
+ self.assertIn("version: 2.10\n", new_text)
def test_leaves_current_entries_alone(self):
text = licenses_yaml(entry("Foo", "java-core", "1.0", ["org.foo: a"]))
@@ -213,5 +238,67 @@ class RefreshVersionsTest(unittest.TestCase):
self.assertEqual((text, [], []), self.refresh(text,
reports(("org.s:a:1.1", "java-core"), ("org.c:a:1.1", "java-core"))))
+def parse_report(*licenses):
+ row = ", ".join("<a>{}</a>".format(license) for license in licenses)
+ report = (
+ '<a id="Project_Dependencies_compile"></a><table>'
+
"<tr><th>GroupId</th><th>ArtifactId</th><th>Version</th><th>Type</th><th>Licenses</th></tr>"
+
"<tr><td>org.tukaani</td><td>xz</td><td>1.10</td><td>jar</td><td>{}</td></tr>"
+ "</table>".format(row)
+ )
+ parser = check_licenses.DependencyReportParser("java-core",
check_licenses.build_compatible_license_names())
+ dep_to_license = parser.parse(io.StringIO(report))
+ return dep_to_license, parser.dep_to_license_names
+
+
+class DependencyReportParserTest(unittest.TestCase):
+ XZ = check_licenses.get_dep_key("org.tukaani", "xz", "1.10")
+
+ def license_of(self, *licenses):
+ return parse_report(*licenses)[0][self.XZ][0]
+
+ def test_known_license_is_normalized(self):
+ self.assertEqual(({self.XZ: ("Zero-Clause BSD", "java-core")},
{self.XZ: ["0BSD"]}), parse_report("0BSD"))
+
+ def test_unknown_license_is_unset_and_its_name_is_kept(self):
+ self.assertEqual(({self.XZ: (None, "java-core")}, {self.XZ: ["Some New
License"]}), parse_report("Some New License"))
+
+ def test_unknown_license_is_fine_when_another_license_is_known(self):
+ self.assertEqual(APACHE, self.license_of("Some New License",
"Apache-2.0"))
+
+ def test_gpl_only_license_is_unset(self):
+ self.assertIsNone(self.license_of("GNU Lesser General Public License,
Version 2.1"))
+
+ def test_gpl_license_does_not_override_a_compatible_one(self):
+ self.assertEqual("Eclipse Public License 1.0",
self.license_of("LGPL-2.1", "Eclipse Public License - v 1.0", "LGPL-2.1"))
+
+ def test_known_license_mentioning_gpl_is_normalized(self):
+ self.assertEqual("CDDL 1.1", self.license_of("CDDL + GPLv2 with
classpath exception"))
+
+ def test_separators_are_not_license_names(self):
+ self.assertEqual({self.XZ: ["Some New License", "LGPL-2.1"]},
parse_report("Some New License", "LGPL-2.1")[1])
+
+ def test_unspecified_license_is_kept(self):
+ self.assertEqual("-", self.license_of("-", "Apache-2.0"))
+
+ def test_first_compatible_license_is_kept(self):
+ self.assertEqual("MIT No Attribution", self.license_of("MIT-0",
"Apache-2.0"))
+
+
+class CompatibleLicenseNamesTest(unittest.TestCase):
+ def test_every_normalized_name_is_a_name(self):
+ compatible_license_names =
check_licenses.build_compatible_license_names()
+ self.assertEqual([], sorted(set(compatible_license_names.values()) -
set(compatible_license_names)))
+
+
+class LoadLicensesYamlTest(unittest.TestCase):
+ def test_versions_that_look_like_numbers_are_loaded_as_strings(self):
+ docs = check_licenses.licenses_yaml.load_all("version:
1.10\n---\nversion: 2\n---\nversion: 1.5.7-11\n")
+ self.assertEqual(["1.10", "2", "1.5.7-11"], [doc["version"] for doc in
docs])
+
+ def test_booleans_are_still_loaded_as_booleans(self):
+ self.assertEqual([{"skip_dependency_report_check": True}],
check_licenses.licenses_yaml.load_all("skip_dependency_report_check: true\n"))
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/licenses.yaml b/licenses.yaml
index ca076a1bbc9..2119cd8ffa0 100644
--- a/licenses.yaml
+++ b/licenses.yaml
@@ -398,7 +398,7 @@ name: Jackson
license_category: binary
module: java-core
license_name: Apache License version 2.0
-version: "2.22"
+version: 2.22
libraries:
- com.fasterxml.jackson.core: jackson-annotations
@@ -1011,7 +1011,7 @@ name: com.nimbusds nimbus-jose-jwt
license_category: binary
module: extensions/druid-pac4j
license_name: Apache License version 2.0
-version: "10.10"
+version: 10.10
libraries:
- com.nimbusds: nimbus-jose-jwt
@@ -1426,7 +1426,7 @@ name: org.bouncycastle bcprov-jdk18on
license_category: binary
module: extensions/druid-kubernetes-extensions
license_name: MIT License
-version: "1.86"
+version: 1.86
libraries:
- org.bouncycastle: bcprov-jdk18on
- org.bouncycastle: bcprov-ext-jdk18on
@@ -1437,7 +1437,7 @@ name: org.bouncycastle bcpkix-jdk18on and bcutil-jdk18on
license_category: binary
module: extensions/druid-kubernetes-extensions
license_name: MIT License
-version: "1.86"
+version: 1.86
libraries:
- org.bouncycastle: bcpkix-jdk18on
- org.bouncycastle: bcutil-jdk18on
@@ -2990,7 +2990,7 @@ libraries:
---
name: jersey-common
-version: '2.30'
+version: 2.30
license_category: binary
module: extensions/druid-avro-extensions
license_name: Apache License version 2.0
@@ -3557,7 +3557,7 @@ name: aircompressor
license_category: binary
module: extensions/druid-parquet-extensions
license_name: Apache License version 2.0
-version: "2.0.3"
+version: 2.0.3
libraries:
- io.airlift: aircompressor
@@ -4012,8 +4012,10 @@ libraries:
name: XZ
license_category: binary
module: java-core
-license_name: Public Domain
+license_name: Zero-Clause BSD
+copyright: The XZ for Java authors and contributors
version: 1.12
+license_file_path: licenses/bin/xz.0BSD
libraries:
- org.tukaani: xz
@@ -4125,7 +4127,7 @@ name: aircompressor
license_category: binary
module: extensions/druid-orc-extensions
license_name: Apache License version 2.0
-version: "2.0.3"
+version: 2.0.3
libraries:
- io.airlift: aircompressor
@@ -7546,7 +7548,7 @@ license_category: binary
module: extensions/druid-kerberos
license_name: Eclipse Public License 2.0
homepage: https://projects.eclipse.org/projects/ee4j.jersey
-version: '2.46'
+version: 2.46
libraries:
- org.glassfish.jersey.containers: jersey-container-servlet
- org.glassfish.jersey.containers: jersey-container-servlet-core
diff --git a/licenses/bin/xz.0BSD b/licenses/bin/xz.0BSD
new file mode 100644
index 00000000000..16270b71eee
--- /dev/null
+++ b/licenses/bin/xz.0BSD
@@ -0,0 +1,13 @@
+Copyright (C) The XZ for Java authors and contributors
+
+Permission to use, copy, modify, and/or distribute this
+software for any purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]