[700] Bundle license texts for all non-Apache-2.0 shaded dependencies - #857
[700] Bundle license texts for all non-Apache-2.0 shaded dependencies#857rangareddy wants to merge 1 commit into
Conversation
50ac2c9 to
efbffc9
Compare
|
@rangareddy I have ran the scripts in my local and it was breaking for few dependencies. Can you address the comments? I will take a look tomorrow again and merge for 0.4.0-incubating rc2. |
efbffc9 to
2f9ed96
Compare
|
@vinishjail97 all ten threads are answered inline and the branch is force-pushed ( Your two direct questions
Things the review surfaced that turned out to be bugs, not gaps
One I found while running your scripts, unrelated to any thread
Two things I deliberately did not decide
Also: I'd flag Not rebased onto |
ff95274 to
a611ada
Compare
|
@vinishjail97 the License Check failure on the previous push was the new gate working, and it turned up something worth knowing before rc2. Pushed The License Check has never actually run in CI. The script builds its module list with Every one of the last ten runs on What that was hiding Replacing To confirm this is not something I introduced: this PR touches no How I have handled it, and why not more Filed as #880 with the full evidence, and this PR adds an explicit one-module I did not fix the drift here because the two candidate fixes have materially different consequences for the published artifact:
That is a release/design call rather than a tooling fix, so it seemed wrong to decide it inside a license-text PR — and worse to leave the gate vacuous in order to avoid it. Happy to do either once you or Two things you may want to consider separately, given the gate has not been effective on any branch:
|
The bundled (shaded) jars listed third-party dependencies in LICENSE-bundled but shipped no license text for many of them, even though the banner points to "licenses/ for text of these licenses". This adds the missing texts and makes the tooling keep them complete and accurate. generate_shaded_license_metadata.py: - Regenerates each module's META-INF/licenses/ directory: for every non-Apache-2.0 bundled dependency it writes LICENSE-<artifactId>, sourced from a curated override first, then the dependency's own jar, and fails loudly when a dependency has neither. - Resolves everything a run would write before writing any of it. A failure used to leave texts deleted and LICENSE-bundled/NOTICE-bundled rewritten for the modules already processed, so the only recovery was to discard the whole run; a failing run is now a no-op across all modules. - Parses the dependency tree correctly for classified artifacts. The version is the second-to-last field, not parts[3], which is the classifier on a six-field line. This aborted the run on org.apache.hudi:hudi-io:jar:shaded and, for the nine classified coordinates that an override happened to cover, silently recorded a classifier where LICENSE-bundled wants a version (io.netty:netty-transport-native-epoll:linux-aarch_64). A "tests" classifier is now excluded alongside test-jar. - Reads POMs that Maven accepts but ElementTree does not. hadoop-project-3.1.0 contains <Xlint:-unchecked/>, which expat rejects outright, and hadoop-yarn-client-2.7.1 binds the Maven namespace to a prefix rather than as the default namespace, leaving every element unqualified so the namespaced XPaths matched nothing. Both POMs are authentic; their SHA-1s match Maven Central. License lookups now match on local name and fall back to a text scan when a POM will not parse. - Drops 18 license-family overrides that only existed because of those three parsing bugs, including org.apache.hadoop, and drops the xml-apis override, which claimed Apache Software License 1.1 while both the POM and the jar's own license/LICENSE carry the Apache 2.0 text. - Checks that a dependency's license text is credible as the family resolved from its POM. Nothing previously tied the two together, so a jar shipping the wrong license file was attributed wrongly and silently. - Derives the bundled set from the runtime tree intersected with the shade <includes>, so the metadata describes what is inside the jar rather than what is on the classpath. - Refuses to run when a shade module has no dependency tree, rather than regenerating the rest and producing a diff that looks complete but is not, and skips xtable-utilities in step with the validator. validate_shaded_license_coverage.sh: - Fails when a non-Apache-2.0 dependency in LICENSE-bundled has no META-INF/licenses/LICENSE-<artifactId>, and also in the reverse direction, when a license text has no bundled dependency behind it. Checking one direction only is what let orphaned texts accumulate (apache#865). - Builds its module list with find and grep instead of ripgrep. ripgrep is not installed by mvn-license-check.yml and is not present on the GitHub ubuntu-latest runner, so this gate has never actually run in CI: the call sits in a process substitution where errexit cannot see it fail, the module list came back empty, and the script printed "No modules with maven-shade-plugin were found" and exited 0. Every License Check run on main reports success without validating anything. An empty module list is now a failure. - Downgrades the includes-vs-tree comparison to a warning for xtable-hive-metastore only, via an explicit KNOWN_INCLUDES_DRIFT list. That module's include list was written for a Hive 2.x dependency set: 25 entries name dependencies that are no longer resolved and 97 runtime dependencies are missing from it. Reconciling them changes what the shaded jar bundles, so it is a release decision rather than a tooling fix, tracked in apache#880. Running main's own unmodified validator with ripgrep available reproduces the same failure, so the drift is pre-existing; fixing the fail-open above is simply what made it visible. Every other check, for every module, stays blocking. - Parses LICENSE-bundled by calling the generator rather than reimplementing the parse in awk. The two implementations detected a family heading differently and could disagree about which dependencies need a text. javolution's family is recorded as MIT rather than the BSD its 5.5.1 POM declares. The project relicensed: that POM was published in 2010 and points at http://javolution.org/LICENSE.txt, which is long dead, there is no 5.5.1 tag from which the 2010 text could be recovered, and the LICENSE the project publishes today is MIT. license_overrides/LICENSE-javolution is that text verbatim, so the recorded family now matches the text actually shipped. Both are ASF Category A, so the artifact's licensing category is unchanged. This is what the new family-vs-text check flagged. junit is corrected from the Common Public License to the Eclipse Public License 1.0. An earlier revision of this change cited junit as the case where a jar ships someone else's license text and so a curated override must win. That is true of junit 4.11, which ships Hamcrest's BSD text, but 4.12 is what is bundled here and it ships its own correct EPL 1.0 text under the non-standard name LICENSE-junit.txt. The curated CPL override was therefore wrong and is removed; a last-resort jar-filename fallback picks the text up instead. Coordinate lists in LICENSE-bundled/NOTICE-bundled are unchanged. Regenerating them requires first reconciling xtable-hive-metastore's shade <includes> with its runtime tree, which drifted over a Hive major version and is tracked in apache#880. Closes apache#700
a611ada to
190a477
Compare
What
The bundled (shaded) jars list their third-party dependencies in
META-INF/LICENSE(LICENSE-bundled), and the banner says "See licenses/ for text of these licenses" — but many bundled non-Apache-2.0 dependencies shipped no license text at all. This adds the missing texts and makes the tooling keep them complete, accurate and enforced.Closes #700. Supersedes #866 (see below).
Background
The earlier tooling (
generate_shaded_license_metadata.py+validate_shaded_license_coverage.sh) already made the coordinate listing inLICENSE-bundledcomplete and validated. The remaining gap (raised in the issue's follow-up comment) was the actual license text files underMETA-INF/licenses/.Review of the first revision (thanks @vinishjail97) then showed the generator could not complete a run across all shade modules at all, and that several of its results were wrong rather than merely missing. Most of the diff below is the result of that round.
Changes
generate_shaded_license_metadata.pyRegenerates each module's
META-INF/licenses/directory. For every non-Apache-2.0 bundled dependency it writesLICENSE-<artifactId>, sourced from a curated override (human-verified), then the dependency's own jar, and fails loudly if a dependency has neither.Resolves everything a run would write before writing any of it. A failure used to leave license texts deleted and
LICENSE-bundled/NOTICE-bundledrewritten for the modules already processed, so the only recovery was to discard the whole run withgit checkout. A failing run is now a no-op across all modules.Parses classified artifacts correctly. The version is the second-to-last field of a dependency-tree line, not
parts[3], which is the classifier on a six-field line. This aborted the run onorg.apache.hudi:hudi-io:jar:shaded:1.2.0and, for the nine classified coordinates an override happened to cover, silently wrote a classifier whereLICENSE-bundledwants a version (io.netty:netty-transport-native-epoll:linux-aarch_64). Atestsclassifier is now excluded alongsidetest-jar—org.apache.hbase:hbase-common:jar:testswas being treated as a bundled runtime dependency.Reads POMs that Maven accepts but ElementTree does not. Two distinct cases, both authentic artifacts whose SHA-1s match Maven Central:
hadoop-project-3.1.0.pomcontains<Xlint:-unchecked/>, an undeclared namespace prefix with a hyphen-leading local name. expat rejects the whole file; it is the parent of the hadoop 3.1.0 yarn artifacts.hadoop-yarn-client-2.7.1.pomopens<project xmlns:pom="…">, binding the Maven namespace to a prefix, so every element is unqualified and the namespaced XPaths matched nothing.Lookups now match on local name, with a text-scan fallback when a POM will not parse.
Drops 18 license-family overrides that only existed because of those parsing bugs, including
org.apache.hadoop. Also dropsxml-apis, which claimedApache Software License 1.1while both its POM and its jar's ownlicense/LICENSEcarry the Apache 2.0 text.Checks the license text against the family resolved from the POM. Nothing previously tied the two together, so a jar shipping the wrong license file was attributed wrongly and silently. This is what caught the junit error below.
Derives the bundled set from the runtime tree intersected with the shade
<includes>, so the metadata describes what is inside the jar rather than what is on the classpath.Decodes embedded license/NOTICE files as strict UTF-8 instead of substituting U+FFFD for bytes it cannot read, which silently mangled older latin-1 texts.
Refuses to run when a shade module has no dependency tree, rather than regenerating the rest and producing a diff that looks like a full regeneration but is not.
xtable-utilitiesis skipped explicitly, in step with the validator.validate_shaded_license_coverage.shFails when a non-Apache-2.0 dependency in
LICENSE-bundledhas noMETA-INF/licenses/LICENSE-<artifactId>, and in the reverse direction, when a license text has no bundled dependency behind it. Checking one direction only is what allowed orphaned texts to accumulate — this is Orphaned license files in bundled jars #865, so [865] Remove orphaned license files from bundled jars #866 can be closed as superseded.Builds its module list with
find/grepinstead ofripgrep. This was a fail-open, and a worse one than I first thought:mvn-license-check.ymlnever installs ripgrep and the GitHububuntu-latestrunner does not ship it, so this gate has never actually run in CI. The call sits in a process substitution whereerrexitcannot see it fail, so the module list came back empty and the script printed "No modules with maven-shade-plugin were found" and exited 0. Every License Check run onmainreports success without validating anything — from the latest run on main:An empty module list is now a failure.
Downgrades the includes-vs-tree check to a warning for
xtable-hive-metastoreonly, via an explicitKNOWN_INCLUDES_DRIFTlist, because fixing the fail-open above immediately surfaced a pre-existing drift in that module. See xtable-hive-metastore shade <includes> has drifted from its runtime dependency tree #880 and the open items below. Every other check, for every module, stays blocking — verified by planting a bogus<include>inxtable-aws, which still fails.Parses
LICENSE-bundledby calling the generator (--non-apache-artifact-ids) rather than reimplementing the parse in awk. The two implementations detected a family heading differently and could disagree about which dependencies need a text.junitis corrected from CPL 1.0 to EPL 1.0The curated override shipped the Common Public License, but junit 4.12 — the version bundled here — is EPL 1.0, and its jar carries the correct EPL text under the non-standard name
LICENSE-junit.txt. The wrong text was being shipped inxtable-hive-metastore. The override is deleted, a last-resort jar-filename fallback picks up the correct text, and the committedLICENSE-junitis corrected.Two other claims from the first revision no longer hold and have been removed above: that
org.apache.hadoopneeds to be treated as Apache-2.0 by override (it resolves from its own POM chain once the parser is fixed), and that license texts are keyed off the committed coordinate list rather than a resolved tree (they now come from the family groups the generator already has in memory, which removed a write-then-parse round-trip).Result
Every non-Apache-2.0 bundled dependency has a license text:
xtable-aws5/5,xtable-hive-metastore21/21,xtable-hudi-support-extensions3/3.The hive-metastore count is 21 rather than the 29 quoted in the first revision because the bundled set is now the runtime tree ∩ shade
<includes>; the other eight are runtime dependencies that maven-shade is not told to include, so they are not in the artifact and must not have texts generated for them.Testing
./mvnw apache-rat:check -Brelease/scripts/validate_shaded_license_coverage.shpython3 release/scripts/generate_shaded_license_metadata.pyjavolution, see below. It could not complete at all before this round.bash -n/python3 -m py_compileAlso verified by hand:
LICENSE-not-a-real-depproducesFAIL … orphaned META-INF/licenses/ text.git statusshowing no metadata changes.KNOWN_INCLUDES_DRIFTentry is scoped: planting a bogus<include>inxtable-awsstill producesFAIL, so only the named module's includes check is downgraded.PATH, which is the condition CI actually runs under.-pl xtable-hive-metastore -amand the four-module invocation produce byte-identical trees.Two open items
1.
javolution:javolution:5.5.1needs a decision. Its POM declaresBSD License(urlhttp://javolution.org/LICENSE.txt, long dead); the curated text in the repo is the MIT license with a 2017 copyright, for a 2010 artifact; the jar carries no license file. The text predates this PR — it arrived with #691 and this PR only relocated it intolicense_overrides/. Rather than guess, the generator refuses on it, which is what the new family check is for. Options: confirm the MIT text's provenance and pin the family with a commented override; source javolution 5.5.1's real BSD text from an archived copy; or take it to legal-discuss.2.
xtable-hive-metastoreshade<includes>has drifted — pre-existing, now tracked in #880. Against the current runtime tree, 25 includes name dependencies that are no longer resolved (ant:ant,asm:*,javax.mail:mail,oro:oro,tomcat:jasper-*, …) and 97 runtime dependencies are missing from the list (all of jetty 9.x, jersey 2.x, hk2, calcite, thehbase-*server modules, …). The list reads as written for a Hive 2.x dependency set and never updated for 3.1.3.This PR touches no
pom.xml, and running main's own unmodified validator with ripgrep available reproduces the identical failure — so the drift is pre-existing and fixing the fail-open is simply what made it visible. It is handled here with the one-moduleKNOWN_INCLUDES_DRIFTentry described above rather than by changing the poms, because the two candidate fixes (grow the include list, or narrow those dependencies toprovided) have materially different consequences for what the published artifact bundles. That is a release decision; #880 has the full evidence and acceptance criteria.This is also why the coordinate lists in
LICENSE-bundled/NOTICE-bundledare left unchanged here: regenerating them would drop those 25 dead entries and break the separate "every shade include is represented in bundled license metadata" check, which currently passes only because the committed metadata predates the drift.Scope
LICENSE-bundled/NOTICE-bundledare unchanged (see open item 2).xtable-utilities(unpublished, already skipped by the validator) remains out of scope, now via an explicit skip list rather than by relying on a dependency tree being absent. Covering it would need ~32 curated texts plus a family decision fororg.openjdk.jol:jol-core, which is GPLv2-with-Classpath-Exception and deliberately shaded. The GPLv2+CPE family mapping is added so the module can be un-skipped later without hitting an unmapped family.main(8 commits ahead, none touching these files).