From 1a6ac84be10da056e72e11998daeea07e162bdcc Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 11 Oct 2026 14:04:37 +0000 Subject: [PATCH 1/5] Version all POMs in the release workflow and verify they stay in sync The release workflow bumped a hardcoded module list, so performance-test (only part of a profile) was left on 0.6.0-SNAPSHOT, which made Dependabot propose bumping it to the released 0.6.0 (#336). - add .github/scripts/project-version.sh (set|verify) discovering all tracked POMs via git - use it for the release and next-snapshot bumps and stage all POMs - fail CI and the release when any POM drifts from the root version - align performance-test with 0.7.0-SNAPSHOT --- .github/scripts/project-version.sh | 52 +++++++++++++++++++++ .github/workflows/maven-central-release.yml | 23 +++++---- .github/workflows/maven.yml | 3 ++ RELEASE.md | 4 +- performance-test/pom.xml | 2 +- 5 files changed, 69 insertions(+), 15 deletions(-) create mode 100755 .github/scripts/project-version.sh diff --git a/.github/scripts/project-version.sh b/.github/scripts/project-version.sh new file mode 100755 index 00000000..7cd09c20 --- /dev/null +++ b/.github/scripts/project-version.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# Keeps the version of every tracked pom.xml in sync with the root POM. +# +# The modules have no element, so each POM carries its own version. +# POMs are discovered via git instead of a hardcoded module list, so modules +# that are only part of a profile (e.g. performance-test) or added later are +# never left behind. +# +# project.build.outputTimestamp is left untouched; the release workflow pins +# it in a dedicated step. +# +# Usage: +# project-version.sh set set in every POM +# project-version.sh verify fail if any POM differs from the root POM +set -euo pipefail + +POM_PATHSPEC=':(glob)**/pom.xml' + +pom_version() { + mvn -B -q -N -f "$1" help:evaluate -Dexpression=project.version -DforceStdout | tr -d '\r ' +} + +case "${1:-}" in + set) + NEW_VERSION="${2:?usage: $0 set }" + git ls-files -z -- "$POM_PATHSPEC" | while IFS= read -r -d '' pom; do + echo "Setting $pom to $NEW_VERSION" + mvn -B -q -N -f "$pom" versions:set -DnewVersion="$NEW_VERSION" -DgenerateBackupPoms=false \ + -DupdateBuildOutputTimestampPolicy=never + done + ;; + verify) + ROOT_VERSION="$(pom_version pom.xml)" + MISMATCHES=0 + while IFS= read -r -d '' pom; do + VERSION="$(pom_version "$pom")" + if [[ "$VERSION" != "$ROOT_VERSION" ]]; then + echo "::error file=$pom::$pom is on version $VERSION, expected $ROOT_VERSION (root pom.xml)." + MISMATCHES=$((MISMATCHES + 1)) + fi + done < <(git ls-files -z -- "$POM_PATHSPEC") + if [[ "$MISMATCHES" -gt 0 ]]; then + echo "Run '.github/scripts/project-version.sh set $ROOT_VERSION' to align all POMs." + exit 1 + fi + echo "All POMs are on version $ROOT_VERSION." + ;; + *) + echo "usage: $0 set | verify" >&2 + exit 2 + ;; +esac diff --git a/.github/workflows/maven-central-release.yml b/.github/workflows/maven-central-release.yml index 782a28e6..1d3b4ebc 100644 --- a/.github/workflows/maven-central-release.yml +++ b/.github/workflows/maven-central-release.yml @@ -63,6 +63,10 @@ jobs: CURRENT_VERSION="${CURRENT_VERSION//$'\r'/}" CURRENT_VERSION="${CURRENT_VERSION// /}" + # All POMs must share the root version, otherwise a module would be + # released and bumped from a stale version. + .github/scripts/project-version.sh verify + if [[ "$CURRENT_VERSION" != *-SNAPSHOT ]]; then echo "::error::Current POM version is '$CURRENT_VERSION', expected a -SNAPSHOT version. main must always be on a snapshot version." exit 1 @@ -85,14 +89,10 @@ jobs: VERSION=${{ steps.version.outputs.VERSION }} echo "Setting version to $VERSION" - # Update parent POM - mvn versions:set -DnewVersion=$VERSION -DgenerateBackupPoms=false - - # Update ALL module POMs. The modules have no element, so - # each must be set individually. Only core and processor are deployed - # to Maven Central, but all modules must share the same version for - # the reactor build to work correctly. - mvn versions:set -DnewVersion=$VERSION -DgenerateBackupPoms=false -pl core,processor,example,example-custom-generator + # Update ALL POMs (root and every module, including profile-only + # ones). Only core and processor are deployed to Maven Central, but + # all modules must share the same version. + .github/scripts/project-version.sh set "$VERSION" - name: Update reproducible build timestamp run: | @@ -114,7 +114,7 @@ jobs: # update to main goes through a reviewed pull request instead of a # direct push that bypasses branch protection. git checkout -B "$BRANCH" - git add pom.xml core/pom.xml processor/pom.xml example/pom.xml example-custom-generator/pom.xml + git add -- ':(glob)**/pom.xml' echo "branch=$BRANCH" >> "$GITHUB_OUTPUT" # Only commit if there are changes. Note: no "[skip ci]" so the @@ -264,12 +264,11 @@ jobs: echo "Next snapshot version: $NEXT_VERSION" # Set all POMs to the next snapshot version. - mvn versions:set -DnewVersion=$NEXT_VERSION -DgenerateBackupPoms=false - mvn versions:set -DnewVersion=$NEXT_VERSION -DgenerateBackupPoms=false -pl core,processor,example,example-custom-generator + .github/scripts/project-version.sh set "$NEXT_VERSION" # Commit as a second commit on the release branch. The tag (already # created and pushed on the first commit) is unaffected by this commit. - git add pom.xml core/pom.xml processor/pom.xml example/pom.xml example-custom-generator/pom.xml + git add -- ':(glob)**/pom.xml' git commit -m "release: prepare next version $NEXT_VERSION" # Force-push the updated branch so the remote has both commits. diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 1bc5415b..90e81684 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -68,6 +68,9 @@ jobs: key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 + - name: Verify all POMs share the root version + run: .github/scripts/project-version.sh verify + - name: Build with Maven run: mvn -B install -Pmetrics --file pom.xml diff --git a/RELEASE.md b/RELEASE.md index 9ed11a80..5f6b9dae 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -20,7 +20,7 @@ No version input is required. The workflow derives the release version from the ### What the Workflow Does 1. Derives the release version from the current POM snapshot version (strips `-SNAPSHOT`) -2. Updates POM versions to the release version in **all** modules (core, processor, example, example-custom-generator) +2. Updates POM versions to the release version in **all** tracked `pom.xml` files (discovered via git, so new and profile-only modules such as `performance-test` are included) 3. Commits the version bump on a dedicated `release/vX.Y.Z` branch and creates tag `vX.Y.Z` 4. Builds and verifies the project with `-Prelease` (reproducible builds via `project.build.outputTimestamp`) 5. Signs artifacts with GPG @@ -85,4 +85,4 @@ Each release produces, in addition to the GPG-signed jars: - Versions with `-` (e.g., `0.2.0-beta`) are marked as pre-releases - Releases are **staged** to the Sonatype Central portal and require a **manual publish** step; nothing is auto-released - Only `core` and `processor` modules are published to Maven Central -- The `example` and `example-custom-generator` modules are version-updated alongside the released modules but are **not** deployed to Maven Central +- All other modules (e.g. `example`, `example-custom-generator`, `performance-test`) are version-updated alongside the released modules but are **not** deployed to Maven Central; CI fails if any POM drifts from the root version diff --git a/performance-test/pom.xml b/performance-test/pom.xml index 61d6a09a..81184dd6 100644 --- a/performance-test/pom.xml +++ b/performance-test/pom.xml @@ -6,7 +6,7 @@ io.github.java-helpers simple-builders-performance-test - 0.6.0-SNAPSHOT + 0.7.0-SNAPSHOT jar Simple Builders - Performance Test From 0813c6845e285f0058d6d049dda6fb016b55297d Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 11 Oct 2026 20:28:55 +0000 Subject: [PATCH 2/5] Simplify project-version.sh and verify versions only on release PRs - readable functions and explicit --set / --verify / --help options - run the version check only for release/* PRs, not on every CI build nor in the release workflow --- .github/scripts/project-version.sh | 94 +++++++++++++-------- .github/workflows/maven-central-release.yml | 8 +- .github/workflows/maven.yml | 5 +- RELEASE.md | 2 +- 4 files changed, 65 insertions(+), 44 deletions(-) diff --git a/.github/scripts/project-version.sh b/.github/scripts/project-version.sh index 7cd09c20..d00f4050 100755 --- a/.github/scripts/project-version.sh +++ b/.github/scripts/project-version.sh @@ -1,52 +1,76 @@ #!/usr/bin/env bash -# Keeps the version of every tracked pom.xml in sync with the root POM. # -# The modules have no element, so each POM carries its own version. -# POMs are discovered via git instead of a hardcoded module list, so modules -# that are only part of a profile (e.g. performance-test) or added later are -# never left behind. +# Sets or verifies the version of all Maven POMs in this repository. # -# project.build.outputTimestamp is left untouched; the release workflow pins -# it in a dedicated step. -# -# Usage: -# project-version.sh set set in every POM -# project-version.sh verify fail if any POM differs from the root POM +# The modules have no , so every POM carries its own version. The POMs +# are found via git, so new or profile-only modules (e.g. performance-test) +# are always included. + set -euo pipefail -POM_PATHSPEC=':(glob)**/pom.xml' +usage() { + cat < | --verify + + --set set in all POMs + --verify fail if any POM differs from the version of the root POM + -h, --help show this help +USAGE +} + +all_poms() { + git ls-files pom.xml '*/pom.xml' +} pom_version() { - mvn -B -q -N -f "$1" help:evaluate -Dexpression=project.version -DforceStdout | tr -d '\r ' + mvn -B -q -N -f "$1" help:evaluate -Dexpression=project.version -DforceStdout +} + +set_version() { + local version="$1" + for pom in $(all_poms); do + echo "Setting version of $pom to $version" + # The reproducible build timestamp is pinned by the release workflow itself. + mvn -B -q -N -f "$pom" versions:set \ + -DnewVersion="$version" \ + -DgenerateBackupPoms=false \ + -DupdateBuildOutputTimestampPolicy=never + done +} + +verify_versions() { + local expected actual failed=0 + expected="$(pom_version pom.xml)" + for pom in $(all_poms); do + actual="$(pom_version "$pom")" + if [[ "$actual" != "$expected" ]]; then + echo "::error file=$pom::$pom has version $actual, expected $expected" + failed=1 + fi + done + return "$failed" } case "${1:-}" in - set) - NEW_VERSION="${2:?usage: $0 set }" - git ls-files -z -- "$POM_PATHSPEC" | while IFS= read -r -d '' pom; do - echo "Setting $pom to $NEW_VERSION" - mvn -B -q -N -f "$pom" versions:set -DnewVersion="$NEW_VERSION" -DgenerateBackupPoms=false \ - -DupdateBuildOutputTimestampPolicy=never - done + --set) + if [[ $# -ne 2 ]]; then + usage >&2 + exit 1 + fi + set_version "$2" ;; - verify) - ROOT_VERSION="$(pom_version pom.xml)" - MISMATCHES=0 - while IFS= read -r -d '' pom; do - VERSION="$(pom_version "$pom")" - if [[ "$VERSION" != "$ROOT_VERSION" ]]; then - echo "::error file=$pom::$pom is on version $VERSION, expected $ROOT_VERSION (root pom.xml)." - MISMATCHES=$((MISMATCHES + 1)) - fi - done < <(git ls-files -z -- "$POM_PATHSPEC") - if [[ "$MISMATCHES" -gt 0 ]]; then - echo "Run '.github/scripts/project-version.sh set $ROOT_VERSION' to align all POMs." + --verify) + if [[ $# -ne 1 ]]; then + usage >&2 exit 1 fi - echo "All POMs are on version $ROOT_VERSION." + verify_versions + ;; + -h | --help) + usage ;; *) - echo "usage: $0 set | verify" >&2 - exit 2 + usage >&2 + exit 1 ;; esac diff --git a/.github/workflows/maven-central-release.yml b/.github/workflows/maven-central-release.yml index 1d3b4ebc..7e083a69 100644 --- a/.github/workflows/maven-central-release.yml +++ b/.github/workflows/maven-central-release.yml @@ -63,10 +63,6 @@ jobs: CURRENT_VERSION="${CURRENT_VERSION//$'\r'/}" CURRENT_VERSION="${CURRENT_VERSION// /}" - # All POMs must share the root version, otherwise a module would be - # released and bumped from a stale version. - .github/scripts/project-version.sh verify - if [[ "$CURRENT_VERSION" != *-SNAPSHOT ]]; then echo "::error::Current POM version is '$CURRENT_VERSION', expected a -SNAPSHOT version. main must always be on a snapshot version." exit 1 @@ -92,7 +88,7 @@ jobs: # Update ALL POMs (root and every module, including profile-only # ones). Only core and processor are deployed to Maven Central, but # all modules must share the same version. - .github/scripts/project-version.sh set "$VERSION" + .github/scripts/project-version.sh --set "$VERSION" - name: Update reproducible build timestamp run: | @@ -264,7 +260,7 @@ jobs: echo "Next snapshot version: $NEXT_VERSION" # Set all POMs to the next snapshot version. - .github/scripts/project-version.sh set "$NEXT_VERSION" + .github/scripts/project-version.sh --set "$NEXT_VERSION" # Commit as a second commit on the release branch. The tag (already # created and pushed on the first commit) is unaffected by this commit. diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 90e81684..9f72ff64 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -68,8 +68,9 @@ jobs: key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 - - name: Verify all POMs share the root version - run: .github/scripts/project-version.sh verify + - name: Verify all POMs share the root version (release PRs) + if: startsWith(github.head_ref, 'release/') + run: .github/scripts/project-version.sh --verify - name: Build with Maven run: mvn -B install -Pmetrics --file pom.xml diff --git a/RELEASE.md b/RELEASE.md index 5f6b9dae..a2100798 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -85,4 +85,4 @@ Each release produces, in addition to the GPG-signed jars: - Versions with `-` (e.g., `0.2.0-beta`) are marked as pre-releases - Releases are **staged** to the Sonatype Central portal and require a **manual publish** step; nothing is auto-released - Only `core` and `processor` modules are published to Maven Central -- All other modules (e.g. `example`, `example-custom-generator`, `performance-test`) are version-updated alongside the released modules but are **not** deployed to Maven Central; CI fails if any POM drifts from the root version +- All other modules (e.g. `example`, `example-custom-generator`, `performance-test`) are version-updated alongside the released modules but are **not** deployed to Maven Central; CI on the release PR fails if any POM differs from the root version From dbfd6bb9157d3b4795a68ddc06ab13f494473e0d Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 11 Oct 2026 20:31:57 +0000 Subject: [PATCH 3/5] Verify POM versions in the release workflow instead of normal CI --- .github/workflows/maven-central-release.yml | 4 ++++ .github/workflows/maven.yml | 4 ---- RELEASE.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/maven-central-release.yml b/.github/workflows/maven-central-release.yml index 7e083a69..a9ac3b02 100644 --- a/.github/workflows/maven-central-release.yml +++ b/.github/workflows/maven-central-release.yml @@ -63,6 +63,10 @@ jobs: CURRENT_VERSION="${CURRENT_VERSION//$'\r'/}" CURRENT_VERSION="${CURRENT_VERSION// /}" + # All POMs must share the root version, otherwise a module would be + # released and bumped from a stale version. + .github/scripts/project-version.sh --verify + if [[ "$CURRENT_VERSION" != *-SNAPSHOT ]]; then echo "::error::Current POM version is '$CURRENT_VERSION', expected a -SNAPSHOT version. main must always be on a snapshot version." exit 1 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9f72ff64..1bc5415b 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -68,10 +68,6 @@ jobs: key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 - - name: Verify all POMs share the root version (release PRs) - if: startsWith(github.head_ref, 'release/') - run: .github/scripts/project-version.sh --verify - - name: Build with Maven run: mvn -B install -Pmetrics --file pom.xml diff --git a/RELEASE.md b/RELEASE.md index a2100798..c7174c67 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -85,4 +85,4 @@ Each release produces, in addition to the GPG-signed jars: - Versions with `-` (e.g., `0.2.0-beta`) are marked as pre-releases - Releases are **staged** to the Sonatype Central portal and require a **manual publish** step; nothing is auto-released - Only `core` and `processor` modules are published to Maven Central -- All other modules (e.g. `example`, `example-custom-generator`, `performance-test`) are version-updated alongside the released modules but are **not** deployed to Maven Central; CI on the release PR fails if any POM differs from the root version +- All other modules (e.g. `example`, `example-custom-generator`, `performance-test`) are version-updated alongside the released modules but are **not** deployed to Maven Central; the release workflow fails if any POM differs from the root version From 53754b05a908be149cdaf4d311d744841291625e Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 11 Oct 2026 20:36:07 +0000 Subject: [PATCH 4/5] Use a simple if/elif chain for version script options --- .github/scripts/project-version.sh | 35 ++++++++++-------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/.github/scripts/project-version.sh b/.github/scripts/project-version.sh index d00f4050..1f8f06f3 100755 --- a/.github/scripts/project-version.sh +++ b/.github/scripts/project-version.sh @@ -51,26 +51,15 @@ verify_versions() { return "$failed" } -case "${1:-}" in - --set) - if [[ $# -ne 2 ]]; then - usage >&2 - exit 1 - fi - set_version "$2" - ;; - --verify) - if [[ $# -ne 1 ]]; then - usage >&2 - exit 1 - fi - verify_versions - ;; - -h | --help) - usage - ;; - *) - usage >&2 - exit 1 - ;; -esac +option="${1:-}" + +if [[ "$option" == "--set" && $# -eq 2 ]]; then + set_version "$2" +elif [[ "$option" == "--verify" && $# -eq 1 ]]; then + verify_versions +elif [[ "$option" == "-h" || "$option" == "--help" ]]; then + usage +else + usage >&2 + exit 1 +fi From 4a62e0e1b3caccdfc95bb43f33e2fbf02efb56d9 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 11 Oct 2026 21:34:17 +0000 Subject: [PATCH 5/5] Use plain POM patterns when staging release versions --- .github/workflows/maven-central-release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven-central-release.yml b/.github/workflows/maven-central-release.yml index a9ac3b02..3f7774bd 100644 --- a/.github/workflows/maven-central-release.yml +++ b/.github/workflows/maven-central-release.yml @@ -114,7 +114,7 @@ jobs: # update to main goes through a reviewed pull request instead of a # direct push that bypasses branch protection. git checkout -B "$BRANCH" - git add -- ':(glob)**/pom.xml' + git add -- pom.xml '*/pom.xml' echo "branch=$BRANCH" >> "$GITHUB_OUTPUT" # Only commit if there are changes. Note: no "[skip ci]" so the @@ -268,7 +268,7 @@ jobs: # Commit as a second commit on the release branch. The tag (already # created and pushed on the first commit) is unaffected by this commit. - git add -- ':(glob)**/pom.xml' + git add -- pom.xml '*/pom.xml' git commit -m "release: prepare next version $NEXT_VERSION" # Force-push the updated branch so the remote has both commits.