This is an automated email from the ASF dual-hosted git repository.
FrankChen021 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 0a7a044da17 build: add script to refresh licenses.yaml versions
(#20736)
0a7a044da17 is described below
commit 0a7a044da179817c297ff9c7f1b1ee0d9f4a04fa
Author: Andreas Maechler <[email protected]>
AuthorDate: Tue Oct 27 20:22:45 2026 -0600
build: add script to refresh licenses.yaml versions (#20736)
* Add a script that refreshes licenses.yaml versions from the dependency
reports
refresh-license-versions.py reads the same Maven dependency reports as
check-licenses.py and updates the version of each licenses.yaml entry
whose libraries all moved to one new version. Only the version line of
an entry changes, so comments, ordering and notices stay as they are.
Entries are matched against the report of their own module, and a
version another entry of that module registers is never taken. Entries
whose libraries moved to different versions, entries with libraries in
no report, and entries of one module that would move to the same
version are listed for a manual edit instead, and the script then exits
non-zero.
The report-reading loop moves out of check_licenses() into
read_dependency_reports() so both scripts share it.
* Compare licenses.yaml entries with their own module's report
An entry counted as current whenever any module still shipped its
version, so an extension that moved to a new version kept its stale
entry as long as another module shipped the old one. The refresh script
now uses the entry's own module report whenever there is one.
* Simplify the licenses.yaml refresh script
Keep each entry's fields in a namespace instead of positional tuples, build
the
registered versions while reading the entries, and capture the version
line's
newline once. Split documents only at a '---' line in the first column, so
an
indented '---' inside a block scalar no longer ends a document.
The report parser's license notes now go to stderr, so stdout only lists the
changes. The "No dependency reports are found" check moves into
read_dependency_reports, and the tests load check-licenses.py once.
* Test the cross-module fallback with reports Maven can produce
A module's dependency report lists one version per library, so two tests
that
gave java-core two versions of the same library could not happen. They now
get
those versions from extension reports, which also covers matching an entry
against other modules' reports when its own module does not ship the
library.
* Point contributors to the refresh script when updating licenses.yaml
* Flag entries that still list a library another entry registers
When one library of an entry moved to a new version but every reported
version of another library is registered by a different entry, the script
rewrote the whole entry. That could register a library twice in one module,
or at a version its module does not ship. List such an entry for a manual
edit instead.
---
dev/license.md | 8 ++
distribution/asf-release-process-guide.md | 1 +
distribution/bin/check-licenses.py | 26 ++--
distribution/bin/refresh-license-versions.py | 203 +++++++++++++++++++++++++++
distribution/bin/test_check_licenses.py | 157 ++++++++++++++++++++-
5 files changed, 381 insertions(+), 14 deletions(-)
diff --git a/dev/license.md b/dev/license.md
index 1a4bf961d82..6ec63aa580c 100644
--- a/dev/license.md
+++ b/dev/license.md
@@ -126,3 +126,11 @@ such as CDDL, EPL, MPL or the SIL Open Font License, also
add a `homepage` field
When you update the version of existing dependencies, you need to update the
version not only in the `pom.xml` file but
also in the `licenses.yaml` file.
+
+`distribution/bin/refresh-license-versions.py` makes that edit from the Maven
dependency reports, and lists the entries
+it cannot update on its own, such as an entry whose libraries moved to
different versions:
+
+```
+distribution/bin/generate-license-dependency-reports.py . target
--clean-maven-artifact-transfer --parallel 2
+distribution/bin/refresh-license-versions.py licenses.yaml
target/license-reports
+```
diff --git a/distribution/asf-release-process-guide.md
b/distribution/asf-release-process-guide.md
index 02f666b6669..ec36578e087 100644
--- a/distribution/asf-release-process-guide.md
+++ b/distribution/asf-release-process-guide.md
@@ -294,6 +294,7 @@ These additional tools were largely used to bootstrap the
initial `LICENSE`, `LI
| --- | --- |
|
[generate-license-dependency-reports](bin/generate-license-dependency-reports.py)
| Point this to the Druid source root, and give it the location of a temp
scratch directory, and it will output Maven dependency reports for Druid. |
| [check-licenses](bin/check-licenses.py) | Checks `licenses.yaml` against the
output of `generate-license-dependency-reports.py`, used by travis and
`-Papache-release` when building distribution, to verify that all dependencies
are present and match the versions in `licenses.yaml`, and that every
`license_file_path` exists and every file in `licenses/bin` is referenced. |
+| [refresh-license-versions](bin/refresh-license-versions.py) | Updates the
`version` of each `licenses.yaml` entry whose libraries moved to a new version
in the output of `generate-license-dependency-reports.py`, and lists the
entries that need a manual edit, such as an entry whose libraries moved to
different versions. Use `--dry-run` to only print the changes. |
| [jar-notice-lister](bin/jar-notice-lister.py) | Point this to an extracted
Druid binary distribution, and give it a temp scratch directory, and it will
output NOTICE information for all the Druid JAR files. |
diff --git a/distribution/bin/check-licenses.py
b/distribution/bin/check-licenses.py
index 0125778e57e..dc28ebf77b7 100755
--- a/distribution/bin/check-licenses.py
+++ b/distribution/bin/check-licenses.py
@@ -407,18 +407,10 @@ 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 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))
- check_license_files(license_yaml, licenses_list)
-
- # Build reported license dictionary.
+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.
reported_dep_to_licenses = {}
reported_modules = {}
- compatible_license_names = build_compatible_license_names()
for dirpath, dirnames, filenames in os.walk(dependency_reports_root):
for filename in filenames:
if filename == "dependencies.html":
@@ -432,9 +424,21 @@ def check_licenses(license_yaml, dependency_reports_root,
exclude_module_prefixe
reported_dep_to_licenses.update(dep_to_license)
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
+
+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))
+ 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)
print_log_to_stderr("Found {} reported
licenses\n".format(len(reported_dep_to_licenses)))
diff --git a/distribution/bin/refresh-license-versions.py
b/distribution/bin/refresh-license-versions.py
new file mode 100755
index 00000000000..0988adbb4ac
--- /dev/null
+++ b/distribution/bin/refresh-license-versions.py
@@ -0,0 +1,203 @@
+#!/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 argparse
+import contextlib
+import importlib.util
+import os
+import re
+import sys
+import types
+
+import yaml
+
+spec = importlib.util.spec_from_file_location(
+ "check_licenses", os.path.join(os.path.dirname(os.path.abspath(__file__)),
"check-licenses.py")
+)
+check_licenses = importlib.util.module_from_spec(spec)
+spec.loader.exec_module(check_licenses)
+
+VERSION_LINE = re.compile(r"^version:[ \t]*(.*?)[ \t]*(\r?\n)?$")
+
+
+def split_documents(text):
+ # Returns the licenses.yaml lines grouped into YAML documents; each group
after the first starts with its '---' line.
+ documents = [[]]
+ for line in text.splitlines(keepends=True):
+ if line.rstrip() == "---":
+ documents.append([])
+ documents[-1].append(line)
+ return documents
+
+
+def find_version_line(lines):
+ for index, line in enumerate(lines):
+ match = VERSION_LINE.match(line)
+ if match:
+ return index, match
+ return None, None
+
+
+def unquote(raw):
+ if len(raw) >= 2 and raw[0] == raw[-1] and raw[0] in "\"'":
+ return raw[1:-1], raw[0]
+ return raw, None
+
+
+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 = '"'
+ return version if quote is None else quote + version + quote
+
+
+def index_reports(reported_modules):
+ # (group_id, artifact_id, version) -> modules becomes (group_id,
artifact_id) -> module -> versions.
+ versions = {}
+ for (group_id, artifact_id, version), modules in reported_modules.items():
+ for module in modules:
+ versions.setdefault((group_id, artifact_id),
{}).setdefault(module, set()).add(version)
+ return versions
+
+
+def refresh_versions(text, reported_modules):
+ # Updates the version of every licenses.yaml entry whose libraries all
moved to one new reported version.
+ # Returns the new text, the updated entries as (name, module, old, new)
and the entries that need a person,
+ # as (name, module, reason). Only version lines change, so comments and
notices stay as they are.
+ reported = index_reports(reported_modules)
+ report_modules = set().union(*reported_modules.values())
+ documents = split_documents(text)
+
+ entries = []
+ # 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))
+ 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
+ version, quote = unquote(match.group(1))
+ libraries = [library for item in parsed["libraries"] for library in
item.items()]
+ for library in libraries:
+ registered.setdefault(library,
{}).setdefault(parsed.get("module"), set()).add(version)
+ entries.append(types.SimpleNamespace(
+ lines=lines, line_index=line_index, newline=match.group(2) or "",
name=parsed.get("name"),
+ module=parsed.get("module"),
skip=parsed.get("skip_dependency_report_check"), version=version,
+ quote=quote, libraries=libraries,
+ ))
+
+ proposals = []
+ flagged = []
+ for entry in entries:
+ if entry.skip or entry.module not in report_modules:
+ continue
+
+ current = []
+ unreported = []
+ claimed = []
+ moved_to = set()
+ problems = []
+ for library in entry.libraries:
+ by_module = reported.get(library)
+ if not by_module:
+ unreported.append("{}:{}".format(*library))
+ continue
+ # Prefer the entry's own module report; only entries of that
module compete for its versions.
+ if entry.module in by_module:
+ pool, taken = by_module[entry.module],
registered[library][entry.module]
+ else:
+ pool, taken = set().union(*by_module.values()),
set().union(*registered[library].values())
+ if entry.version in pool:
+ current.append(library)
+ continue
+ candidates = pool - taken
+ if len(candidates) == 1:
+ moved_to.update(candidates)
+ elif candidates:
+ problems.append("{}:{} has several new versions
{}".format(*library, sorted(candidates)))
+ else:
+ # Every reported version belongs to another entry;
check-licenses lists this one as unchecked.
+ claimed.append("{}:{}".format(*library))
+
+ if not problems and moved_to:
+ if len(moved_to) > 1:
+ problems.append("libraries moved to different versions {};
split the entry".format(sorted(moved_to)))
+ elif current:
+ problems.append("some libraries are still at {}; split the
entry".format(entry.version))
+ elif unreported:
+ problems.append("{} are in no report; update or remove them by
hand".format(", ".join(unreported)))
+ elif claimed:
+ problems.append("{} ship only at versions other entries
register; remove them by hand".format(", ".join(claimed)))
+ if problems:
+ flagged.append((entry.name, entry.module, "; ".join(problems)))
+ elif moved_to:
+ entry.new_version = moved_to.pop()
+ proposals.append(entry)
+
+ # Two stale entries of one module moving the same library to the same
version would register it twice.
+ claimants = {}
+ for entry in proposals:
+ for library in entry.libraries:
+ claimants.setdefault((entry.module, library, entry.new_version),
[]).append(entry)
+
+ updated = []
+ for entry in proposals:
+ rival_names = sorted({
+ rival.name for library in entry.libraries
+ for rival in claimants[(entry.module, library, entry.new_version)]
if rival is not entry
+ })
+ if rival_names:
+ flagged.append((entry.name, entry.module, "entries {} move the
same libraries to {}; keep one".format(rival_names, entry.new_version)))
+ continue
+ entry.lines[entry.line_index] = "version:
{}{}".format(format_version(entry.new_version, entry.quote), entry.newline)
+ updated.append((entry.name, entry.module, entry.version,
entry.new_version))
+
+ return "".join(line for lines in documents for line in lines), updated,
flagged
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Refresh the versions in
licenses.yaml from the Maven dependency reports.")
+ parser.add_argument("license_yaml", metavar="<path to licenses.yaml>",
type=str)
+ parser.add_argument("dependency_reports_root", metavar="<root to maven
dependency reports>", type=str)
+ parser.add_argument("--dry-run", action="store_true", help="Print the
changes without writing licenses.yaml.")
+ args = parser.parse_args()
+
+ # 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(
+ args.dependency_reports_root,
check_licenses.build_compatible_license_names()
+ )
+
+ with open(args.license_yaml, encoding="utf-8", newline="") as f:
+ text = f.read()
+ new_text, updated, flagged = refresh_versions(text, reported_modules)
+
+ for name, module, old, new in updated:
+ print("updated: {} ({}): {} -> {}".format(name, module, old, new))
+ for name, module, reason in flagged:
+ print("needs a manual edit: {} ({}): {}".format(name, module, reason))
+ print("{} entries updated, {} need a manual edit".format(len(updated),
len(flagged)))
+
+ if updated and not args.dry_run:
+ with open(args.license_yaml, "w", encoding="utf-8", newline="") as f:
+ f.write(new_text)
+ if flagged:
+ sys.exit(1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/distribution/bin/test_check_licenses.py
b/distribution/bin/test_check_licenses.py
index 7583f41e1d2..3a6b9c16424 100755
--- a/distribution/bin/test_check_licenses.py
+++ b/distribution/bin/test_check_licenses.py
@@ -20,10 +20,11 @@ import os
import unittest
spec = importlib.util.spec_from_file_location(
- "check_licenses", os.path.join(os.path.dirname(os.path.abspath(__file__)),
"check-licenses.py")
+ "refresh_license_versions",
os.path.join(os.path.dirname(os.path.abspath(__file__)),
"refresh-license-versions.py")
)
-check_licenses = importlib.util.module_from_spec(spec)
-spec.loader.exec_module(check_licenses)
+refresh_license_versions = importlib.util.module_from_spec(spec)
+spec.loader.exec_module(refresh_license_versions)
+check_licenses = refresh_license_versions.check_licenses
APACHE = "Apache License version 2.0"
AZURE = "extensions/druid-azure-extensions"
@@ -62,5 +63,155 @@ class FindDruidModuleNameTest(unittest.TestCase):
self.assertEqual(AZURE,
check_licenses.find_druid_module_name("target/license-reports/ext/druid-azure-extensions/reports"))
+def entry(name, module, version, libraries, extra=""):
+ return (
+ "name: {}\nlicense_category: binary\nmodule: {}\nlicense_name: Apache
License version 2.0\n"
+ "version: {}\nlibraries:\n{}{}"
+ ).format(name, module, version, "".join(" - {}\n".format(library) for
library in libraries), extra)
+
+
+def licenses_yaml(*entries):
+ return "# header\n\n---\n\n" + "\n---\n\n".join(entries)
+
+
+def reports(*gavs_and_module):
+ reported = {}
+ for gav, module in gavs_and_module:
+ reported.setdefault(check_licenses.get_dep_key(*gav.split(":")),
set()).add(module)
+ return reported
+
+
+class RefreshVersionsTest(unittest.TestCase):
+ def refresh(self, text, reported):
+ return refresh_license_versions.refresh_versions(text, reported)
+
+ def assertFlagged(self, count, text, reported):
+ new_text, updated, flagged = self.refresh(text, reported)
+ self.assertEqual((text, [], count), (new_text, updated, len(flagged)))
+
+ def test_updates_only_the_version_line_when_all_libraries_moved(self):
+ notice = "notice: |\n version: not this one\n"
+ text = licenses_yaml(entry("Foo", "java-core", "1.0.0", ["org.foo: a",
"org.foo: b"], notice))
+ new_text, updated, flagged = self.refresh(text,
reports(("org.foo:a:1.0.1", "java-core"), ("org.foo:b:1.0.1", "java-core")))
+ self.assertEqual(text.replace("version: 1.0.0\n", "version: 1.0.1\n"),
new_text)
+ self.assertEqual([("Foo", "java-core", "1.0.0", "1.0.1")], updated)
+ self.assertEqual([], flagged)
+
+ def test_does_not_split_documents_at_indented_dashes(self):
+ text = licenses_yaml("name: Foo\nnotice: |\n ---\nmodule:
java-core\nversion: 1.0.0\nlibraries:\n - org.foo: a\n")
+ _, 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):
+ 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")))
+ self.assertIn("version: '2.22'\n", new_text)
+ self.assertIn('version: "2"\n', new_text)
+
+ def test_leaves_current_entries_alone(self):
+ text = licenses_yaml(entry("Foo", "java-core", "1.0", ["org.foo: a"]))
+ self.assertEqual((text, [], []), self.refresh(text,
reports(("org.foo:a:1.0", "java-core"))))
+
+ def test_flags_libraries_that_moved_to_different_versions(self):
+ text = licenses_yaml(entry("Foo", "java-core", "1.0", ["org.foo: a",
"org.foo: b"]))
+ self.assertFlagged(1, text, reports(("org.foo:a:1.1", "java-core"),
("org.foo:b:1.2", "java-core")))
+
+ def test_flags_entries_where_only_some_libraries_moved(self):
+ text = licenses_yaml(entry("Foo", "java-core", "1.0", ["org.foo: a",
"org.foo: b"]))
+ self.assertFlagged(1, text, reports(("org.foo:a:1.1", "java-core"),
("org.foo:b:1.0", "java-core")))
+
+ def test_updates_the_same_library_in_every_module(self):
+ text = licenses_yaml(
+ entry("Pg", "extensions/druid-lookups-cached-single", "42.7.13",
["org.postgresql: postgresql"]),
+ entry("Pg", "extensions/druid-lookups-cached-global", "42.7.13",
["org.postgresql: postgresql"]),
+ )
+ _, updated, flagged = self.refresh(text, reports(
+ ("org.postgresql:postgresql:42.7.14",
"extensions/druid-lookups-cached-single"),
+ ("org.postgresql:postgresql:42.7.14",
"extensions/druid-lookups-cached-global"),
+ ))
+ self.assertEqual(2, len(updated))
+ self.assertEqual([], flagged)
+
+ def test_does_not_take_a_version_another_entry_registers(self):
+ text = licenses_yaml(
+ entry("Old", "java-core", "1.2.2", ["jakarta.activation:
jakarta.activation-api"]),
+ entry("New", "java-core", "2.1.4", ["jakarta.activation:
jakarta.activation-api"]),
+ )
+ _, updated, flagged = self.refresh(text, reports(
+ ("org.other:x:1.0", "java-core"),
+ ("jakarta.activation:jakarta.activation-api:1.2.2",
"extensions/druid-hdfs-storage"),
+ ("jakarta.activation:jakarta.activation-api:2.1.5", AZURE),
+ ))
+ self.assertEqual([("New", "java-core", "2.1.4", "2.1.5")], updated)
+ self.assertEqual([], flagged)
+
+ def
test_updates_an_entry_whose_old_version_only_ships_in_another_module(self):
+ text = licenses_yaml(entry("JTS",
"extensions/druid-parquet-extensions", "1.19.0", ["org.locationtech.jts:
jts-core"]))
+ _, updated, _ = self.refresh(text, reports(
+ ("org.locationtech.jts:jts-core:1.19.0", "java-core"),
+ ("org.locationtech.jts:jts-core:1.20.0",
"extensions/druid-parquet-extensions"),
+ ))
+ self.assertEqual([("JTS", "extensions/druid-parquet-extensions",
"1.19.0", "1.20.0")], updated)
+
+ def
test_leaves_entries_whose_library_is_only_reported_at_another_entry_version(self):
+ text = licenses_yaml(
+ entry("Stale", "java-core", "1.0", ["org.foo: a"]),
+ entry("Current", "java-core", "2.0", ["org.foo: a"]),
+ )
+ self.assertEqual((text, [], []), self.refresh(text,
reports(("org.foo:a:2.0", "java-core"))))
+
+ def test_takes_a_version_an_entry_of_another_module_registers(self):
+ text = licenses_yaml(
+ entry("Auth", "java-core", "1.30.0", ["com.google.auth:
google-auth-library-credentials"]),
+ entry("Auth", "extensions/druid-google-extensions", "1.54.0",
["com.google.auth: google-auth-library-credentials"]),
+ )
+ _, updated, flagged = self.refresh(text, reports(
+ ("com.google.auth:google-auth-library-credentials:1.54.0",
"java-core"),
+ ("com.google.auth:google-auth-library-credentials:1.54.0",
"extensions/druid-google-extensions"),
+ ))
+ self.assertEqual([("Auth", "java-core", "1.30.0", "1.54.0")], updated)
+ self.assertEqual([], flagged)
+
+ def test_flags_entries_of_one_module_that_move_to_the_same_version(self):
+ text = licenses_yaml(
+ entry("Kafka", "extensions/druid-avro-extensions", "6.2.12-ccs",
["org.apache.kafka: kafka-clients"]),
+ entry("Kafka", "extensions/druid-avro-extensions", "5.5.1-ccs",
["org.apache.kafka: kafka-clients"]),
+ )
+ self.assertFlagged(2, text,
reports(("org.apache.kafka:kafka-clients:8.3.2-ccs",
"extensions/druid-avro-extensions")))
+
+ def test_flags_moved_entries_with_libraries_in_no_report(self):
+ text = licenses_yaml(entry("Kotlin jdk8", "java-core", "1.8.21",
["org.k: stdlib", "org.k: stdlib-jdk8"]))
+ self.assertFlagged(1, text, reports(("org.k:stdlib:2.4.21",
"java-core")))
+
+ def test_flags_moved_entries_with_libraries_another_entry_registers(self):
+ text = licenses_yaml(
+ entry("Family", "java-core", "1.0.0", ["org.f: a", "org.f: b"]),
+ entry("B", "java-core", "1.0.1", ["org.f: b"]),
+ )
+ self.assertFlagged(1, text, reports(("org.f:a:1.0.1", "java-core"),
("org.f:b:1.0.1", "java-core")))
+
+ def test_flags_a_library_with_several_new_versions(self):
+ text = licenses_yaml(entry("Foo", "java-core", "1.0", ["org.foo: a"]))
+ self.assertFlagged(1, text, reports(("org.other:x:1.0", "java-core"),
("org.foo:a:1.1", AZURE), ("org.foo:a:1.2", "extensions/druid-hdfs-storage")))
+
+ def test_prefers_the_version_reported_in_the_entry_module(self):
+ text = licenses_yaml(entry("Kinesis",
"extensions/druid-kinesis-indexing-service", "1.12.3", ["com.amazonaws:
jmespath-java"]))
+ _, updated, _ = self.refresh(text, reports(
+ ("com.amazonaws:jmespath-java:1.12.800", "java-core"),
+ ("com.amazonaws:jmespath-java:1.12.4",
"extensions/druid-kinesis-indexing-service"),
+ ))
+ self.assertEqual([("Kinesis",
"extensions/druid-kinesis-indexing-service", "1.12.3", "1.12.4")], updated)
+
+ def test_skips_flagged_entries_and_modules_without_a_report(self):
+ text = licenses_yaml(
+ entry("Skipped", "java-core", "1.0", ["org.s: a"],
"skip_dependency_report_check: true\n"),
+ entry("Contrib", "extensions-contrib/druid-ranger-security",
"1.0", ["org.c: a"]),
+ )
+ self.assertEqual((text, [], []), self.refresh(text,
reports(("org.s:a:1.1", "java-core"), ("org.c:a:1.1", "java-core"))))
+
+
if __name__ == "__main__":
unittest.main()
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]