From cf830ff24c74acd4fdb7613491f83d9b83bb5909 Mon Sep 17 00:00:00 2001 From: Fabiana Severin Date: Mon, 24 Aug 2026 11:42:25 +0100 Subject: [PATCH 01/11] feat(release): add changelog entry, GitHub Releases, lastPublished, and RELEASING.md --- .github/workflows/release.yml | 49 ++++++++++++++++++ RELEASING.md | 50 +++++++++++++++++++ aws-lambda-java-core/pom.xml | 1 + .../pom.xml | 1 + aws-lambda-java-events/pom.xml | 1 + aws-lambda-java-log4j2/pom.xml | 1 + aws-lambda-java-serialization/pom.xml | 1 + aws-lambda-java-tests/pom.xml | 1 + 8 files changed, 105 insertions(+) create mode 100644 RELEASING.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 60617434..f3a9b03f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,6 +27,10 @@ on: description: 'Next development version override (optional, must end with -SNAPSHOT)' required: false type: string + changelogEntry: + description: 'Changelog entry (Markdown bullets, e.g. "- Fix X"). Prepended to the module RELEASE.CHANGELOG.md in the version-bump PR and used as the GitHub Release notes. Required.' + required: true + type: string skip_publish: description: 'Skip publish (dry-run validation)' required: false @@ -48,6 +52,7 @@ env: MODULE: ${{ github.event.inputs.module }} RELEASE_VERSION_INPUT: ${{ github.event.inputs.releaseVersion }} DEVELOPMENT_VERSION_INPUT: ${{ github.event.inputs.developmentVersion }} + CHANGELOG_ENTRY_INPUT: ${{ github.event.inputs.changelogEntry }} # Batch mode + no transfer-progress spam for every Maven call (Maven 3.9+). MAVEN_ARGS: "-B --no-transfer-progress" AWS_REGION: ${{ vars.AWS_REGION_MAVEN_RELEASE }} @@ -252,6 +257,34 @@ jobs: -Darguments="-gs $MAVEN_SETTINGS -Prelease -Dgpg.keyname=$GPG_KEYNAME -Dgpg.passphrase=$GPG_PASSPHRASE" \ --file "$MODULE/pom.xml" + # Bump the lastPublished comment under ; rides in the bump PR. + - name: Record last published version in POM + if: ${{ github.event.inputs.skip_publish != 'true' }} + run: | + if ! grep -q "||" "$MODULE/pom.xml" + git commit -am "chore(release): record ${MODULE} lastPublished=${EFFECTIVE_RELEASE_VERSION}" + + # Prepend the changelog entry so it ships in the version-bump PR. Passed + # via env, never interpolated into the script, so it can't inject shell. + - name: Prepend changelog entry + if: ${{ github.event.inputs.skip_publish != 'true' }} + run: | + CHANGELOG="$MODULE/RELEASE.CHANGELOG.md" + TMP="$(mktemp)" + { + echo "### $(date +'%B %d, %Y')" + echo "\`${EFFECTIVE_RELEASE_VERSION}\`:" + printf '%s\n\n' "$CHANGELOG_ENTRY_INPUT" + [ -f "$CHANGELOG" ] && cat "$CHANGELOG" + } > "$TMP" + mv "$TMP" "$CHANGELOG" + git add "$CHANGELOG" + git commit -m "docs(release): add ${MODULE} ${EFFECTIVE_RELEASE_VERSION} changelog entry" + # main is protected (no direct push), so push the tag and open a PR for # the version-bump commits instead. Skipping this would leave the POM on # the just-released -SNAPSHOT. @@ -273,6 +306,22 @@ jobs: --title "chore(release): ${MODULE} ${EFFECTIVE_RELEASE_VERSION}" \ --body "Post-release version bump for ${MODULE} ${EFFECTIVE_RELEASE_VERSION} (already on Maven Central, tag ${TAG} pushed)." + # GitHub Release on the pushed tag: changelog entry + Central link. + - name: Create GitHub Release + if: ${{ github.event.inputs.skip_publish != 'true' }} + env: + GH_TOKEN: ${{ github.token }} + run: | + TAG="${MODULE}-${EFFECTIVE_RELEASE_VERSION}" + NOTES="$(mktemp)" + { + printf '%s\n\n' "$CHANGELOG_ENTRY_INPUT" + echo "Published to Maven Central: https://central.sonatype.com/artifact/com.amazonaws/${MODULE}/${EFFECTIVE_RELEASE_VERSION}" + } > "$NOTES" + gh release create "$TAG" \ + --title "${MODULE} ${EFFECTIVE_RELEASE_VERSION}" \ + --notes-file "$NOTES" + - name: Dry-run release (prepare only, no publish) if: ${{ github.event.inputs.skip_publish == 'true' }} run: | diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 00000000..f2f0865f --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,50 @@ +# Releasing to Maven Central + +How maintainers publish a module using the +[`Release to Maven Central`](.github/workflows/release.yml) workflow. + +Releasable modules: `aws-lambda-java-core`, `aws-lambda-java-events`, +`aws-lambda-java-events-sdk-transformer`, `aws-lambda-java-log4j2`, +`aws-lambda-java-serialization`, `aws-lambda-java-tests`. + +> `aws-lambda-java-runtime-interface-client` has its own pipeline, +> [`release-runtime-interface-client.yml`](.github/workflows/release-runtime-interface-client.yml). + +## Cutting a release + +1. **Actions → Release to Maven Central → Run workflow**, with the branch set to + **`main`** (releases only run from `main`). +2. Fill in the inputs: + + | Input | Required | Notes | + |-------|----------|-------| + | `module` | yes | Module directory to release. | + | `changelogEntry` | yes | Markdown bullets, e.g. `- Fix X`. Added to the module `RELEASE.CHANGELOG.md` and used as the GitHub Release notes. | + | `releaseVersion` | no | Defaults to the POM version without `-SNAPSHOT`. | + | `developmentVersion` | no | Next dev version; must end with `-SNAPSHOT`. | + | `skip_publish` | no | Dry run: build and validate, publish nothing. | + +3. Run it and approve the `Release` environment when prompted. + +## What it does + +1. Validates the branch and resolves the release version from the POM (or your override). +2. Builds and tests the module. +3. Publishes to Maven Central and pushes the tag `-`. +4. Opens a **version-bump PR** into `main` with the next `-SNAPSHOT`, the updated + `lastPublished` comment, and your changelog entry. +5. Creates a GitHub Release on the tag from your changelog entry. + +Merge the version-bump PR to return `main` to a clean `-SNAPSHOT` state. + +## Dry runs + +Set `skip_publish` to build, test, and `release:prepare -DdryRun=true` without +pushing anything. A `changelogEntry` is still required by the form but unused. + +## If a release fails + +- **Before publish:** nothing was pushed. Fix and re-run. +- **After publish:** the Central version is immutable and the tag exists. Don't + re-run for the same version (it fails at `release:prepare`); finish the + remaining steps by hand (merge the bump PR, or `gh release create`). diff --git a/aws-lambda-java-core/pom.xml b/aws-lambda-java-core/pom.xml index 7cfba2b8..41d11cb7 100644 --- a/aws-lambda-java-core/pom.xml +++ b/aws-lambda-java-core/pom.xml @@ -6,6 +6,7 @@ com.amazonaws aws-lambda-java-core 1.4.1-SNAPSHOT + jar AWS Lambda Java Core Library diff --git a/aws-lambda-java-events-sdk-transformer/pom.xml b/aws-lambda-java-events-sdk-transformer/pom.xml index 4776aabc..5d4ac563 100644 --- a/aws-lambda-java-events-sdk-transformer/pom.xml +++ b/aws-lambda-java-events-sdk-transformer/pom.xml @@ -6,6 +6,7 @@ com.amazonaws aws-lambda-java-events-sdk-transformer 3.1.2-SNAPSHOT + jar AWS Lambda Java Events SDK Transformer Library diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml index 3bef204f..e7df4ee0 100644 --- a/aws-lambda-java-events/pom.xml +++ b/aws-lambda-java-events/pom.xml @@ -6,6 +6,7 @@ com.amazonaws aws-lambda-java-events 3.16.2-SNAPSHOT + jar AWS Lambda Java Events Library diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml index ac1de269..6fd74bae 100644 --- a/aws-lambda-java-log4j2/pom.xml +++ b/aws-lambda-java-log4j2/pom.xml @@ -6,6 +6,7 @@ com.amazonaws aws-lambda-java-log4j2 1.6.5-SNAPSHOT + jar AWS Lambda Java Log4j 2.x Libraries diff --git a/aws-lambda-java-serialization/pom.xml b/aws-lambda-java-serialization/pom.xml index c9285672..7c1f8041 100644 --- a/aws-lambda-java-serialization/pom.xml +++ b/aws-lambda-java-serialization/pom.xml @@ -5,6 +5,7 @@ com.amazonaws aws-lambda-java-serialization 1.4.2-SNAPSHOT + jar AWS Lambda Java Runtime Serialization diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml index bb0c7ab7..f5ca724a 100644 --- a/aws-lambda-java-tests/pom.xml +++ b/aws-lambda-java-tests/pom.xml @@ -6,6 +6,7 @@ com.amazonaws aws-lambda-java-tests 1.1.3-SNAPSHOT + jar AWS Lambda Java Tests From 555b3f50daf93e9c58f5b57a0619737df0441012 Mon Sep 17 00:00:00 2001 From: Fabiana Severin Date: Tue, 25 Aug 2026 11:58:47 +0100 Subject: [PATCH 02/11] build: centralize module versions in a parent POM --- .github/workflows/release.yml | 54 ++++++++--- .gitignore | 4 + RELEASING.md | 3 +- aws-lambda-java-core/pom.xml | 7 ++ .../pom.xml | 10 +- aws-lambda-java-events/pom.xml | 7 ++ aws-lambda-java-log4j2/pom.xml | 10 +- .../pom.xml | 13 ++- aws-lambda-java-serialization/pom.xml | 7 ++ aws-lambda-java-tests/pom.xml | 13 ++- pom.xml | 97 +++++++++++++++++++ 11 files changed, 200 insertions(+), 25 deletions(-) create mode 100644 pom.xml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f3a9b03f..f9d86434 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -167,9 +167,9 @@ jobs: # Cross-module gate: serialization has no tests in its own build, so the # `mvn verify` above exercises nothing. Its behavioral coverage lives in - # aws-lambda-java-tests, which depends on serialization via a version - # property. Install the just-built serialization and run that suite - # against it, so we never publish serialization the suite hasn't exercised. + # aws-lambda-java-tests, which depends on it via the parent version map. + # Install the just-built serialization and run that suite against it, so + # we never publish serialization the suite hasn't exercised. - name: Run cross-module test gate run: | case "$MODULE" in @@ -179,8 +179,10 @@ jobs: echo "::group::Installing $MODULE $MOD_VER for the gate" mvn install -DskipTests --file "$MODULE/pom.xml" echo "::endgroup::" - echo "::notice::Gating $MODULE on aws-lambda-java-tests (aws-lambda-java-serialization.version=$MOD_VER)" - mvn verify -Daws-lambda-java-serialization.version="$MOD_VER" --file aws-lambda-java-tests/pom.xml + echo "::notice::Gating $MODULE on aws-lambda-java-tests (lambda.serialization.version=$MOD_VER)" + # Override the map property so the suite runs against the + # just-built serialization, not the version pinned in the map. + mvn verify -Dlambda.serialization.version="$MOD_VER" --file aws-lambda-java-tests/pom.xml ;; *) echo "::notice::No cross-module test gate for $MODULE" @@ -257,16 +259,44 @@ jobs: -Darguments="-gs $MAVEN_SETTINGS -Prelease -Dgpg.keyname=$GPG_KEYNAME -Dgpg.passphrase=$GPG_PASSPHRASE" \ --file "$MODULE/pom.xml" - # Bump the lastPublished comment under ; rides in the bump PR. - - name: Record last published version in POM + # Record the published version in the two places that track it, from the + # same EFFECTIVE_RELEASE_VERSION in one commit so they can't drift: + # (1) the module's lastPublished comment (informational, every module) and + # (2) the parent version map (functional, only for modules others depend + # on). Rides in the version-bump PR below (main is protected). + - name: Record released version (POM lastPublished + parent version map) if: ${{ github.event.inputs.skip_publish != 'true' }} run: | - if ! grep -q "||" "$MODULE/pom.xml" + git add "$MODULE/pom.xml" + else + echo "::notice::$MODULE has no lastPublished comment; skipping annotation" + fi + + # (2) Parent version map — keyed only for modules other modules depend on. + case "$MODULE" in + aws-lambda-java-core) PROP=lambda.core.version ;; + aws-lambda-java-events) PROP=lambda.events.version ;; + aws-lambda-java-serialization) PROP=lambda.serialization.version ;; + *) PROP="" ;; + esac + if [ -n "$PROP" ]; then + PROP_RE="${PROP//./\\.}" + sed -i.bak -E "s|(<${PROP_RE}>)[^<]*()|\1${EFFECTIVE_RELEASE_VERSION}\2|" pom.xml + rm -f pom.xml.bak + git add pom.xml + else + echo "::notice::$MODULE has no internal consumers; version map unchanged" + fi + + # One commit for both records, or nothing if neither changed. + if git diff --cached --quiet; then + echo "::notice::$MODULE already recorded at ${EFFECTIVE_RELEASE_VERSION}; nothing to commit" + else + git commit -m "chore(release): record ${MODULE} ${EFFECTIVE_RELEASE_VERSION} (lastPublished + version map)" fi - sed -i "s|||" "$MODULE/pom.xml" - git commit -am "chore(release): record ${MODULE} lastPublished=${EFFECTIVE_RELEASE_VERSION}" # Prepend the changelog entry so it ships in the version-bump PR. Passed # via env, never interpolated into the script, so it can't inject shell. diff --git a/.gitignore b/.gitignore index 5a277e5d..5e4d8c8c 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,7 @@ experimental/aws-lambda-java-profiler/integration_tests/helloworld/bin .kiro build mise.toml + +# flatten-maven-plugin generates this self-contained POM at build time; it is +# published in place of the raw module POM and must never be committed. +.flattened-pom.xml diff --git a/RELEASING.md b/RELEASING.md index f2f0865f..6b453a08 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -32,7 +32,8 @@ Releasable modules: `aws-lambda-java-core`, `aws-lambda-java-events`, 2. Builds and tests the module. 3. Publishes to Maven Central and pushes the tag `-`. 4. Opens a **version-bump PR** into `main` with the next `-SNAPSHOT`, the updated - `lastPublished` comment, and your changelog entry. + `lastPublished` comment, the parent POM's version-map entry (for modules other + modules depend on: core, events, serialization), and your changelog entry. 5. Creates a GitHub Release on the tag from your changelog entry. Merge the version-bump PR to return `main` to a clean `-SNAPSHOT` state. diff --git a/aws-lambda-java-core/pom.xml b/aws-lambda-java-core/pom.xml index 41d11cb7..a71dd719 100644 --- a/aws-lambda-java-core/pom.xml +++ b/aws-lambda-java-core/pom.xml @@ -3,6 +3,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 + + com.amazonaws + aws-lambda-java-libs-parent + 1.0.0 + ../pom.xml + + com.amazonaws aws-lambda-java-core 1.4.1-SNAPSHOT diff --git a/aws-lambda-java-events-sdk-transformer/pom.xml b/aws-lambda-java-events-sdk-transformer/pom.xml index 5d4ac563..5248ac57 100644 --- a/aws-lambda-java-events-sdk-transformer/pom.xml +++ b/aws-lambda-java-events-sdk-transformer/pom.xml @@ -3,7 +3,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - com.amazonaws + + com.amazonaws + aws-lambda-java-libs-parent + 1.0.0 + ../pom.xml + + aws-lambda-java-events-sdk-transformer 3.1.2-SNAPSHOT @@ -69,7 +75,7 @@ com.amazonaws aws-lambda-java-events - 3.16.1 + provided diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml index e7df4ee0..9103fbbc 100644 --- a/aws-lambda-java-events/pom.xml +++ b/aws-lambda-java-events/pom.xml @@ -3,6 +3,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 + + com.amazonaws + aws-lambda-java-libs-parent + 1.0.0 + ../pom.xml + + com.amazonaws aws-lambda-java-events 3.16.2-SNAPSHOT diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml index 6fd74bae..ecc8c878 100644 --- a/aws-lambda-java-log4j2/pom.xml +++ b/aws-lambda-java-log4j2/pom.xml @@ -3,7 +3,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - com.amazonaws + + com.amazonaws + aws-lambda-java-libs-parent + 1.0.0 + ../pom.xml + + aws-lambda-java-log4j2 1.6.5-SNAPSHOT @@ -53,7 +59,7 @@ com.amazonaws aws-lambda-java-core - 1.2.3 + org.apache.logging.log4j diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml index 6db41aa3..7d8b7d53 100644 --- a/aws-lambda-java-runtime-interface-client/pom.xml +++ b/aws-lambda-java-runtime-interface-client/pom.xml @@ -2,7 +2,14 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - com.amazonaws + + + com.amazonaws + aws-lambda-java-libs-parent + 1.0.0 + ../pom.xml + + aws-lambda-java-runtime-interface-client 2.12.0-SNAPSHOT jar @@ -65,12 +72,12 @@ com.amazonaws aws-lambda-java-core - 1.4.0 + com.amazonaws aws-lambda-java-serialization - 1.4.1 + software.amazon.awssdk diff --git a/aws-lambda-java-serialization/pom.xml b/aws-lambda-java-serialization/pom.xml index 7c1f8041..40981c0e 100644 --- a/aws-lambda-java-serialization/pom.xml +++ b/aws-lambda-java-serialization/pom.xml @@ -2,6 +2,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 + + com.amazonaws + aws-lambda-java-libs-parent + 1.0.0 + ../pom.xml + + com.amazonaws aws-lambda-java-serialization 1.4.2-SNAPSHOT diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml index f5ca724a..dbe8d08f 100644 --- a/aws-lambda-java-tests/pom.xml +++ b/aws-lambda-java-tests/pom.xml @@ -3,7 +3,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - com.amazonaws + + com.amazonaws + aws-lambda-java-libs-parent + 1.0.0 + ../pom.xml + + aws-lambda-java-tests 1.1.3-SNAPSHOT @@ -44,8 +50,7 @@ --> 5.9.2 0.8.7 - 1.4.1 - 3.16.1 + 3.18.0 3.27.7 @@ -54,12 +59,10 @@ com.amazonaws aws-lambda-java-serialization - ${aws-lambda-java-serialization.version} com.amazonaws aws-lambda-java-events - ${aws-lambda-java-events.version} org.junit.jupiter diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..3b2be2f0 --- /dev/null +++ b/pom.xml @@ -0,0 +1,97 @@ + + + 4.0.0 + + com.amazonaws + aws-lambda-java-libs-parent + + 1.0.0 + pom + + AWS Lambda Java Libs Parent + + Build-time-only parent that centralizes internal module versions. + + https://aws.amazon.com/lambda/ + + + Apache License, Version 2.0 + https://aws.amazon.com/apache2.0 + repo + + + + https://github.com/aws/aws-lambda-java-libs.git + scm:git:https://github.com/aws/aws-lambda-java-libs.git + scm:git:https://github.com/aws/aws-lambda-java-libs.git + HEAD + + + + AWS Lambda team + Amazon Web Services + https://aws.amazon.com/ + + + + + + 1.4.0 + 3.16.1 + 1.4.1 + + + + + + com.amazonaws + aws-lambda-java-core + ${lambda.core.version} + + + com.amazonaws + aws-lambda-java-events + ${lambda.events.version} + + + com.amazonaws + aws-lambda-java-serialization + ${lambda.serialization.version} + + + + + + + + + org.codehaus.mojo + flatten-maven-plugin + 1.6.0 + + ossrh + true + + + + flatten + process-resources + + flatten + + + + flatten-clean + clean + + clean + + + + + + + From 5d510463d0660947fff61bd1825d59fbb87e30b3 Mon Sep 17 00:00:00 2001 From: Fabiana Severin Date: Mon, 31 Aug 2026 11:20:32 +0100 Subject: [PATCH 03/11] refactor(release): address PR review on parent POM and workflow --- .github/workflows/release.yml | 14 +++++--------- aws-lambda-java-core/pom.xml | 2 +- aws-lambda-java-events-sdk-transformer/pom.xml | 5 ++--- aws-lambda-java-events/pom.xml | 5 ++--- aws-lambda-java-log4j2/pom.xml | 5 ++--- aws-lambda-java-runtime-interface-client/pom.xml | 10 ++++++---- aws-lambda-java-serialization/pom.xml | 2 +- aws-lambda-java-tests/pom.xml | 2 +- pom.xml | 14 ++++++++++++-- 9 files changed, 32 insertions(+), 27 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f9d86434..cd33b768 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -275,20 +275,16 @@ jobs: echo "::notice::$MODULE has no lastPublished comment; skipping annotation" fi - # (2) Parent version map — keyed only for modules other modules depend on. - case "$MODULE" in - aws-lambda-java-core) PROP=lambda.core.version ;; - aws-lambda-java-events) PROP=lambda.events.version ;; - aws-lambda-java-serialization) PROP=lambda.serialization.version ;; - *) PROP="" ;; - esac - if [ -n "$PROP" ]; then + # (2) Parent version map. Update the module's entry only if the parent + # declares one; its presence is what opts a module in. No list here. + PROP="lambda.${MODULE#aws-lambda-java-}.version" + if grep -qF "<${PROP}>" pom.xml; then PROP_RE="${PROP//./\\.}" sed -i.bak -E "s|(<${PROP_RE}>)[^<]*()|\1${EFFECTIVE_RELEASE_VERSION}\2|" pom.xml rm -f pom.xml.bak git add pom.xml else - echo "::notice::$MODULE has no internal consumers; version map unchanged" + echo "::notice::$MODULE is not consumed by other modules (no ${PROP} in parent POM); version map unchanged" fi # One commit for both records, or nothing if neither changed. diff --git a/aws-lambda-java-core/pom.xml b/aws-lambda-java-core/pom.xml index a71dd719..6edf2432 100644 --- a/aws-lambda-java-core/pom.xml +++ b/aws-lambda-java-core/pom.xml @@ -5,7 +5,7 @@ com.amazonaws - aws-lambda-java-libs-parent + aws-lambda-java-libs 1.0.0 ../pom.xml diff --git a/aws-lambda-java-events-sdk-transformer/pom.xml b/aws-lambda-java-events-sdk-transformer/pom.xml index 5248ac57..51a8bfc2 100644 --- a/aws-lambda-java-events-sdk-transformer/pom.xml +++ b/aws-lambda-java-events-sdk-transformer/pom.xml @@ -5,7 +5,7 @@ com.amazonaws - aws-lambda-java-libs-parent + aws-lambda-java-libs 1.0.0 ../pom.xml @@ -48,7 +48,6 @@ 1.8 1.11.914 2.15.40 - 5.12.2 3.5.4 @@ -82,7 +81,7 @@ org.junit.jupiter junit-jupiter-engine - ${junit-jupiter.version} + test diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml index 9103fbbc..76d2ee86 100644 --- a/aws-lambda-java-events/pom.xml +++ b/aws-lambda-java-events/pom.xml @@ -5,7 +5,7 @@ com.amazonaws - aws-lambda-java-libs-parent + aws-lambda-java-libs 1.0.0 ../pom.xml @@ -50,7 +50,6 @@ UTF-8 2.20.1 2.40.1 - 5.12.2 @@ -107,7 +106,7 @@ org.junit.jupiter junit-jupiter-engine - ${junit-jupiter.version} + test diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml index 1f09b3db..972664f7 100644 --- a/aws-lambda-java-log4j2/pom.xml +++ b/aws-lambda-java-log4j2/pom.xml @@ -3,7 +3,7 @@ com.amazonaws - aws-lambda-java-libs-parent + aws-lambda-java-libs 1.0.0 ../pom.xml @@ -43,7 +43,6 @@ 1.8 1.8 2.25.5 - 5.12.2 @@ -78,7 +77,7 @@ org.junit.jupiter junit-jupiter-engine - ${junit-jupiter.version} + test diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml index 7d8b7d53..d9752f08 100644 --- a/aws-lambda-java-runtime-interface-client/pom.xml +++ b/aws-lambda-java-runtime-interface-client/pom.xml @@ -5,7 +5,7 @@ com.amazonaws - aws-lambda-java-libs-parent + aws-lambda-java-libs 1.0.0 ../pom.xml @@ -47,7 +47,9 @@ 0.8.12 2.4 3.1.1 - 5.12.2 + 3.4.0 3.5.4 test org.junit.jupiter junit-jupiter - ${junit-jupiter.version} + test diff --git a/aws-lambda-java-serialization/pom.xml b/aws-lambda-java-serialization/pom.xml index 40981c0e..ba354dd2 100644 --- a/aws-lambda-java-serialization/pom.xml +++ b/aws-lambda-java-serialization/pom.xml @@ -4,7 +4,7 @@ com.amazonaws - aws-lambda-java-libs-parent + aws-lambda-java-libs 1.0.0 ../pom.xml diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml index dbe8d08f..3737d6af 100644 --- a/aws-lambda-java-tests/pom.xml +++ b/aws-lambda-java-tests/pom.xml @@ -5,7 +5,7 @@ com.amazonaws - aws-lambda-java-libs-parent + aws-lambda-java-libs 1.0.0 ../pom.xml diff --git a/pom.xml b/pom.xml index 3b2be2f0..e50ed715 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.amazonaws - aws-lambda-java-libs-parent + aws-lambda-java-libs 1.0.0 pom @@ -36,11 +36,11 @@ - 1.4.0 3.16.1 1.4.1 + 5.12.2 @@ -60,6 +60,16 @@ aws-lambda-java-serialization ${lambda.serialization.version} + + org.junit.jupiter + junit-jupiter + ${junit-jupiter.version} + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + From ce9f80bfff7b4bb8e808ef9a04f5000d58f4a8a9 Mon Sep 17 00:00:00 2001 From: Fabiana Severin Date: Mon, 31 Aug 2026 11:47:51 +0100 Subject: [PATCH 04/11] docs(release): shorten version-map comment --- .github/workflows/release.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cd33b768..e21d4588 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -275,8 +275,7 @@ jobs: echo "::notice::$MODULE has no lastPublished comment; skipping annotation" fi - # (2) Parent version map. Update the module's entry only if the parent - # declares one; its presence is what opts a module in. No list here. + # (2) Parent version map. Update the module's entry only if the parent declares one PROP="lambda.${MODULE#aws-lambda-java-}.version" if grep -qF "<${PROP}>" pom.xml; then PROP_RE="${PROP//./\\.}" From 5a6a5289e5ee371b45a330acc372df9908b1b460 Mon Sep 17 00:00:00 2001 From: Fabiana Severin Date: Mon, 31 Aug 2026 18:10:17 +0100 Subject: [PATCH 05/11] chore(release): set meaningful Central deploymentName (GAV) --- aws-lambda-java-core/pom.xml | 1 + aws-lambda-java-events-sdk-transformer/pom.xml | 1 + aws-lambda-java-events/pom.xml | 1 + aws-lambda-java-log4j2/pom.xml | 1 + aws-lambda-java-runtime-interface-client/pom.xml | 1 + aws-lambda-java-serialization/pom.xml | 1 + aws-lambda-java-tests/pom.xml | 1 + 7 files changed, 7 insertions(+) diff --git a/aws-lambda-java-core/pom.xml b/aws-lambda-java-core/pom.xml index 6edf2432..b4b5cba6 100644 --- a/aws-lambda-java-core/pom.xml +++ b/aws-lambda-java-core/pom.xml @@ -163,6 +163,7 @@ central false + ${project.groupId}:${project.artifactId}:${project.version} diff --git a/aws-lambda-java-events-sdk-transformer/pom.xml b/aws-lambda-java-events-sdk-transformer/pom.xml index 51a8bfc2..c310be2a 100644 --- a/aws-lambda-java-events-sdk-transformer/pom.xml +++ b/aws-lambda-java-events-sdk-transformer/pom.xml @@ -213,6 +213,7 @@ central false + ${project.groupId}:${project.artifactId}:${project.version} diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml index 76d2ee86..949d420b 100644 --- a/aws-lambda-java-events/pom.xml +++ b/aws-lambda-java-events/pom.xml @@ -209,6 +209,7 @@ central false + ${project.groupId}:${project.artifactId}:${project.version} diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml index 972664f7..c50667d8 100644 --- a/aws-lambda-java-log4j2/pom.xml +++ b/aws-lambda-java-log4j2/pom.xml @@ -202,6 +202,7 @@ central false + ${project.groupId}:${project.artifactId}:${project.version} diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml index d9752f08..ef67d180 100644 --- a/aws-lambda-java-runtime-interface-client/pom.xml +++ b/aws-lambda-java-runtime-interface-client/pom.xml @@ -426,6 +426,7 @@ central false + ${project.groupId}:${project.artifactId}:${project.version} diff --git a/aws-lambda-java-serialization/pom.xml b/aws-lambda-java-serialization/pom.xml index ba354dd2..d815f8c8 100644 --- a/aws-lambda-java-serialization/pom.xml +++ b/aws-lambda-java-serialization/pom.xml @@ -187,6 +187,7 @@ central false + ${project.groupId}:${project.artifactId}:${project.version} diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml index 3737d6af..4d53bf33 100644 --- a/aws-lambda-java-tests/pom.xml +++ b/aws-lambda-java-tests/pom.xml @@ -244,6 +244,7 @@ central false + ${project.groupId}:${project.artifactId}:${project.version} From f980a36b17fe602ac95e436167ad02d519d5280f Mon Sep 17 00:00:00 2001 From: Fabiana Severin Date: Tue, 1 Sep 2026 16:36:40 +0100 Subject: [PATCH 06/11] feat(release): attach signed jars + verify notes to GitHub Release --- .github/workflows/release.yml | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e21d4588..9a4155a0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -228,6 +228,10 @@ jobs: gpgconf --kill gpg-agent || true gpg --batch --import <<< "$GPG_PRIVATE_KEY" GPG_KEYNAME=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/ {print $5; exit}') + # Publish the primary key fingerprint (NOT secret) for the GitHub + # Release verification instructions. Only the public fingerprint + # crosses $GITHUB_ENV here; the passphrase and token never do. + echo "GPG_FINGERPRINT=$(gpg --list-secret-keys --with-colons | awk -F: '/^fpr:/ {print $10; exit}')" >> "$GITHUB_ENV" # Global settings holding only the Sonatype "central" server for upload. # Passed to Maven as -gs (global) so it MERGES with the CodeArtifact @@ -342,10 +346,36 @@ jobs: { printf '%s\n\n' "$CHANGELOG_ENTRY_INPUT" echo "Published to Maven Central: https://central.sonatype.com/artifact/com.amazonaws/${MODULE}/${EFFECTIVE_RELEASE_VERSION}" + echo + echo "## Verifying the signatures" + echo + echo "The attached \`.jar.asc\` files are the same PGP signatures published to Maven Central, made with the AWS Lambda Java release signing key." + echo + echo '```' + echo "# 1. Import the public signing key" + echo "gpg --keyserver keys.openpgp.org --recv-keys ${GPG_FINGERPRINT}" + echo "# 2. Verify a downloaded jar against its signature" + echo "gpg --verify ${MODULE}-${EFFECTIVE_RELEASE_VERSION}.jar.asc ${MODULE}-${EFFECTIVE_RELEASE_VERSION}.jar" + echo '```' } > "$NOTES" + + # Attach the signed jars and their detached PGP signatures produced by + # release:perform (byte-for-byte the same artifacts and .asc files + # Maven Central received). They live in the perform checkout's target/ + # dir and persist past the Release step, so no re-signing is needed. + ARTIFACT_DIR="$MODULE/target/checkout/target" + ASSETS=() + while IFS= read -r f; do ASSETS+=("$f"); done < <( + find "$ARTIFACT_DIR" -maxdepth 1 -type f \( -name '*.jar' -o -name '*.jar.asc' \) 2>/dev/null | sort + ) + if [ ${#ASSETS[@]} -eq 0 ]; then + echo "::warning::No signed jars found under $ARTIFACT_DIR; creating the release without attachments" + fi + gh release create "$TAG" \ --title "${MODULE} ${EFFECTIVE_RELEASE_VERSION}" \ - --notes-file "$NOTES" + --notes-file "$NOTES" \ + "${ASSETS[@]}" - name: Dry-run release (prepare only, no publish) if: ${{ github.event.inputs.skip_publish == 'true' }} From fb9da27b44d97ac688ed682c1aa5b0e323524dda Mon Sep 17 00:00:00 2001 From: Fabiana Severin Date: Tue, 1 Sep 2026 16:55:09 +0100 Subject: [PATCH 07/11] refactor(release): split shared parent POM into a follow-up PR Move the shared parent POM and everything that depends on it out of this PR into a stacked follow-up, so this PR carries only the release-workflow features that stand on their own: - changelogEntry input, GitHub Release creation, signed-jar attachment and signature-verification notes - per-module lastPublished markers and Central deploymentName Removed here (returns in the follow-up PR): - root pom.xml (centralized version map + flatten plugin) - blocks and "version managed by parent" comments in modules - release.yml parent-version-map step and the version-map property in the cross-module test gate - the parent-version-map mention in RELEASING.md and the .flattened-pom.xml .gitignore entry --- .github/workflows/release.yml | 39 ++----- .gitignore | 4 - RELEASING.md | 3 +- aws-lambda-java-core/pom.xml | 7 -- .../pom.xml | 13 +-- aws-lambda-java-events/pom.xml | 10 +- aws-lambda-java-log4j2/pom.xml | 13 +-- .../pom.xml | 21 +--- aws-lambda-java-serialization/pom.xml | 7 -- aws-lambda-java-tests/pom.xml | 13 +-- pom.xml | 107 ------------------ 11 files changed, 34 insertions(+), 203 deletions(-) delete mode 100644 pom.xml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9a4155a0..2fe90e42 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -167,9 +167,9 @@ jobs: # Cross-module gate: serialization has no tests in its own build, so the # `mvn verify` above exercises nothing. Its behavioral coverage lives in - # aws-lambda-java-tests, which depends on it via the parent version map. - # Install the just-built serialization and run that suite against it, so - # we never publish serialization the suite hasn't exercised. + # aws-lambda-java-tests, which depends on serialization via a version + # property. Install the just-built serialization and run that suite + # against it, so we never publish serialization the suite hasn't exercised. - name: Run cross-module test gate run: | case "$MODULE" in @@ -179,10 +179,8 @@ jobs: echo "::group::Installing $MODULE $MOD_VER for the gate" mvn install -DskipTests --file "$MODULE/pom.xml" echo "::endgroup::" - echo "::notice::Gating $MODULE on aws-lambda-java-tests (lambda.serialization.version=$MOD_VER)" - # Override the map property so the suite runs against the - # just-built serialization, not the version pinned in the map. - mvn verify -Dlambda.serialization.version="$MOD_VER" --file aws-lambda-java-tests/pom.xml + echo "::notice::Gating $MODULE on aws-lambda-java-tests (aws-lambda-java-serialization.version=$MOD_VER)" + mvn verify -Daws-lambda-java-serialization.version="$MOD_VER" --file aws-lambda-java-tests/pom.xml ;; *) echo "::notice::No cross-module test gate for $MODULE" @@ -263,15 +261,13 @@ jobs: -Darguments="-gs $MAVEN_SETTINGS -Prelease -Dgpg.keyname=$GPG_KEYNAME -Dgpg.passphrase=$GPG_PASSPHRASE" \ --file "$MODULE/pom.xml" - # Record the published version in the two places that track it, from the - # same EFFECTIVE_RELEASE_VERSION in one commit so they can't drift: - # (1) the module's lastPublished comment (informational, every module) and - # (2) the parent version map (functional, only for modules others depend - # on). Rides in the version-bump PR below (main is protected). - - name: Record released version (POM lastPublished + parent version map) + # Record the published version in the module's lastPublished comment so + # the POM reflects what's on Central. Rides in the version-bump PR below + # (main is protected). + - name: Record released version (POM lastPublished) if: ${{ github.event.inputs.skip_publish != 'true' }} run: | - # (1) Module's lastPublished annotation. + # Module's lastPublished annotation. if grep -q "||" "$MODULE/pom.xml" git add "$MODULE/pom.xml" @@ -279,22 +275,11 @@ jobs: echo "::notice::$MODULE has no lastPublished comment; skipping annotation" fi - # (2) Parent version map. Update the module's entry only if the parent declares one - PROP="lambda.${MODULE#aws-lambda-java-}.version" - if grep -qF "<${PROP}>" pom.xml; then - PROP_RE="${PROP//./\\.}" - sed -i.bak -E "s|(<${PROP_RE}>)[^<]*()|\1${EFFECTIVE_RELEASE_VERSION}\2|" pom.xml - rm -f pom.xml.bak - git add pom.xml - else - echo "::notice::$MODULE is not consumed by other modules (no ${PROP} in parent POM); version map unchanged" - fi - - # One commit for both records, or nothing if neither changed. + # Commit the record, or nothing if it didn't change. if git diff --cached --quiet; then echo "::notice::$MODULE already recorded at ${EFFECTIVE_RELEASE_VERSION}; nothing to commit" else - git commit -m "chore(release): record ${MODULE} ${EFFECTIVE_RELEASE_VERSION} (lastPublished + version map)" + git commit -m "chore(release): record ${MODULE} ${EFFECTIVE_RELEASE_VERSION} lastPublished" fi # Prepend the changelog entry so it ships in the version-bump PR. Passed diff --git a/.gitignore b/.gitignore index 5e4d8c8c..5a277e5d 100644 --- a/.gitignore +++ b/.gitignore @@ -39,7 +39,3 @@ experimental/aws-lambda-java-profiler/integration_tests/helloworld/bin .kiro build mise.toml - -# flatten-maven-plugin generates this self-contained POM at build time; it is -# published in place of the raw module POM and must never be committed. -.flattened-pom.xml diff --git a/RELEASING.md b/RELEASING.md index 6b453a08..f2f0865f 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -32,8 +32,7 @@ Releasable modules: `aws-lambda-java-core`, `aws-lambda-java-events`, 2. Builds and tests the module. 3. Publishes to Maven Central and pushes the tag `-`. 4. Opens a **version-bump PR** into `main` with the next `-SNAPSHOT`, the updated - `lastPublished` comment, the parent POM's version-map entry (for modules other - modules depend on: core, events, serialization), and your changelog entry. + `lastPublished` comment, and your changelog entry. 5. Creates a GitHub Release on the tag from your changelog entry. Merge the version-bump PR to return `main` to a clean `-SNAPSHOT` state. diff --git a/aws-lambda-java-core/pom.xml b/aws-lambda-java-core/pom.xml index b4b5cba6..669ef58f 100644 --- a/aws-lambda-java-core/pom.xml +++ b/aws-lambda-java-core/pom.xml @@ -3,13 +3,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - - com.amazonaws - aws-lambda-java-libs - 1.0.0 - ../pom.xml - - com.amazonaws aws-lambda-java-core 1.4.1-SNAPSHOT diff --git a/aws-lambda-java-events-sdk-transformer/pom.xml b/aws-lambda-java-events-sdk-transformer/pom.xml index c310be2a..17955dc9 100644 --- a/aws-lambda-java-events-sdk-transformer/pom.xml +++ b/aws-lambda-java-events-sdk-transformer/pom.xml @@ -3,13 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - - com.amazonaws - aws-lambda-java-libs - 1.0.0 - ../pom.xml - - + com.amazonaws aws-lambda-java-events-sdk-transformer 3.1.2-SNAPSHOT @@ -48,6 +42,7 @@ 1.8 1.11.914 2.15.40 + 5.12.2 3.5.4 @@ -74,14 +69,14 @@ com.amazonaws aws-lambda-java-events - + 3.16.1 provided org.junit.jupiter junit-jupiter-engine - + ${junit-jupiter.version} test diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml index 949d420b..555d9134 100644 --- a/aws-lambda-java-events/pom.xml +++ b/aws-lambda-java-events/pom.xml @@ -3,13 +3,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - - com.amazonaws - aws-lambda-java-libs - 1.0.0 - ../pom.xml - - com.amazonaws aws-lambda-java-events 3.16.2-SNAPSHOT @@ -50,6 +43,7 @@ UTF-8 2.20.1 2.40.1 + 5.12.2 @@ -106,7 +100,7 @@ org.junit.jupiter junit-jupiter-engine - + ${junit-jupiter.version} test diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml index c50667d8..d8945133 100644 --- a/aws-lambda-java-log4j2/pom.xml +++ b/aws-lambda-java-log4j2/pom.xml @@ -1,13 +1,7 @@ 4.0.0 - - com.amazonaws - aws-lambda-java-libs - 1.0.0 - ../pom.xml - - + com.amazonaws aws-lambda-java-log4j2 1.6.6-SNAPSHOT @@ -43,6 +37,7 @@ 1.8 1.8 2.25.5 + 5.12.2 @@ -56,7 +51,7 @@ com.amazonaws aws-lambda-java-core - + 1.2.3 org.apache.logging.log4j @@ -77,7 +72,7 @@ org.junit.jupiter junit-jupiter-engine - + ${junit-jupiter.version} test diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml index ef67d180..756fe353 100644 --- a/aws-lambda-java-runtime-interface-client/pom.xml +++ b/aws-lambda-java-runtime-interface-client/pom.xml @@ -2,14 +2,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - - - com.amazonaws - aws-lambda-java-libs - 1.0.0 - ../pom.xml - - + com.amazonaws aws-lambda-java-runtime-interface-client 2.12.0-SNAPSHOT jar @@ -47,9 +40,7 @@ 0.8.12 2.4 3.1.1 - + 5.12.2 3.4.0 3.5.4 + 1.4.0 com.amazonaws aws-lambda-java-serialization - + 1.4.1 software.amazon.awssdk @@ -89,13 +80,13 @@ org.junit.jupiter junit-jupiter-engine - + ${junit-jupiter.version} test org.junit.jupiter junit-jupiter - + ${junit-jupiter.version} test diff --git a/aws-lambda-java-serialization/pom.xml b/aws-lambda-java-serialization/pom.xml index d815f8c8..a5a085ca 100644 --- a/aws-lambda-java-serialization/pom.xml +++ b/aws-lambda-java-serialization/pom.xml @@ -2,13 +2,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - - com.amazonaws - aws-lambda-java-libs - 1.0.0 - ../pom.xml - - com.amazonaws aws-lambda-java-serialization 1.4.2-SNAPSHOT diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml index 4d53bf33..8fb3ee0c 100644 --- a/aws-lambda-java-tests/pom.xml +++ b/aws-lambda-java-tests/pom.xml @@ -3,13 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - - com.amazonaws - aws-lambda-java-libs - 1.0.0 - ../pom.xml - - + com.amazonaws aws-lambda-java-tests 1.1.3-SNAPSHOT @@ -50,7 +44,8 @@ --> 5.9.2 0.8.7 - + 1.4.1 + 3.16.1 3.18.0 3.27.7 @@ -59,10 +54,12 @@ com.amazonaws aws-lambda-java-serialization + ${aws-lambda-java-serialization.version} com.amazonaws aws-lambda-java-events + ${aws-lambda-java-events.version} org.junit.jupiter diff --git a/pom.xml b/pom.xml deleted file mode 100644 index e50ed715..00000000 --- a/pom.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - 4.0.0 - - com.amazonaws - aws-lambda-java-libs - - 1.0.0 - pom - - AWS Lambda Java Libs Parent - - Build-time-only parent that centralizes internal module versions. - - https://aws.amazon.com/lambda/ - - - Apache License, Version 2.0 - https://aws.amazon.com/apache2.0 - repo - - - - https://github.com/aws/aws-lambda-java-libs.git - scm:git:https://github.com/aws/aws-lambda-java-libs.git - scm:git:https://github.com/aws/aws-lambda-java-libs.git - HEAD - - - - AWS Lambda team - Amazon Web Services - https://aws.amazon.com/ - - - - - 1.4.0 - 3.16.1 - 1.4.1 - 5.12.2 - - - - - - com.amazonaws - aws-lambda-java-core - ${lambda.core.version} - - - com.amazonaws - aws-lambda-java-events - ${lambda.events.version} - - - com.amazonaws - aws-lambda-java-serialization - ${lambda.serialization.version} - - - org.junit.jupiter - junit-jupiter - ${junit-jupiter.version} - - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - - - - - - - - - org.codehaus.mojo - flatten-maven-plugin - 1.6.0 - - ossrh - true - - - - flatten - process-resources - - flatten - - - - flatten-clean - clean - - clean - - - - - - - From 91ebbbc83808eaf187293d0d691b49c9b39c8b07 Mon Sep 17 00:00:00 2001 From: Fabiana Severin Date: Tue, 1 Sep 2026 17:54:38 +0100 Subject: [PATCH 08/11] feat(release): attach signed jars to GitHub Releases Add reusable setup-corretto8 and create-github-release composite actions; attach the signed jars + .asc signatures (same as Maven Central) with GPG verification notes, and add changelog + lastPublished to the RIC release. --- .../actions/create-github-release/action.yml | 94 +++++++++++++++++++ .github/actions/setup-corretto8/action.yml | 29 ++++++ .../release-runtime-interface-client.yml | 92 ++++++++++-------- .github/workflows/release.yml | 74 +++------------ .../pom.xml | 3 +- 5 files changed, 191 insertions(+), 101 deletions(-) create mode 100644 .github/actions/create-github-release/action.yml create mode 100644 .github/actions/setup-corretto8/action.yml diff --git a/.github/actions/create-github-release/action.yml b/.github/actions/create-github-release/action.yml new file mode 100644 index 00000000..731495f5 --- /dev/null +++ b/.github/actions/create-github-release/action.yml @@ -0,0 +1,94 @@ +name: "Create GitHub Release with signed assets" +description: > + Creates a GitHub Release on an already-pushed tag. Builds the release notes + from the changelog entry, a Maven Central link, and GPG verification + instructions, then attaches the signed jars and their detached .asc + signatures (byte-for-byte the same signatures uploaded to Maven Central). The + attachment set is derived from the .asc files, so only signed, published + artifacts are attached (unsigned intermediates like shade's original-*.jar are + skipped). No re-signing happens here. + +inputs: + tag: + description: "Git tag the release is created on (already pushed)." + required: true + title: + description: "Release title." + required: true + module: + description: "Module artifactId (used for the Central link and verify example)." + required: true + version: + description: "Released version." + required: true + changelog-entry: + description: "Markdown changelog entry used as the lead of the release notes." + required: true + fingerprint: + description: "Public GPG key fingerprint, shown in the verification instructions." + required: true + artifact-dir: + description: > + Directory (searched non-recursively) holding the signed jars and their + .asc siblings. For release:perform this is /target/checkout/target; + for an in-place deploy it is /target. + required: true + extra-notes: + description: "Optional Markdown inserted between the changelog and the Central link (e.g. an artifact inventory)." + required: false + default: "" + github-token: + description: "Token for the gh CLI (typically github.token)." + required: true + +runs: + using: composite + steps: + - name: Create GitHub Release + shell: bash + env: + GH_TOKEN: ${{ inputs.github-token }} + TAG: ${{ inputs.tag }} + RELEASE_TITLE: ${{ inputs.title }} + REL_MODULE: ${{ inputs.module }} + REL_VERSION: ${{ inputs.version }} + CHANGELOG_ENTRY: ${{ inputs.changelog-entry }} + GPG_FINGERPRINT: ${{ inputs.fingerprint }} + ARTIFACT_DIR: ${{ inputs.artifact-dir }} + EXTRA_NOTES: ${{ inputs.extra-notes }} + run: | + NOTES="$(mktemp)" + { + printf '%s\n\n' "$CHANGELOG_ENTRY" + if [ -n "$EXTRA_NOTES" ]; then + printf '%s\n\n' "$EXTRA_NOTES" + fi + echo "Published to Maven Central: https://central.sonatype.com/artifact/com.amazonaws/${REL_MODULE}/${REL_VERSION}" + echo + echo "## Verifying the signatures" + echo + echo "The attached \`.jar.asc\` files are the same GPG signatures published to Maven Central, made with the AWS Lambda Java release signing key." + echo + echo '```sh' + echo "# Import the public signing key" + echo "gpg --keyserver keys.openpgp.org --recv-keys ${GPG_FINGERPRINT}" + echo "# Verify a downloaded jar against its signature" + echo "gpg --verify ${REL_MODULE}-${REL_VERSION}.jar.asc ${REL_MODULE}-${REL_VERSION}.jar" + echo '```' + } > "$NOTES" + + # Attach the signed jars + their detached GPG signatures. Deriving the + # list from the .asc set means only signed, published artifacts are + # attached (skips unsigned intermediates like shade's original-*.jar). + ASSETS=() + while IFS= read -r sig; do + ASSETS+=("${sig%.asc}" "$sig") + done < <(find "$ARTIFACT_DIR" -maxdepth 1 -type f -name '*.jar.asc' 2>/dev/null | sort) + if [ ${#ASSETS[@]} -eq 0 ]; then + echo "::warning::No signed jars found under $ARTIFACT_DIR; creating the release without attachments" + fi + + gh release create "$TAG" \ + --title "$RELEASE_TITLE" \ + --notes-file "$NOTES" \ + "${ASSETS[@]}" diff --git a/.github/actions/setup-corretto8/action.yml b/.github/actions/setup-corretto8/action.yml new file mode 100644 index 00000000..2f9f451a --- /dev/null +++ b/.github/actions/setup-corretto8/action.yml @@ -0,0 +1,29 @@ +name: "Use the runner image's preinstalled Corretto 8" +description: > + Points JAVA_HOME/PATH at the CodeBuild image's preinstalled Corretto 8 + ($JAVA_8_HOME) and writes a Maven toolchains.xml for JDK 8. The image defaults + JAVA_HOME to Java 25, so this is required before any Maven call. Avoids + actions/setup-java, which fetches from corretto.github.io + corretto.aws, both + blocked by the runner egress lock. $JAVA_8_HOME resolves per-arch + (x86_64/aarch64). + +runs: + using: composite + steps: + - name: Use the runner image's preinstalled Corretto 8 + shell: bash + run: | + echo "JAVA_HOME=$JAVA_8_HOME" >> "$GITHUB_ENV" + echo "$JAVA_8_HOME/bin" >> "$GITHUB_PATH" + "$JAVA_8_HOME/bin/java" -version + mkdir -p "$HOME/.m2" + cat > "$HOME/.m2/toolchains.xml" < + + + jdk + 8 + $JAVA_8_HOME + + + EOF diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml index 7a966971..6fa1d899 100644 --- a/.github/workflows/release-runtime-interface-client.yml +++ b/.github/workflows/release-runtime-interface-client.yml @@ -16,6 +16,10 @@ on: description: 'Next development version override (optional, must end with -SNAPSHOT)' required: false type: string + changelogEntry: + description: 'Changelog entry (Markdown bullets, e.g. "- Fix X"). Prepended to the module RELEASE.CHANGELOG.md in the version-bump PR and used as the GitHub Release notes. Required.' + required: true + type: string skip_publish: description: 'Skip publish (dry-run validation)' required: false @@ -38,6 +42,7 @@ env: MODULE: aws-lambda-java-runtime-interface-client RELEASE_VERSION_INPUT: ${{ github.event.inputs.releaseVersion }} DEVELOPMENT_VERSION_INPUT: ${{ github.event.inputs.developmentVersion }} + CHANGELOG_ENTRY_INPUT: ${{ github.event.inputs.changelogEntry }} MAVEN_ARGS: "-B --no-transfer-progress" AWS_REGION: ${{ vars.AWS_REGION_MAVEN_RELEASE }} OIDC_ROLE_ARN: ${{ secrets.AWS_ROLE_MAVEN_RELEASE }} @@ -75,27 +80,8 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - # Use the CodeBuild image's preinstalled Corretto 8. The image ships it at - # $JAVA_8_HOME but defaults JAVA_HOME to Java 25, so point JAVA_HOME/PATH at - # 8. Avoids actions/setup-java, which fetches from corretto.github.io + - # corretto.aws, both blocked by the runner egress lock. $JAVA_8_HOME - # resolves per-arch (x86_64/aarch64). - name: Use the runner image's preinstalled Corretto 8 - run: | - echo "JAVA_HOME=$JAVA_8_HOME" >> "$GITHUB_ENV" - echo "$JAVA_8_HOME/bin" >> "$GITHUB_PATH" - "$JAVA_8_HOME/bin/java" -version - mkdir -p "$HOME/.m2" - cat > "$HOME/.m2/toolchains.xml" < - - - jdk - 8 - $JAVA_8_HOME - - - EOF + uses: ./.github/actions/setup-corretto8 # Route all mvn resolution through the CodeArtifact mirror. Must precede # resolve-release-version, which invokes `mvn help:evaluate`. Ambient @@ -164,27 +150,8 @@ jobs: with: fetch-depth: 0 # full history for tagging/pushing - # Use the CodeBuild image's preinstalled Corretto 8. The image ships it at - # $JAVA_8_HOME but defaults JAVA_HOME to Java 25, so point JAVA_HOME/PATH at - # 8. Avoids actions/setup-java, which fetches from corretto.github.io + - # corretto.aws, both blocked by the runner egress lock. $JAVA_8_HOME - # resolves per-arch (x86_64/aarch64). - name: Use the runner image's preinstalled Corretto 8 - run: | - echo "JAVA_HOME=$JAVA_8_HOME" >> "$GITHUB_ENV" - echo "$JAVA_8_HOME/bin" >> "$GITHUB_PATH" - "$JAVA_8_HOME/bin/java" -version - mkdir -p "$HOME/.m2" - cat > "$HOME/.m2/toolchains.xml" < - - - jdk - 8 - $JAVA_8_HOME - - - EOF + uses: ./.github/actions/setup-corretto8 # Route all mvn resolution through the CodeArtifact mirror. Must precede # resolve-release-version (which invokes `mvn help:evaluate`) and the OIDC @@ -304,6 +271,10 @@ jobs: gpgconf --kill gpg-agent || true gpg --batch --import <<< "$GPG_PRIVATE_KEY" GPG_KEYNAME=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/ {print $5; exit}') + # Publish the primary key fingerprint (NOT secret) for the GitHub + # Release verification instructions. Only the public fingerprint + # crosses $GITHUB_ENV here; the passphrase and token never do. + echo "GPG_FINGERPRINT=$(gpg --list-secret-keys --with-colons | awk -F: '/^fpr:/ {print $10; exit}')" >> "$GITHUB_ENV" # Global settings holding only the Sonatype "central" server for upload. # Passed to Maven as -gs (global) so it MERGES with the CodeArtifact @@ -339,10 +310,31 @@ jobs: git commit -am "chore(ric): release ${EFFECTIVE_RELEASE_VERSION}" git tag "$TAG_NAME" - # Next development version commit. + # Next development version commit. Also refresh the informational + # lastPublished marker to the version just published (rides in the + # post-release commit, so the tagged release commit is untouched). mvn versions:set -DnewVersion="$NEXT_DEV_VERSION" -DgenerateBackupPoms=false --file "$MODULE/pom.xml" + if grep -q "||" "$MODULE/pom.xml" + fi git commit -am "chore(ric): prepare next development ${NEXT_DEV_VERSION}" + # Prepend the changelog entry so it ships in the version-bump PR (on + # top of the dev-version commit, after the tag, so the tag itself is + # unchanged). Passed via env, never interpolated into the script, so + # it can't inject shell. + CHANGELOG="$MODULE/RELEASE.CHANGELOG.md" + TMP="$(mktemp)" + { + echo "### $(date +'%B %d, %Y')" + echo "\`${EFFECTIVE_RELEASE_VERSION}\`:" + printf '%s\n\n' "$CHANGELOG_ENTRY_INPUT" + [ -f "$CHANGELOG" ] && cat "$CHANGELOG" + } > "$TMP" + mv "$TMP" "$CHANGELOG" + git add "$CHANGELOG" + git commit -m "docs(release): add ${MODULE} ${EFFECTIVE_RELEASE_VERSION} changelog entry" + # Tag push isn't gated by branch protection; the version-bump commits # go to a release branch and land on main via PR. git push origin "refs/tags/${TAG_NAME}" @@ -354,6 +346,24 @@ jobs: --title "chore(release): ${MODULE} ${EFFECTIVE_RELEASE_VERSION}" \ --body "Post-release version bump for ${MODULE} ${EFFECTIVE_RELEASE_VERSION} (already on Maven Central, tag ${TAG_NAME} pushed)." + # GitHub Release on the pushed tag: the signed artifacts (byte-for-byte the + # same detached GPG signatures uploaded to Maven Central) + verification + # instructions. `mvn deploy` signed in place, so the jars and their .asc + # siblings are in the module target dir and need no re-signing. + - name: Create GitHub Release + if: ${{ github.event.inputs.skip_publish != 'true' }} + uses: ./.github/actions/create-github-release + with: + tag: ${{ env.TAG_NAME }} + title: ${{ env.MODULE }} ${{ env.EFFECTIVE_RELEASE_VERSION }} + module: ${{ env.MODULE }} + version: ${{ env.EFFECTIVE_RELEASE_VERSION }} + changelog-entry: ${{ env.CHANGELOG_ENTRY_INPUT }} + fingerprint: ${{ env.GPG_FINGERPRINT }} + artifact-dir: ${{ env.MODULE }}/target + extra-notes: "Artifacts: main JAR + linux/linux_musl x x86_64/aarch_64 native classifier JARs." + github-token: ${{ github.token }} + # Dry-run: validate assembly, no publish/push. - name: Dry-run assemble (no publish) if: ${{ github.event.inputs.skip_publish == 'true' }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2fe90e42..70d0903d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -91,27 +91,8 @@ jobs: with: fetch-depth: 0 # full history for tagging/pushing - # Use the CodeBuild image's preinstalled Corretto 8. The image ships it at - # $JAVA_8_HOME but defaults JAVA_HOME to Java 25, so point JAVA_HOME/PATH at - # 8. Avoids actions/setup-java, which fetches from corretto.github.io + - # corretto.aws, both blocked by the runner egress lock. $JAVA_8_HOME - # resolves per-arch (x86_64/aarch64). - name: Use the runner image's preinstalled Corretto 8 - run: | - echo "JAVA_HOME=$JAVA_8_HOME" >> "$GITHUB_ENV" - echo "$JAVA_8_HOME/bin" >> "$GITHUB_PATH" - "$JAVA_8_HOME/bin/java" -version - mkdir -p "$HOME/.m2" - cat > "$HOME/.m2/toolchains.xml" < - - - jdk - 8 - $JAVA_8_HOME - - - EOF + uses: ./.github/actions/setup-corretto8 # Route all mvn resolution through the CodeArtifact mirror. Runs before the # OIDC step (which would shadow the runner-role creds this needs) and on @@ -320,47 +301,22 @@ jobs: --title "chore(release): ${MODULE} ${EFFECTIVE_RELEASE_VERSION}" \ --body "Post-release version bump for ${MODULE} ${EFFECTIVE_RELEASE_VERSION} (already on Maven Central, tag ${TAG} pushed)." - # GitHub Release on the pushed tag: changelog entry + Central link. + # GitHub Release on the pushed tag: changelog + Central link + GPG verify + # instructions, with the signed jars and their .asc signatures attached. + # release:perform builds in a fresh checkout, so the signed artifacts live + # under /target/checkout/target. - name: Create GitHub Release if: ${{ github.event.inputs.skip_publish != 'true' }} - env: - GH_TOKEN: ${{ github.token }} - run: | - TAG="${MODULE}-${EFFECTIVE_RELEASE_VERSION}" - NOTES="$(mktemp)" - { - printf '%s\n\n' "$CHANGELOG_ENTRY_INPUT" - echo "Published to Maven Central: https://central.sonatype.com/artifact/com.amazonaws/${MODULE}/${EFFECTIVE_RELEASE_VERSION}" - echo - echo "## Verifying the signatures" - echo - echo "The attached \`.jar.asc\` files are the same PGP signatures published to Maven Central, made with the AWS Lambda Java release signing key." - echo - echo '```' - echo "# 1. Import the public signing key" - echo "gpg --keyserver keys.openpgp.org --recv-keys ${GPG_FINGERPRINT}" - echo "# 2. Verify a downloaded jar against its signature" - echo "gpg --verify ${MODULE}-${EFFECTIVE_RELEASE_VERSION}.jar.asc ${MODULE}-${EFFECTIVE_RELEASE_VERSION}.jar" - echo '```' - } > "$NOTES" - - # Attach the signed jars and their detached PGP signatures produced by - # release:perform (byte-for-byte the same artifacts and .asc files - # Maven Central received). They live in the perform checkout's target/ - # dir and persist past the Release step, so no re-signing is needed. - ARTIFACT_DIR="$MODULE/target/checkout/target" - ASSETS=() - while IFS= read -r f; do ASSETS+=("$f"); done < <( - find "$ARTIFACT_DIR" -maxdepth 1 -type f \( -name '*.jar' -o -name '*.jar.asc' \) 2>/dev/null | sort - ) - if [ ${#ASSETS[@]} -eq 0 ]; then - echo "::warning::No signed jars found under $ARTIFACT_DIR; creating the release without attachments" - fi - - gh release create "$TAG" \ - --title "${MODULE} ${EFFECTIVE_RELEASE_VERSION}" \ - --notes-file "$NOTES" \ - "${ASSETS[@]}" + uses: ./.github/actions/create-github-release + with: + tag: ${{ env.MODULE }}-${{ env.EFFECTIVE_RELEASE_VERSION }} + title: ${{ env.MODULE }} ${{ env.EFFECTIVE_RELEASE_VERSION }} + module: ${{ env.MODULE }} + version: ${{ env.EFFECTIVE_RELEASE_VERSION }} + changelog-entry: ${{ env.CHANGELOG_ENTRY_INPUT }} + fingerprint: ${{ env.GPG_FINGERPRINT }} + artifact-dir: ${{ env.MODULE }}/target/checkout/target + github-token: ${{ github.token }} - name: Dry-run release (prepare only, no publish) if: ${{ github.event.inputs.skip_publish == 'true' }} diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml index 756fe353..4ae81a81 100644 --- a/aws-lambda-java-runtime-interface-client/pom.xml +++ b/aws-lambda-java-runtime-interface-client/pom.xml @@ -4,7 +4,8 @@ 4.0.0 com.amazonaws aws-lambda-java-runtime-interface-client - 2.12.0-SNAPSHOT + 2.12.1-SNAPSHOT + jar AWS Lambda Java Runtime Interface Client From 73633715037fbfa04b450228274868b41aab4fcc Mon Sep 17 00:00:00 2001 From: Fabiana Severin Date: Wed, 2 Sep 2026 10:29:42 +0100 Subject: [PATCH 09/11] fix(release): validate release version and keep GPG passphrase off argv --- .../actions/resolve-release-version/action.yml | 18 ++++++++++++++++++ .../release-runtime-interface-client.yml | 15 ++++++++++++++- .github/workflows/release.yml | 9 +++++++-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/.github/actions/resolve-release-version/action.yml b/.github/actions/resolve-release-version/action.yml index 06d3f4f1..f8fcdccc 100644 --- a/.github/actions/resolve-release-version/action.yml +++ b/.github/actions/resolve-release-version/action.yml @@ -50,5 +50,23 @@ runs: # Optional override; default strips -SNAPSHOT. EFFECTIVE_RELEASE_VERSION="${RELEASE_VERSION_OVERRIDE:-${CURRENT_VERSION%-SNAPSHOT}}" + # Constrain the version to a strict MAJOR.MINOR.PATCH(-prerelease) shape. + # This is a security control: EFFECTIVE_RELEASE_VERSION + # (which can come verbatim from the releaseVersion input) is later spliced + # into a `sed` program, a git tag/branch name, and written to $GITHUB_ENV. + # The character class here forbids sed delimiters/metacharacters (| & \ /), + # whitespace, and newlines, so none of those sinks can be injected. + if [[ ! "$EFFECTIVE_RELEASE_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.]+)?$ ]]; then + echo "::error::Release version '$EFFECTIVE_RELEASE_VERSION' is not a valid MAJOR.MINOR.PATCH[-prerelease] version" + exit 1 + fi + # A release version must not itself be a SNAPSHOT (the default path strips + # it; only an override could reintroduce it). Mirrors the developmentVersion + # must-be-SNAPSHOT rule. + if [[ "$EFFECTIVE_RELEASE_VERSION" == *-SNAPSHOT ]]; then + echo "::error::Release version '$EFFECTIVE_RELEASE_VERSION' must not be a SNAPSHOT" + exit 1 + fi + echo "CURRENT_VERSION=$CURRENT_VERSION" >> "$GITHUB_ENV" echo "EFFECTIVE_RELEASE_VERSION=$EFFECTIVE_RELEASE_VERSION" >> "$GITHUB_ENV" diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml index 6fa1d899..a7a70059 100644 --- a/.github/workflows/release-runtime-interface-client.yml +++ b/.github/workflows/release-runtime-interface-client.yml @@ -146,6 +146,15 @@ jobs: environment: Release timeout-minutes: 30 steps: + # Defence-in-depth: build-natives already gates on main, but this job does + # the actual publish/tag/push on a separate runner, so re-verify here too. + - name: Verify release branch + run: | + if [[ "$GITHUB_REF_NAME" != "main" ]]; then + echo "::error::Releases must run from the main branch, got '$GITHUB_REF_NAME'" + exit 1 + fi + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 0 # full history for tagging/pushing @@ -290,9 +299,13 @@ jobs: } > "$MAVEN_SETTINGS" # --- Publish --- (-gs: merge Sonatype creds with the ~/.m2 mirror) + # Pass the passphrase via MAVEN_GPG_PASSPHRASE (read natively by + # maven-gpg-plugin) rather than -Dgpg.passphrase, so it never lands in + # the process argument list. + export MAVEN_GPG_PASSPHRASE="$GPG_PASSPHRASE" mvn deploy -Prelease -DskipTests -DmultiArch=false \ -gs "$MAVEN_SETTINGS" \ - -Dgpg.keyname="$GPG_KEYNAME" -Dgpg.passphrase="$GPG_PASSPHRASE" \ + -Dgpg.keyname="$GPG_KEYNAME" \ --file "$MODULE/pom.xml" # main is protected (no direct push), so push the tag (tag pushes aren't diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 70d0903d..d89d3ebd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -237,9 +237,14 @@ jobs: # perform forks a fresh build. Pass the Sonatype creds as GLOBAL # settings (-gs) so the fork still auto-reads ~/.m2/settings.xml (the - # mirror) and merges the two. + # mirror) and merges the two. The GPG passphrase is exported as + # MAVEN_GPG_PASSPHRASE (read natively by maven-gpg-plugin and inherited + # by the forked build) instead of being placed in -Darguments: it keeps + # the passphrase out of the process argument list and avoids the release + # plugin's space-splitting of -Darguments mangling a passphrase. + export MAVEN_GPG_PASSPHRASE="$GPG_PASSPHRASE" mvn release:perform -DlocalCheckout=true \ - -Darguments="-gs $MAVEN_SETTINGS -Prelease -Dgpg.keyname=$GPG_KEYNAME -Dgpg.passphrase=$GPG_PASSPHRASE" \ + -Darguments="-gs $MAVEN_SETTINGS -Prelease -Dgpg.keyname=$GPG_KEYNAME" \ --file "$MODULE/pom.xml" # Record the published version in the module's lastPublished comment so From 649ce7ed5f5f5f44159033c8977f5d5e537012b9 Mon Sep 17 00:00:00 2001 From: Fabiana Severin Date: Wed, 2 Sep 2026 11:26:37 +0100 Subject: [PATCH 10/11] chore(release): squash post-release bump into one commit --- .../release-runtime-interface-client.yml | 16 ++++------ .github/workflows/release.yml | 30 ++++++++----------- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml index a7a70059..29a31ae9 100644 --- a/.github/workflows/release-runtime-interface-client.yml +++ b/.github/workflows/release-runtime-interface-client.yml @@ -323,19 +323,15 @@ jobs: git commit -am "chore(ric): release ${EFFECTIVE_RELEASE_VERSION}" git tag "$TAG_NAME" - # Next development version commit. Also refresh the informational - # lastPublished marker to the version just published (rides in the - # post-release commit, so the tagged release commit is untouched). + # Single post-release commit: next development version bump, the + # lastPublished marker, and the changelog entry. Sits on top of the + # tag, so the tagged release commit is untouched. The changelog entry + # is passed via env, never interpolated into the script, so it can't + # inject shell. mvn versions:set -DnewVersion="$NEXT_DEV_VERSION" -DgenerateBackupPoms=false --file "$MODULE/pom.xml" if grep -q "||" "$MODULE/pom.xml" fi - git commit -am "chore(ric): prepare next development ${NEXT_DEV_VERSION}" - - # Prepend the changelog entry so it ships in the version-bump PR (on - # top of the dev-version commit, after the tag, so the tag itself is - # unchanged). Passed via env, never interpolated into the script, so - # it can't inject shell. CHANGELOG="$MODULE/RELEASE.CHANGELOG.md" TMP="$(mktemp)" { @@ -346,7 +342,7 @@ jobs: } > "$TMP" mv "$TMP" "$CHANGELOG" git add "$CHANGELOG" - git commit -m "docs(release): add ${MODULE} ${EFFECTIVE_RELEASE_VERSION} changelog entry" + git commit -am "chore(release): prepare next development, record ${MODULE} ${EFFECTIVE_RELEASE_VERSION} lastPublished and changelog" # Tag push isn't gated by branch protection; the version-bump commits # go to a release branch and land on main via PR. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d89d3ebd..1d681cf9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -247,13 +247,16 @@ jobs: -Darguments="-gs $MAVEN_SETTINGS -Prelease -Dgpg.keyname=$GPG_KEYNAME" \ --file "$MODULE/pom.xml" - # Record the published version in the module's lastPublished comment so - # the POM reflects what's on Central. Rides in the version-bump PR below - # (main is protected). - - name: Record released version (POM lastPublished) + # Fold the lastPublished marker and changelog entry into the single + # next-development commit that release:prepare created (local, unpushed), + # so the whole post-release bump is ONE commit in the version-bump PR + # below (main is protected). The tag points at the prior release commit, + # so amending here leaves the tag untouched. The changelog entry is passed + # via env, never interpolated into the script, so it can't inject shell. + - name: Record next dev, lastPublished and changelog if: ${{ github.event.inputs.skip_publish != 'true' }} run: | - # Module's lastPublished annotation. + # Refresh the module's lastPublished marker to what was just published. if grep -q "||" "$MODULE/pom.xml" git add "$MODULE/pom.xml" @@ -261,18 +264,7 @@ jobs: echo "::notice::$MODULE has no lastPublished comment; skipping annotation" fi - # Commit the record, or nothing if it didn't change. - if git diff --cached --quiet; then - echo "::notice::$MODULE already recorded at ${EFFECTIVE_RELEASE_VERSION}; nothing to commit" - else - git commit -m "chore(release): record ${MODULE} ${EFFECTIVE_RELEASE_VERSION} lastPublished" - fi - - # Prepend the changelog entry so it ships in the version-bump PR. Passed - # via env, never interpolated into the script, so it can't inject shell. - - name: Prepend changelog entry - if: ${{ github.event.inputs.skip_publish != 'true' }} - run: | + # Prepend the changelog entry. CHANGELOG="$MODULE/RELEASE.CHANGELOG.md" TMP="$(mktemp)" { @@ -283,7 +275,9 @@ jobs: } > "$TMP" mv "$TMP" "$CHANGELOG" git add "$CHANGELOG" - git commit -m "docs(release): add ${MODULE} ${EFFECTIVE_RELEASE_VERSION} changelog entry" + + # Fold into release:prepare's next-dev commit -> one post-release commit. + git commit --amend -m "chore(release): prepare next development, record ${MODULE} ${EFFECTIVE_RELEASE_VERSION} lastPublished and changelog" # main is protected (no direct push), so push the tag and open a PR for # the version-bump commits instead. Skipping this would leave the POM on From baa4cd50f7d0c44681ee1586f8674eb15b65a594 Mon Sep 17 00:00:00 2001 From: Fabiana Severin Date: Wed, 2 Sep 2026 11:45:14 +0100 Subject: [PATCH 11/11] refactor(release): centralize release tag in TAG_NAME --- .github/workflows/release.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1d681cf9..7e6fa0b4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -114,6 +114,9 @@ jobs: exit 1 fi echo "::notice::Releasing $MODULE $EFFECTIVE_RELEASE_VERSION (POM currently $CURRENT_VERSION)" + # Single source of truth for the tag, reused by the push, GitHub + # Release, rollback, and summary steps. + echo "TAG_NAME=${MODULE}-${EFFECTIVE_RELEASE_VERSION}" >> "$GITHUB_ENV" - name: Configure git user run: | @@ -287,18 +290,17 @@ jobs: env: GH_TOKEN: ${{ github.token }} run: | - TAG="${MODULE}-${EFFECTIVE_RELEASE_VERSION}" - RELEASE_BRANCH="release/${TAG}" + RELEASE_BRANCH="release/${TAG_NAME}" # Tag push isn't gated by branch protection; commits go via a PR. - git push origin "refs/tags/${TAG}" + git push origin "refs/tags/${TAG_NAME}" git push origin "HEAD:refs/heads/${RELEASE_BRANCH}" gh pr create \ --base "${GITHUB_REF_NAME}" \ --head "${RELEASE_BRANCH}" \ --title "chore(release): ${MODULE} ${EFFECTIVE_RELEASE_VERSION}" \ - --body "Post-release version bump for ${MODULE} ${EFFECTIVE_RELEASE_VERSION} (already on Maven Central, tag ${TAG} pushed)." + --body "Post-release version bump for ${MODULE} ${EFFECTIVE_RELEASE_VERSION} (already on Maven Central, tag ${TAG_NAME} pushed)." # GitHub Release on the pushed tag: changelog + Central link + GPG verify # instructions, with the signed jars and their .asc signatures attached. @@ -308,7 +310,7 @@ jobs: if: ${{ github.event.inputs.skip_publish != 'true' }} uses: ./.github/actions/create-github-release with: - tag: ${{ env.MODULE }}-${{ env.EFFECTIVE_RELEASE_VERSION }} + tag: ${{ env.TAG_NAME }} title: ${{ env.MODULE }} ${{ env.EFFECTIVE_RELEASE_VERSION }} module: ${{ env.MODULE }} version: ${{ env.EFFECTIVE_RELEASE_VERSION }} @@ -333,13 +335,12 @@ jobs: run: | mvn release:rollback --file "$MODULE/pom.xml" || true mvn release:clean --file "$MODULE/pom.xml" || true - git tag -d "${MODULE}-${EFFECTIVE_RELEASE_VERSION}" 2>/dev/null || true + git tag -d "$TAG_NAME" 2>/dev/null || true echo "::warning::Release failed before publish completed. The remote was not modified; the runner state has been rolled back. Safe to retry." - name: Summary if: ${{ github.event.inputs.skip_publish != 'true' }} run: | - TAG_NAME="${MODULE}-${EFFECTIVE_RELEASE_VERSION}" echo "## Release Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY