ci(java): require explicit java_version for variant builds, drop repo-var fallback#35987
ci(java): require explicit java_version for variant builds, drop repo-var fallback#35987sfreudenthaler wants to merge 8 commits into
Conversation
…-var fallback The java-variant workflow still fell back to RELEASE_JAVA_VARIANT_VERSION / RELEASE_JAVA_VARIANT_SUFFIX when dispatched with an empty java_version. With Java 25 now the default (#35914) those vars point at the default itself, so an empty dispatch produced a redundant duplicate of the primary release image — and deleting the vars without a guard would have made an empty dispatch fall through to .sdkmanrc with no suffix, overwriting the primary release tags. Make .sdkmanrc the single source of truth for the default Java: - java_version is now a required dispatch input; all vars.RELEASE_JAVA_VARIANT_* fallbacks are removed (build, deployment, release, concurrency). - New fail-fast guard in extract-version reads .sdkmanrc from the release branch being built and errors when the requested version is empty or equal to the default. - Header docs updated; run-name simplified for the dispatch-only trigger. After this merges, the RELEASE_JAVA_VARIANT_VERSION and RELEASE_JAVA_VARIANT_SUFFIX repository variables should be deleted. Fixes #35986 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Claude finished @sfreudenthaler's task in 3m 50s —— View job PR Review
Overall this is well-constructed. The approach is sound: single source of truth for the Java version, fail-fast guard on the variant workflow, self-healing base image. A few things worth a second look:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ebcb99b3dc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
sfreudenthaler
left a comment
There was a problem hiding this comment.
ready for review
Addresses Codex P1 on #35987: with the repo-var fallback removed, an empty artifact_suffix let each phase derive its own default — maven-job derives java${major} while the deployment phase derives java-${major} — so the build uploaded docker-build-context-java21 and deployment tried to download docker-build-context-java-21, failing after a successful build. Derive the effective suffix once in extract-version (explicit input wins, else java-{major} per the release variant convention) and pass the same value to the build, deployment, and release phases. Also validates that java_version starts with a numeric major before deriving. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Strip \r when parsing .sdkmanrc: a CRLF-committed file (nothing in .gitattributes normalizes it) would leave a trailing \r in default_java, making the same-as-default equality guard silently fail open. - Fail with a clear message when the release branch / .sdkmanrc cannot be read via the API, or when the file has no java= entry, instead of surfacing a raw gh error. Addresses review feedback on #35987. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e blocks Team is Mac/Linux only and the current blob is clean LF, so the unreachable-in-practice error wrappers (unreadable branch, missing java= entry) aren't worth the reading cost; a failing gh api call already fails the step. Keep the zero-cost tr -d '\r' so a CRLF-committed file can never make the same-as-default guard fail open. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Does this, or can we make this, update the mvn parent/pox.xml variables ? These in particular:
<jdk.min.version>25</jdk.min.version>
<maven.compiler.argument.source>${maven.compiler.source}</maven.compiler.argument.source>
<maven.compiler.argument.target>${maven.compiler.target}</maven.compiler.argument.target>
<maven.compiler.argument.testSource>${maven.compiler.testSource}</maven.compiler.argument.testSource>
<maven.compiler.argument.testTarget>${maven.compiler.testTarget}</maven.compiler.argument.testTarget>
Or is this not a good idea? It would be very nice to have .sdkman variable be the single source of truth.
let me look tonight. agree and it's in the spirit of what i'm trying to push towards in this PR |
…t Java version Addresses review feedback on the variant workflow: changing the default Java version previously required hunting down literals in parent/pom.xml alongside .sdkmanrc. Now a bump is .sdkmanrc plus one number, and the build fails fast at validate if they drift. parent/pom.xml: - jdk.min.version now chains to the effective dotcms.core.compiler.release (follows both the default and deliberate -D overrides) instead of a literal - new build-helper regex-property execution derives sdkmanrc.java.major from the .sdkmanrc java entry (via the existing ext.java property load) - new enforcer requireProperty rule fails the build when dotcms.core.compiler.release.default does not match the .sdkmanrc major - dotcms.core.compiler.release.default stays a literal on purpose: IDEs derive the project language level from the static model and cannot evaluate plugin-derived properties; the enforcer guard makes drift impossible instead .mvn/maven-build-cache-config.xml: - force properties:read-project-properties, build-helper:regex-property and enforcer:enforce to run on cache hits; skipping the property loads while populating the regex-property mojo fails with unresolved parameters, and the drift guard must fire regardless of cache state maven-job action: - when java-version is overridden (variant builds), also pass -Dsdkman.java.version so the Docker image produced by the Maven build embeds the variant JDK instead of the committed .sdkmanrc default Verified: default validate passes (cached and uncached back-to-back), drift (.sdkmanrc=26 vs default 25) fails with a remediation message, variant (-Dsdkman.java.version=21.0.8-ms -Ddotcms.core.compiler.release=21) and back-compat (-Ddotcms.core.compiler.release=11) overrides pass, full reactor validate passes, and runtime.docker.sdkman.java.version resolves to the variant JDK under override. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@wezell ready for rereivew. got it down to 2 changes. that's the best claude thinks we can do while keeping good ide support. |
…tent comment, stale suffix doc - run-name: java_version is a required input, so drop the dead || '' branch - java-guard: document that .sdkmanrc is read from the branch tip while the build checks out the tag, and why divergence is harmless (explicit suffix means primary tags can never be overwritten) - maven-job: clarify the artifact-suffix fallback is for callers without a later download phase; the variant workflow always passes an explicit value Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Matches the enforcer's default binding; makes the in-phase ordering dependency on derive-sdkmanrc-java-major visible to readers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🚧 Converting to draft — design pivot agreed with @wezellParking this pending a redesign. Capturing the agreed direction from the #feat-java25 thread (Jun 5) so the context isn't lost. What this PR does today (the narrow hardening)
This is all valid and green — but it's fail-fast-if-the-version-is-wrong, which is a stepping stone, not the destination. The direction instead (@wezell)Make
Net design:
Status / urgencyJava 25 prod rollout completed Jun 8, so the variant workflow is no longer time-pressured. Reopening for review once reworked around the base-image-existence action. The pom/enforcer single-source-of-truth piece here likely survives the rework intact. |
…ing version Redesign per @wezell: make .sdkmanrc the single knob and have the pipeline build the JDK base image on demand, rather than fail-fast when it is absent. - New composite action core-cicd/ensure-java-base: anonymous existence check (buildx imagetools inspect); when missing, build+push multi-arch if Docker Hub creds are present, else build locally (--load, amd64) so the current build can still proceed. Restores the default Docker builder afterward so maven-job's subsequent plain docker build/save is unaffected. - Wire it into maven-job between get-sdkman-version and the dotCMS image build, reusing the already-resolved SDKMAN_JAVA_VERSION so base tag and FROM stay in lockstep. Single chokepoint => covers main, PR, release and variant builds. - Thread optional DOCKER_USERNAME/DOCKER_TOKEN secrets through build-phase to the publishing callers (release, variant, trunk, merge-queue, nightly, lts, manual-deploy) so a missing base is published; PR builds degrade to local build. - Refactor cicd_manual_build-java-base.yml to reuse the action (force build), removing the duplicated buildx/build-push logic. - Variant workflow: keep the manual-only required/equals-default guard, add an explicit empty-default_java check (fails loudly on a bad branch/.sdkmanrc), and document that the base image now self-heals. The pom .sdkmanrc single-source-of-truth + drift enforcer from earlier in this PR are retained unchanged. Refs #35986 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
wezell
left a comment
There was a problem hiding this comment.
Love this. Once merged, let's exercise the job by ticking our .sdkmanrc java to 25.0.2-ms
Fixes #35986
What
Makes
.sdkmanrcthe single knob for the dotCMS Java version and makes the pipeline self-heal the JDK base image instead of failing when it's missing. Follow-up to #35914 (Java 25 default) and #35915 (variant auto-build retired).Self-healing base image
The dotCMS image is
FROM dotcms/java-base:${SDKMAN_JAVA_VERSION}(dotCMS/src/main/docker/original/Dockerfile). That base was previously only ever built by the manualcicd_manual_build-java-base.ymlworkflow, so bumping.sdkmanrcto a version whose base hadn't been pre-built would break every build.core-cicd/ensure-java-base— anonymous existence check (docker buildx imagetools inspect); when the tag is missing it builds the base:--load, host arch) so the current build still resolvesFROM— the build never fails just because the base was absent.defaultDocker builder afterward somaven-job's subsequent plaindocker build/docker saveis unaffected.maven-jobbetweenget-sdkman-versionand the dotCMS image build, reusing the already-resolvedSDKMAN_JAVA_VERSIONso the base tag and theFROMbuild-arg stay in lockstep. This is the single chokepoint every Docker build flows through → covers PR, trunk, release, and variant builds.DOCKER_USERNAME/DOCKER_TOKENsecrets threaded throughcicd_comp_build-phase.ymland passed by the publishing callers (release, variant, trunk, merge-queue, nightly, lts, manual-deploy) so a missing base gets published. PR builds don't pass them → graceful local-only build. The dotCMS image build itself still pulls the public base anonymously, so these are not required for a normal build.cicd_manual_build-java-base.ymlrefactored to reuse the action (force: true), removing the duplicated buildx / build-push logic — one source of truth for how the base is built.flowchart TD SDK[".sdkmanrc / -Dsdkman.java.version"] --> RES["maven-job: resolve<br/>SDKMAN_JAVA_VERSION"] RES --> ENS["ensure-java-base action"] ENS -->|"exists on Docker Hub"| NOOP["no-op"] ENS -->|"missing + creds"| PUSH["build multi-arch + PUSH<br/>dotcms/java-base:VERSION"] ENS -->|"missing, no creds"| LOAD["build amd64 + --load locally"] NOOP --> IMG["docker build dotCMS image<br/>FROM dotcms/java-base:VERSION"] PUSH --> IMG LOAD --> IMGVariant workflow (
cicd_7-release-java-variant.yml) — manual-only guard keptworkflow_dispatch-only, so its guard never affects automated runs.java_versionstays required and an equals-default request still errors (it would be a redundant duplicate of the primary release image — the empty-dispatch protection that prevents overwriting primary Docker tags). A missing base is no longer a dead-end: it's self-healed by the sharedmaven-jobstep. Also added an explicit empty-default_javacheck so a wrong branch name or missing/malformed.sdkmanrcfails loudly instead of the equality check silently passing..sdkmanrcas single source of truth in the pom (retained from earlier review feedback)Unchanged from the prior iteration and survives the rework intact:
jdk.min.versionchains to the effective${dotcms.core.compiler.release}.build-helper:regex-propertyexecution derivessdkmanrc.java.majorfrom the.sdkmanrcjava entry.validate) whendotcms.core.compiler.release.defaultdoesn't match the.sdkmanrcmajor, naming both files in the remediation message..mvn/maven-build-cache-config.xmlgainsrunAlwaysfor the property-read / regex-property / enforcer executions so a cache hit can't skip the drift guard.Net effect — a future default-Java cutover (e.g. java-29) is: update
.sdkmanrc+ one number inparent/pom.xml, dispatch/merge as usual, and the base image is produced automatically. Forget the pom number and every build fails atvalidatewith remediation instructions.Why
After #35915 the variant workflow is manual-only, but an empty dispatch still silently fell back to repo vars (now pointing at the Java 25 default) — a redundant duplicate of the primary image; deleting those vars without a guard would let an empty dispatch overwrite the primary release Docker tags. More broadly, the only way to introduce a new Java version's base image was a manual pre-build step. This PR removes both foot-guns: the workflow requires a deliberate variant version, and the base image builds itself on demand wherever it's needed.
Verification
actionlintclean on all changed workflows; every changed YAML parses.ensure-java-basedecision logic dry-run across all paths: exists→no-op, missing+creds→push multi-arch, missing+no-creds→load amd64, force+push=false→validation-only,push=true+no-creds→error../mvnw validateresults (default / variant-override / drift-simulation) still hold.cicd_manual_build-java-base.ymlfor a throwaway version; dispatch the variant workflow against a Java version whose base is absent and confirm it self-heals then builds.Delete the now-unused repository variables (settings, not code):
🤖 Generated with Claude Code