From 498222f353d225abc94415fa17339724c9344cbb Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Tue, 25 Aug 2026 14:55:05 +0200 Subject: [PATCH 1/3] Support multiple modules and make release preparation idempotent Adapt `deploy-release-reusable` to repositories with multiple modules inheriting directly from `logging-parent` (e.g. Apache Flume, whose reactor root and `flume-parent` both do): * The `revision` and `project.build.outputTimestamp` properties are now updated in every git-tracked `pom.xml` defining them (excluding `src/**`), using `versions:set-property` instead of `help:evaluate` and a `sed` hack. Both updates share a single step and Bash function. Also make the release preparation commits idempotent: * The changelog is released first, so the `project.build.outputTimestamp` value covers all release preparation commits. Since the `pom.xml` still contains the old version at that point, `revision` is overridden on the command line. * The timestamp is taken from the author date of `HEAD` (preserved by squash commits and rebases) and the commit updating it is backdated to the same value, so re-runs produce no new commits. * All commits are published with a single `git push` at the end. Assisted-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01A4jy56QVeduMJcpkryJQpG --- .../workflows/deploy-release-reusable.yaml | 73 +++++++++---------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/.github/workflows/deploy-release-reusable.yaml b/.github/workflows/deploy-release-reusable.yaml index fc3a1437..f9e349c9 100644 --- a/.github/workflows/deploy-release-reusable.yaml +++ b/.github/workflows/deploy-release-reusable.yaml @@ -104,54 +104,51 @@ jobs: # Export version to calling workflow echo "project-version=$PROJECT_VERSION" >> $GITHUB_OUTPUT - - name: Set the Maven `revision` property - shell: bash - run: | - export REVISION=$(./mvnw \ - --non-recursive --quiet --batch-mode \ - -DforceStdout=true \ - -Dexpression=revision \ - help:evaluate \ - | tail -n 1) - if [ "$REVISION" != "$PROJECT_VERSION" ]; then - echo "Maven \`revision\` property \`$REVISION\` doesn't match with the project version \`$PROJECT_VERSION\`, updating \`pom.xml\`..." - ./mvnw \ - --non-recursive --batch-mode --errors --no-transfer-progress \ - -Dproperty=revision \ - -DnewVersion="$PROJECT_VERSION" \ - -DgenerateBackupPoms=false \ - versions:set-property - git commit -S pom.xml -m "Set version to \`$PROJECT_VERSION\`" - git push -f origin - fi - - - name: Set the Maven `project.build.outputTimestamp` property - shell: bash - run: | - export PROPERTY="project.build.outputTimestamp" - grep -qE '^[\t ]+<'$PROPERTY'>' pom.xml || { - echo "Failed to find the \`$PROPERTY\` Maven property!" - exit 1 - } - export TIMESTAMP=$(TZ=UTC0 git show --quiet --date="format-local:%Y-%m-%dT%H:%M:%SZ" --format="%cd") - sed -r 's|^([\t ]+<'$PROPERTY'>).+()$|\1'$TIMESTAMP'\2|g' -i pom.xml - if [ -n "$(git status --porcelain)" ]; then - git commit -S pom.xml -m "Update the \`$PROPERTY\` property" - git push -f origin - fi - - name: Release changelog shell: bash run: | + # `revision` is overridden explicitly, since the `pom.xml` is only updated in the next step ./mvnw \ --non-recursive --batch-mode --errors --no-transfer-progress \ + -Drevision="$PROJECT_VERSION" \ -P changelog-release git add src - if [ -n "$(git status --porcelain)" ]; then + if [ -n "$(git status --porcelain -- src)" ]; then git commit -S src -m "Release changelog for version \`$PROJECT_VERSION\`" - git push -f origin fi + - name: Set the Maven `revision` and `project.build.outputTimestamp` properties + shell: bash + run: | + # update_property + # Updates in every `pom.xml` defining it and commits if anything changed + update_property() { + local property="$1" value="$2" message="$3" pom poms + readarray -t poms < <(git grep -lE "^[[:space:]]*<$property>" -- 'pom.xml' '*/pom.xml' ':!src/**') + [ "${#poms[@]}" -gt 0 ] || { + echo "Failed to find the \`$property\` Maven property!" + exit 1 + } + for pom in "${poms[@]}"; do + ./mvnw -f "$pom" \ + --non-recursive --batch-mode --errors --no-transfer-progress \ + -Dproperty="$property" \ + -DnewVersion="$value" \ + -DgenerateBackupPoms=false \ + versions:set-property + done + if [ -n "$(git status --porcelain -- "${poms[@]}")" ]; then + git commit -S -m "$message" -- "${poms[@]}" + fi + } + update_property revision "$PROJECT_VERSION" "Set version to \`$PROJECT_VERSION\`" + # The author date, unlike the committer date, survives squash commits and rebases. + # Backdating the commit below to it makes re-runs of this step no-ops. + export TIMESTAMP=$(TZ=UTC0 git show --quiet --date="format-local:%Y-%m-%dT%H:%M:%SZ" --format="%ad") + export GIT_AUTHOR_DATE="$TIMESTAMP" + update_property project.build.outputTimestamp "$TIMESTAMP" "Update the \`project.build.outputTimestamp\` property" + git push -f origin + - name: Upload to Nexus id: nexus shell: bash From a43c4c103923cc85d39d9d6954ea53c23a5d3900 Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Tue, 25 Aug 2026 15:07:39 +0200 Subject: [PATCH 2/3] Share a single author date across all automatic commits Export `GIT_AUTHOR_DATE` once, right after checkout: the author date of the checked out commit. All automatic commits (changelog, `revision`, `project.build.outputTimestamp`) and the timestamp property now share this value, so re-runs of the workflow regenerate commits with identical author dates. Assisted-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01A4jy56QVeduMJcpkryJQpG --- .github/workflows/deploy-release-reusable.yaml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy-release-reusable.yaml b/.github/workflows/deploy-release-reusable.yaml index f9e349c9..e4e20744 100644 --- a/.github/workflows/deploy-release-reusable.yaml +++ b/.github/workflows/deploy-release-reusable.yaml @@ -88,6 +88,11 @@ jobs: # Set up user name and email required for `git commit` git config user.name "ASF Logging Services RM" git config user.email private@logging.apache.org + # Share the author date of the checked out commit with all automatic commits + # and the `project.build.outputTimestamp` Maven property. + # The author date, unlike the committer date, survives squash commits and + # rebases, which makes re-runs of this workflow idempotent. + echo "GIT_AUTHOR_DATE=$(TZ=UTC0 git show --quiet --date="format-local:%Y-%m-%dT%H:%M:%SZ" --format="%ad")" >> $GITHUB_ENV - name: Export version id: version @@ -142,11 +147,8 @@ jobs: fi } update_property revision "$PROJECT_VERSION" "Set version to \`$PROJECT_VERSION\`" - # The author date, unlike the committer date, survives squash commits and rebases. - # Backdating the commit below to it makes re-runs of this step no-ops. - export TIMESTAMP=$(TZ=UTC0 git show --quiet --date="format-local:%Y-%m-%dT%H:%M:%SZ" --format="%ad") - export GIT_AUTHOR_DATE="$TIMESTAMP" - update_property project.build.outputTimestamp "$TIMESTAMP" "Update the \`project.build.outputTimestamp\` property" + # `GIT_AUTHOR_DATE` is exported by the `Set up Git user` step + update_property project.build.outputTimestamp "$GIT_AUTHOR_DATE" "Update the \`project.build.outputTimestamp\` property" git push -f origin - name: Upload to Nexus From e440388c534bd12c840693646612363971f05074 Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Tue, 25 Aug 2026 15:08:56 +0200 Subject: [PATCH 3/3] Rename `Set up Git user` step to `Set up Git` The step no longer only configures the committer identity, it also exports `GIT_AUTHOR_DATE`. Assisted-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01A4jy56QVeduMJcpkryJQpG --- .github/workflows/deploy-release-reusable.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-release-reusable.yaml b/.github/workflows/deploy-release-reusable.yaml index e4e20744..6360f1f6 100644 --- a/.github/workflows/deploy-release-reusable.yaml +++ b/.github/workflows/deploy-release-reusable.yaml @@ -82,7 +82,7 @@ jobs: server-password: NEXUS_PASSWORD gpg-private-key: ${{ secrets.GPG_SECRET_KEY }} - - name: Set up Git user + - name: Set up Git shell: bash run: | # Set up user name and email required for `git commit` @@ -147,7 +147,7 @@ jobs: fi } update_property revision "$PROJECT_VERSION" "Set version to \`$PROJECT_VERSION\`" - # `GIT_AUTHOR_DATE` is exported by the `Set up Git user` step + # `GIT_AUTHOR_DATE` is exported by the `Set up Git` step update_property project.build.outputTimestamp "$GIT_AUTHOR_DATE" "Update the \`project.build.outputTimestamp\` property" git push -f origin