Skip to content

feat(boot): build 4.0.0-4.0.7 from a third layout era - #250

Open
amondnet wants to merge 4 commits into
mainfrom
amondnet/issue-137-boot-4-0-x-era
Open

amondnet wants to merge 4 commits into
mainfrom
amondnet/issue-137-boot-4-0-x-era

Conversation

@amondnet

@amondnet amondnet commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Closes #137

What

Spring Boot 4.0.0–4.0.7 were refused by eraFor. They sit between the two Boot eras: 4.0.0 moved the Antora component to documentation/, but the root-aggregate-content archive is not published until 4.0.8. The component path and the assembly moved apart, so neither existing era covered the eight releases between them.

This adds a third era for 4.0.0<4.0.8: the 4.x component path with ADR-0004's synthesized assembly, against the inputs 4.x moved. Declared oldest first, the table is now 3.3.0-<4.0.0 synthesized, 4.0.0-<4.0.8 synthesized (4.x paths), >=4.0.8 archive.

Widening a neighbour cannot express this — the 3.x era's paths do not exist at these tags, and the archive era's assembly would merge a zip that 404s. Reasoning and measurements are recorded in ADR-0005; ADR-0004 is untouched and still governs 3.3–3.x.

Measured, not assumed (2026-09-17)

Question the issue asked first Answer
Which 4.0.x jars ship META-INF/spring-configuration-metadata.json 103, measured two independent ways that agree exactly: the partials the 4.0.8 archive ships, and the artifacts publishing a 4.0.0 and 4.0.7 jar with the file. Of the 34 other v4.0.0 modules, 4 publish no jar and 30 publish one with no metadata — spring-boot-test among them, as in 3.x
Does the attributes properties file keep its shape Yes — same key=value shape, and 4.0.0's file is byte-identical to 4.0.8's (123 entries against 3.5.16's 111)
Is the BOM script readable at platform/ Yes — same library(...)/links DSL

The regression risk the issue flagged

AntoraAsciidocAttributes.java changed with the restructure: 4.x reads Jackson 3 from the tools.jackson coordinates, keeps the 2.x line as a second Jackson 2 Bom behind a new version-jackson2-databind, and drops pulsar-client-reactive-api. Running the port's 3.x table against a 4.x BOM silently withholds four attributes the corpus links through.

So the addDependencyVersion table is split into era-scoped BOOT_3_MANAGED_VERSIONS / BOOT_4_MANAGED_VERSIONS, threaded through SynthesisSources into both synthesizeAttributes and versionSourceBoms so the BOM fetch and the synthesis cannot disagree about which coordinates exist.

It is era-scoped rather than a union because both lines manage com.fasterxml.jackson.core:jackson-databind — a union would emit version-jackson2-databind for 3.x, where upstream names no such attribute. (Gating each row on its library being declared in the BOM was tried first and dropped: right answer, wrong reason, since upstream resolves the coordinate without consulting the library.)

Verification

Ground truth. 4.0.8 is one patch above the range and shares the module split, the moved paths and the Jackson coordinates. Reconstructing it from its tag and diffing against the descriptor its own content archive ships:

End to end under --strict, with the 4.0.8 archive build as the control:

Counter 4.0.0 4.0.7 4.0.8 (archive)
exit code 0 0 0
pages 147 147 239
synthesized attributes 899 900 n/a
unresolved attribute references 2 2 2
unresolved configprop: 0 0 0
empty include-code:: groups 1 1 1

The two residues are the same two files in all three builds — tutorial/first-application and how-to/native-image/developing-your-first-application, whose [source,shell] blocks omit subs="attributes" upstream. The 92-page gap is the generated appendix, the same Gradle-output gap ADR-0004 accepted for 3.x.

3.x non-regression checked at 3.3.0 and 3.5.16: no version-jackson2-databind, Jackson values unchanged on the 2.x coordinates.

Done when

$ bun run scripts/detect-upstream-versions.ts --project boot
boot: skipping 1 version(s) with unpublished upstream artifacts: 4.1.0
boot: 8 missing GA version(s): 4.0.0, 4.0.1, 4.0.2, 4.0.3, 4.0.4, 4.0.5, 4.0.6, 4.0.7

Tests

421 pass, 0 fail (was 382). No test was weakened or deleted. Six tests encoded the old "4.0 gap" behaviour and were retargeted at boundaries that still exist — for example "an era ceiling is exclusive" now asserts that 4.0.0 selects the 4.x era and 4.0.8 the archive era, instead of asserting 4.0.0 is refused. New coverage: era selection at 4.0.0/4.0.7/4.0.8, the 103-artifact metadata set, and versionSourceBoms resolving a different BOM set per era table.

bun test, bunx tsc --noEmit -p . and bun run lint are clean.

Out of scope

Releasing the eight versions and recording them in catalog.json is a separate step, to be done after merge. Tag pushes must go three at a time — GitHub creates no push event for the fourth and later tags in one push (#61).


Summary by cubic

Adds a third layout era so Spring Boot 4.0.0–4.0.7 become buildable; previously they were refused because 4.0.0 moved the Antora component to documentation/ while the content archive stayed unpublished until 4.0.8. The new era reconstructs the generated half from the tag's 4.x paths, and the managed-version attribute port is split era-scoped so 4.x's renamed Jackson coordinates register without leaking a version-jackson2-databind attribute into 3.x output.

New Features

  • The synthesized era reads the moved inputs (documentation/…, platform/spring-boot-dependencies/build.gradle) plus 103 spring-boot-* metadata jars; reconstructing 4.0.8 from them reproduces all 876 attributes of its shipped descriptor, 0 differing.
  • These releases omit the generated appendix (147 pages against 4.0.8's 239), the same gap ADR-0004 accepted for 3.x.
  • 3.3.0 and 3.5.16 are regression-checked clean: no version-jackson2-databind, Jackson values unchanged on the 2.x coordinates.
  • detect-upstream-versions.ts now lists 4.0.0–4.0.7; 4.1.0 stays blocked by the availability gate because its zip is unpublished.
  • Reasoning and measurements are recorded in ADR-0006.

Migration

Written for commit 12258e0. Summary will update on new commits.

4.0.0-4.0.7 sit between the two Boot eras: 4.0.0 moved the Antora component
to `documentation/`, but the `root-aggregate-content` archive is not published
until 4.0.8 (404 at 4.0.0 and 4.0.7, 200 at 4.0.8, probed 2026-09-17). The
component path and the assembly moved apart, so `eraFor` returned `undefined`
and the eight releases were refused.

Declare a third era for `4.0.0`-`<4.0.8`: the 4.x component path with
ADR-0004's synthesized assembly, against the inputs 4.x moved
(`documentation/.../src/main`, `platform/spring-boot-dependencies/build.gradle`).
Widening a neighbour cannot express this — the 3.x era's paths do not exist at
these tags, and the archive era's assembly would merge a zip that 404s.

`BOOT_4_METADATA_ARTIFACTS` is measured, not carried over: Boot 4 split three
module trees into ~140 projects, and 103 of them both ship a partial in the
4.0.8 archive and publish a 4.0.0/4.0.7 jar carrying
`META-INF/spring-configuration-metadata.json`. The two measurements agree
exactly. `spring-boot-test` is excluded, as in 3.x.

Split the attribute port's `addDependencyVersion` table into era-scoped
`BOOT_3_MANAGED_VERSIONS` / `BOOT_4_MANAGED_VERSIONS`, threaded through
`SynthesisSources` into both `synthesizeAttributes` and `versionSourceBoms` so
the BOM fetch and the synthesis cannot disagree. 4.x reads Jackson 3 from the
`tools.jackson` coordinates and adds `version-jackson2-databind`; running the
3.x table against a 4.x BOM withholds four attributes the corpus links through.
The table is era-scoped rather than a union because both lines manage
`com.fasterxml.jackson.core:jackson-databind`, so a union would emit
`version-jackson2-databind` for 3.x, where upstream names no such attribute.

Verified against 4.0.8 as ground truth, one patch above the range: the
reconstruction reproduces all 876 attributes of the descriptor its own content
archive ships, 0 differing, 0 missing. End to end under `--strict`, 4.0.0 and
4.0.7 convert with exit 0, 147 pages, 0 unresolved `configprop:`, and exactly
2 literal attribute references — the same two files the 4.0.8 archive build
leaves, both upstream's own missing `subs="attributes"`. 3.x checked for
regression at 3.3.0 and 3.5.16.

`detect-upstream-versions.ts --project boot` now reports 4.0.0-4.0.7 as
buildable; 4.1.0 stays excluded by the availability gate.

Refs #137
@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 11 complexity · 0 duplication

Metric Results
Complexity 11
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@amondnet
amondnet marked this pull request as ready for review September 17, 2026 03:00
@greptile-apps

greptile-apps Bot commented Sep 17, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with the previous synthesis-testing gap addressed and no new actionable issues identified.

Summary

Adds a third Spring Boot layout era, enabling 4.0.0–4.0.7 through synthesis from the relocated documentation inputs and 103 metadata jars.

  • Uses era-specific managed-version tables for both BOM selection and attribute synthesis.
  • Preserves the 3.x synthesis path and the archive-based assembly from 4.0.8 onward.
  • The latest change addresses the previous testing finding: synthesis assertions distinguish Jackson 2 and Jackson 3 coordinates and ensure 3.x does not emit version-jackson2-databind.
  • No new actionable issues were identified.

Reviews (3) · Last reviewed commit: "chore(tests): apply review suggestions o..."

Comment thread tests/unit/antora-attributes.test.ts
#248 landed ADR-0005 on main (supersession on the publish path) while this
branch was open, so both sides claimed 0005. Renumber this one and follow the
references through README.md, the knowledge note and the index.
…ot-4-0-x-era

# Conflicts:
#	.please/docs/decisions/index.md
@codecov

codecov Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.90446% with 8 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
scripts/fetch-upstream.ts 0.00% 8 Missing ⚠️

📢 Thoughts on this report? Let us know!

Exercise synthesizeAttributes with both era tables against one managedVersions map carrying the 2.x and 3.x Jackson coordinates at once, so a row reading the wrong groupId resolves to the other line's version instead of being dropped by setIfPresent.
@sonarqubecloud

Copy link
Copy Markdown

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.

Build Spring Boot 4.0.0–4.0.7: the component is in the tag, only the content archive is missing

1 participant