dannycjones commented on code in PR #3414:
URL: https://github.com/apache/iceberg-rust/pull/3414#discussion_r4285037035
##########
dev/release/licenses.py:
##########
@@ -56,6 +75,270 @@ def require_cargo_deny() -> None:
)
+def declared_clarifications() -> set[CrateName]:
+ """Crate names that deny.toml carries a [[licenses.clarify]] block for."""
+ with DENY_TOML.open("rb") as handle:
+ config = tomllib.load(handle)
+
+ blocks = config.get("licenses", {}).get("clarify", [])
+ if not blocks:
+ raise Failure(
+ f"Expected at least one [[licenses.clarify]] block in {DENY_TOML},
found none.\n"
+ "If the last one was deliberately removed, remove this check with
it."
+ )
+
+ pinned = sorted(block["crate"] for block in blocks if "@" in
block["crate"])
+ if pinned:
+ raise Failure(
+ textwrap.dedent("""
+ {deny_toml} pins a [[licenses.clarify]] block to a crate
version:
+ {specs}
+
+ Version pins are rejected by this script.
+ cargo-deny supports them, but will not report when they become
stale.
+ To keep things simple, this script requires that no pinning is
used.
+ Where newer versions change licensing, the script will reject
the clarification
+ and the deny.toml file should be updated.
+ """).format(
+ deny_toml=DENY_TOML,
+ specs="\n".join(f" {spec}" for spec in pinned),
+ )
+ )
+
+ return {block["crate"] for block in blocks}
+
+
+def evaluated_crates() -> tuple[
+ dict[CrateName, set[CrateVersion]], dict[CrateName, set[CrateVersion]]
+]:
+ """Every crate cargo-deny evaluated, along with the subset that had a
clarification applied."""
+ result = subprocess.run(
+ [
+ "cargo",
+ "deny",
+ "--format=json",
+ "check",
+ "license",
+ # We emit the license accepted messages as warnings so we can
count them.
+ "--warn=accepted",
+ ],
+ cwd=REPO_ROOT,
+ capture_output=True,
+ text=True,
+ check=False,
+ )
+ diagnostics = result.stderr
+ if result.returncode != 0:
+ print(diagnostics, file=sys.stderr, end="")
+ raise Failure(
+ "cargo-deny failed while re-running to verify that no license "
+ "clarifications are ignored."
+ )
+
+ evaluated: dict[CrateName, set[CrateVersion]] = defaultdict(set)
+ clarified: dict[CrateName, set[CrateVersion]] = defaultdict(set)
+ for line in diagnostics.splitlines():
+ if not line.strip():
+ continue
+ line_truncated = line[:200]
+ try:
+ diagnostic = json.loads(line)
+ except json.JSONDecodeError:
+ raise Failure(
+ "cargo-deny emitted a line that is not JSON, so its output
cannot be "
+ f"parsed:\n {line_truncated}"
+ )
+
+ fields = diagnostic.get("fields", {})
+
+ # Anything not accepted should already be reported.
+ if fields.get("code") != "accepted":
+ continue
+
+ graphs = fields.get("graphs") or []
+ # An `accepted` verdict covers exactly one crate. Other checks attach
several.
+ if len(graphs) != 1:
+ raise Failure(
+ f"cargo-deny reported an 'accepted' license verdict covering "
+ f"{len(graphs)} crates, but one was expected:\n
{line_truncated}"
+ )
+ krate = graphs[0].get("Krate", {})
+
+ name, version = krate.get("name"), krate.get("version")
+ if name is None or version is None:
+ raise Failure(
+ "cargo-deny reported an 'accepted' license verdict without
naming both "
+ f"the crate and its version:\n {line_truncated}"
+ )
+
+ evaluated[name].add(version)
+ labels = fields.get("labels") or []
+ CLARIFICATION_APPLIED_MSG = "license expression retrieved via user
override"
+ if any(label.get("message") == CLARIFICATION_APPLIED_MSG for label in
labels):
Review Comment:
There is no 'stable indicator', this is the best we have for now.
This fails open - so if we can no longer detect clarifications applied, then
the script will fail and we can adjust. I'll add this as a code comment so its
obvious.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]