Skip to content

build(docx): count render-docx in the coverage aggregate and gate its Stable API with japicmp - #1020

Merged
DemchaAV merged 3 commits into
2.5-devfrom
build/docx-coverage-aggregate
Nov 6, 2026
Merged

DemchaAV merged 3 commits into
2.5-devfrom
build/docx-coverage-aggregate

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Nov 6, 2026 •

Copy link
Copy Markdown
Owner

Why

graph-compose-render-docx was invisible to both release guards:

  • Coverage. Its tests ran without the JaCoCo agent, and graph-compose-coverage did not list it, so the Word export had no coverage figure and its classes were outside the ratchet.
  • Binary compatibility. japicmp diffed core and templates only. docs/api-stability.md promises that constructing DocxSemanticBackend and calling session.export(backend, path) "stays the Stable path", but nothing checked it, so the class, its no-argument constructor, name() and export(...) could break in a 2.x minor with CI green.

Measured before choosing the gate's shape: render-docx 2.5.0-SNAPSHOT against the published 2.0.0 and 2.4.1 reports additions only. With @Beta excluded, both read "No changes". Its public API did not change between 2.0.0 and 2.4.1, and everything added in 2.5 is @Beta. So no Stable signature is broken today, and a diff against the 2.x floor holds exactly the Stable surface.

What changed

Coverage aggregate

  • render-docx/pom.xml runs jacoco-maven-plugin prepare-agent at the pinned jacoco.plugin.version, as render-pdf and templates do.
  • coverage/pom.xml depends on render-docx, unpacks its classes for the check, and merges render-docx/target/jacoco.exec. Floors stay 0.875 / 0.68.
  • VersionConsistencyGuardTest.jacocoPluginVersionAgreesAcrossModules now holds render-docx's agent version too.
  • New VersionConsistencyGuardTest.coverageAggregateReadsEveryMeasuredModule holds each measured module (core, render-pdf, render-docx, templates) to all four inputs: its dependency, its unpacked classes, its merged exec, and the agent in its own pom. All four are read from the parsed pom, so a commented-out line counts as missing. It also requires compile scope on each measured dependency (report-aggregate skips a test-scope one) and the qa suites' exec in the merge. None of the four fails when it is missing. JaCoCo's merge skips an absent exec, and a module dropped from every list is simply not reported while the aggregate still clears its floors.

japicmp gate for render-docx

  • A japicmp profile in render-docx/pom.xml: one execution, japicmp-against-baseline, against japicmp.baseline = 2.0.0, like the engine's gate. It excludes only the @Internal marker, sets ignoreMissingOldVersion=false, and fails on binary breaks; source breaks are report-only.
  • ci.yml, the binary-compat job:
    • a new render_docx path filter (render-docx/src/**, render-docx/pom.xml) in its condition;
    • drops the cached graph-compose-render-docx before resolving;
    • adds :graph-compose-render-pdf,:graph-compose-render-docx to -pl. render-pdf is there only because render-docx compiles against it; it has no profile;
    • a test -s for the new report, and uploads it.
  • publish.yml: the same cache drop, -pl and report check.
  • scripts/cut-release.ps1: only Step 5b's three lists change — -pl, $japicmpReports and $japicmpBaselines (the 2.0.0 pin) — plus the one line that reads render-docx/pom.xml for that pin, and Step 5b's header comment, which now names render-docx. BinaryCompatibilityGateGuardTest finds every pom with a japicmp profile and requires the release-time run to diff it, check its report and drop its cached baseline, so the cut checks render-docx before the tag as it checks core. The guard now also checks the baseline list, which it did not before: each gated module's entry must read its own pom's pin property. Step 3a and the Update-Japicmp* pin-moving functions are untouched: the floor does not move inside 2.x.
  • BinaryCompatibilityGateGuardTest:
    • render-docx is added to REQUIRED_EXECUTIONS and CACHED_ARTIFACTS;
    • the two templates-only checks now cover both templates and render-docx: an unresolvable baseline fails the build, and the gate excludes only @Internal. They are renamed theTemplatesAndDocxGates….
  • VersionConsistencyGuardTest: render-docx's japicmp.version lockstep and its pin in JAPICMP_BASELINE_PINS, so the pin cannot name the version being built.
  • docs/api-stability.md (Binary-compatibility enforcement): render-docx is gated against the floor; the four Stable members are named. Like the engine's floor pin, this one will need a decision when 3.0 opens. It also says that a member that becomes Stable after 2.0.0 is not held by a floor-only diff, and that guarding one with a previous-release baseline belongs to graduating the DOCX @Beta API to Stable, which ROADMAP.md lists as still open after 2.5. docs/contributing/release-process.md (Step 5b), CONTRIBUTING.md, CHANGELOG.md (Build), and comments in ci.yml, coverage/pom.xml, templates/pom.xml and the post-2.0 roadmap's coverage section are updated to match. The coverage/pom.xml comment now says the floors trail the aggregate, and leaves raising them to a separate ratchet step.

No public API changes, so the knowledge pack is unchanged.

Verification

  • Coverage numbers come from the CI reactor command (clean verify over core … coverage): BUILD SUCCESS, "All coverage checks have been met" over 1227 classes (1073 before).
    • render-docx alone: 96.90% instructions, 85.00% branches. These count its own tests and the qa suites.
    • Aggregate: 93.99% / 77.52% before, 94.88% / 81.37% after.
    • Tests in that run, 0 failures: core 842, render-pdf 339, render-docx 2545, templates 128, qa 1910.
  • Agent cost: render-docx tests took 137–139 s with the agent and 138–154 s without (two runs each, 2545 tests).
  • The gate as CI runs it: ./mvnw -B -ntp -DskipTests -P japicmp clean verify -pl :graph-compose-core,:graph-compose-templates,:graph-compose-render-pdf,:graph-compose-render-docx gave BUILD SUCCESS in 48 s. All four reports were written, including render-docx/target/japicmp/japicmp-against-baseline.xml.
  • Fails closed: making DocxSemanticBackend() package-private fails the same command with tests skipped (-Dmaven.test.skip=true). japicmp itself fails it: "There is at least one incompatibility: … DocxSemanticBackend():CONSTRUCTOR_LESS_ACCESSIBLE". File restored byte-identical.
  • Guards: BinaryCompatibilityGateGuardTest 7, VersionConsistencyGuardTest 24, CiGateCoverageGuardTest 3, CiGuardListGuardTest 1, PublishTrainGuardTest 7 — 0 failures.
  • Sabotages: each break below was applied on its own, failed the guard method that owns it (surefire failures, not build errors), and was restored byte-identical.
    • Coverage, 11: agent version drift; agent goal removed; exec include removed; exec include commented out; classes not unpacked; unpack list commented out and replaced without render-docx; dependency removed; dependency at test scope; qa exec not merged; unpack execution renamed; merge execution renamed (the last two fail with the guard's own message, not a null dereference).
    • japicmp wiring, 15: CI -pl, condition, report check and cache drop; publish -pl and report check; cut-release.ps1 -pl, render-docx baseline entry removed, that entry reading the core pom, and the templates previous-release entry removed; ignoreMissingOldVersion=true; an extra package exclude; report-only (breakBuild…=false); baseline set to the working version; japicmp.version drift.
  • Full gate on the reviewed tree: GATE PASS — reactor clean verify (core 843, render-pdf 339, render-docx 2545, templates 128, qa 1910; 0 failures; coverage ratchet met), the four knowledge checks, core javadoc, install and the examples tests (93). The last commit changes only the null checks in coverageAggregateReadsEveryMeasuredModule (CodeQL); that test class was re-run, 24/0.
  • Not run: cut-release.ps1 itself, by instruction; release-script-check.yml covers it on CI.

… Stable API with japicmp

render-docx ran its tests without the JaCoCo agent and was outside the
coverage aggregate, and japicmp did not diff it, so the Stable members of
DocxSemanticBackend could break in a 2.x minor with every check green.

Coverage: the module's pom runs prepare-agent at the pinned JaCoCo version,
and coverage/pom.xml depends on it, unpacks its classes and merges its exec.
The module measures 96.90% instructions and 85.00% branches; the aggregate
rises from 93.99% / 77.52% to 94.88% / 81.37%; the floors are unchanged.
VersionConsistencyGuardTest holds the agent version and, in a new test, each
measured module to its dependency, unpacked classes, merged exec and agent.

japicmp: one execution against the 2.x floor, 2.0.0, as the engine's gate
does, excluding only @internal and failing on a baseline it cannot resolve.
The pull-request job (also run on render-docx/src/** and its pom), the
publish workflow and cut-release.ps1 Step 5b diff it beside core and
templates; in cut-release.ps1 only Step 5b's -pl, report and baseline
lists change. BinaryCompatibilityGateGuardTest and VersionConsistencyGuardTest
hold the wiring and the pin, and the guard now also checks Step 5b's
baseline list. docs/api-stability.md says a member that becomes Stable
after 2.0.0 is not held by a floor-only diff.
The Step 5b baseline check requires each gated module's entry to read
its own pom's pin property; the coverage guard requires compile scope on
each measured dependency and the qa suites' exec in the merge.
api-stability.md says "every pin", and names graduating the DOCX @beta
API to Stable (ROADMAP.md) instead of a stage name no public doc defines.
CodeQL read the AssertJ not-null checks as no check at all and flagged
the dereference after them. An explicit AssertionError says which
execution coverage/pom.xml lost, and no path reaches a null.
@DemchaAV
DemchaAV marked this pull request as ready for review November 6, 2026 10:26
@DemchaAV
DemchaAV merged commit 176e879 into 2.5-dev Nov 6, 2026
14 checks passed
@DemchaAV
DemchaAV deleted the build/docx-coverage-aggregate branch November 6, 2026 10:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants