From 7227da98caaae0f5d19fa47c1399ca7fa4323ef0 Mon Sep 17 00:00:00 2001 From: Mohsen Zainalpour Date: Wed, 5 Aug 2026 18:29:40 -0400 Subject: [PATCH] fix(build): pin javadoc strictness so a -D flag cannot silence it (#205) maven-javadoc-plugin binds failOnError/skip/doclint to Maven USER PROPERTIES, and a property only supplies the value when the POM does not. Left unset, `-Dmaven.javadoc.failOnError=false` on any mvn command line (including publish.yml's real deploy) silences javadoc without touching a file in the repo, invisible to both existing guards. A POM value takes precedence over the property, so pinning makes the override impossible rather than merely detectable. The #203 sweep is extended to REQUIRE the pin, because deleting it restores the overridable state without introducing any permissive value. --- CONTRIBUTING.md | 42 +++- pom.xml | 11 + scripts/check-javadoc-strictness.py | 309 +++++++++++++++++++++++++--- 3 files changed, 320 insertions(+), 42 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 99c8dc1..96ccdc6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,8 +30,8 @@ installing). It runs automatically in the release lane (`-Prelease`, i.e. CI's r deploy); to run it locally, add `-Dinvoker.skip=false`. Javadoc errors fail the build. A broken `{@link}`, an unresolvable reference, or a malformed tag -is an error under the JDK's default doclint, and the javadoc jars published to Maven Central are -built with the plugin's default `failOnError=true`. Javadoc only runs in the release lane, so a +is an error under doclint, and the javadoc jars published to Maven Central are built with +`failOnError` on — both pinned explicitly in the root pom (see *The pin*, below). Javadoc only runs in the release lane, so a plain `./mvnw verify` will not catch it, but CI's release-smoke will — check it locally with: ```sh @@ -61,7 +61,7 @@ override elsewhere would leave it green. The sweep runs `help:effective-pom` ove reactor and rejects any module whose *effective* javadoc config silences errors — `failOnError`, `skip`, `skippedModules`, a `doclint` value other than `all`, an `-Xdoclint` option that disables a group, or the equivalent `maven.javadoc.*` / `doclint` **properties**, which need no `` -at all. Run it locally with: +at all. It also **requires** the pin described below to be present on every module. Run it locally with: ```sh # -DdualEmbedded matches CI, so the sweep covers rift-java-embedded too @@ -73,11 +73,37 @@ python3 scripts/check-javadoc-strictness.py --self-test # asserts the detector The module set depends on your JDK (`rift-java-embedded-jdk21` only joins on JDK 21), so a local run sweeps fewer modules than CI — pass `--require` only if you know which set to expect. -Two things it deliberately does *not* do: it reads configuration, not behaviour (that is the -canary's job), and it cannot see a `-Dmaven.javadoc.failOnError=false` added to a workflow's own -`mvn` command line. Its `--require` list in `ci.yml` names the modules the reactor must contain, so -a module dropping out of the reactor fails the sweep instead of silently shrinking it — add new -published modules there. +It reads configuration, not behaviour — proving the behaviour is the canary's job. Its `--require` +list in `ci.yml` names the modules the reactor must contain, so a module dropping out of the reactor +fails the sweep instead of silently shrinking it; add new published modules there. + +**The pin** closes the command-line gap, and is the reason the root `pluginManagement` sets these +three explicitly rather than relying on their (already strict) defaults: + +```xml + + true + false + all + +``` + +Each of these parameters binds to a Maven **user property**, and a property only supplies the value +when the POM does not. Left unset, `-Dmaven.javadoc.failOnError=false` on any `mvn` command line — +including `publish.yml`'s real deploy — silences javadoc errors for that invocation without touching +a file in the repo, where neither guard above could see it. A `` value takes +precedence over the property, so pinning makes that override *impossible* rather than merely +detectable. Verified: with the pin, a broken `{@link}` still fails the build under +`-Dmaven.javadoc.failOnError=false`, `-Dmaven.javadoc.skip=true` and `-Ddoclint=none`. + +Deleting the pin would restore the silently-overridable state without introducing any *permissive* +value, so the sweep requires it and names any module that lost it. Do not remove it. + +The sweep requires the pin on the entry Maven actually **executes**, and on any `` that +carries its own ``. Both are load-bearing: a module can override its inherited +configuration (`combine.self="override"`) at either level, which drops the pin at run time while the +inherited copy still looks pinned. If you add a javadoc `` to a module or an +execution, repeat the three pinned values in it. ## Module layout diff --git a/pom.xml b/pom.xml index 3dbb7c0..9162780 100644 --- a/pom.xml +++ b/pom.xml @@ -137,6 +137,17 @@ org.apache.maven.plugins maven-javadoc-plugin ${maven-javadoc-plugin.version} + + + true + false + all +