diff --git a/.github/actions/configure-release-aws-credentials/action.yml b/.github/actions/configure-release-aws-credentials/action.yml
new file mode 100644
index 00000000..a02a1e9a
--- /dev/null
+++ b/.github/actions/configure-release-aws-credentials/action.yml
@@ -0,0 +1,27 @@
+name: "Configure AWS credentials for release (OIDC)"
+description: >
+ Assumes the release OIDC role via aws-actions/configure-aws-credentials so the
+ job can read the signing key and Sonatype token from Secrets Manager. Pinning
+ of the underlying action lives here so it is updated in one place.
+
+inputs:
+ aws-region:
+ description: "AWS region to operate in."
+ required: true
+ role-to-assume:
+ description: "ARN of the OIDC role to assume."
+ required: true
+ role-session-name:
+ description: "Session name for the assumed role (helps distinguish callers in CloudTrail)."
+ required: true
+
+runs:
+ using: composite
+ steps:
+ - uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4
+ with:
+ aws-region: ${{ inputs.aws-region }}
+ role-to-assume: ${{ inputs.role-to-assume }}
+ role-session-name: ${{ inputs.role-session-name }}
+ # Short-lived: the job only needs the role briefly to read two secrets.
+ role-duration-seconds: 300
diff --git a/.github/actions/resolve-release-version/action.yml b/.github/actions/resolve-release-version/action.yml
new file mode 100644
index 00000000..06d3f4f1
--- /dev/null
+++ b/.github/actions/resolve-release-version/action.yml
@@ -0,0 +1,54 @@
+name: "Resolve and validate release version"
+description: >
+ Reads the module POM version (the source of truth), verifies it is a
+ -SNAPSHOT, and derives the effective release version (the optional override,
+ or the POM version with -SNAPSHOT stripped). Exports CURRENT_VERSION and
+ EFFECTIVE_RELEASE_VERSION to the job environment for subsequent steps.
+
+inputs:
+ module:
+ description: "Module directory containing the pom.xml to release."
+ required: true
+ release-version-override:
+ description: "Optional release version; defaults to the POM version without -SNAPSHOT."
+ required: false
+ default: ""
+ validate-module-dir:
+ description: "Fail if the module directory or its pom.xml is missing (use for the choice-driven workflow)."
+ required: false
+ default: "false"
+
+runs:
+ using: composite
+ steps:
+ - name: Resolve and validate release version
+ shell: bash
+ env:
+ MODULE: ${{ inputs.module }}
+ RELEASE_VERSION_OVERRIDE: ${{ inputs.release-version-override }}
+ VALIDATE_MODULE_DIR: ${{ inputs.validate-module-dir }}
+ run: |
+ if [[ "$VALIDATE_MODULE_DIR" == "true" ]]; then
+ if [[ ! -d "$MODULE" ]]; then
+ echo "::error::Module directory '$MODULE' does not exist"
+ exit 1
+ fi
+ if [[ ! -f "$MODULE/pom.xml" ]]; then
+ echo "::error::No pom.xml found in '$MODULE'"
+ exit 1
+ fi
+ fi
+
+ # The POM version is the source of truth and must be a SNAPSHOT.
+ CURRENT_VERSION=$(mvn -q -DforceStdout help:evaluate -Dexpression=project.version --file "$MODULE/pom.xml")
+ CURRENT_VERSION="${CURRENT_VERSION//[$'\r\n']/}"
+ if [[ "$CURRENT_VERSION" != *-SNAPSHOT ]]; then
+ echo "::error::POM version '$CURRENT_VERSION' is not a SNAPSHOT"
+ exit 1
+ fi
+
+ # Optional override; default strips -SNAPSHOT.
+ EFFECTIVE_RELEASE_VERSION="${RELEASE_VERSION_OVERRIDE:-${CURRENT_VERSION%-SNAPSHOT}}"
+
+ 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
new file mode 100644
index 00000000..6cc3bd6e
--- /dev/null
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -0,0 +1,287 @@
+name: Release RIC to Maven Central
+
+# RIC ships a native JNI lib for 4 targets + a main JAR (5 artifacts). Each
+# native lib is built on its own architecture (x86_64 on ubuntu-latest,
+# aarch_64 on ubuntu-24.04-arm) instead of emulating with QEMU. A build matrix
+# produces the classifier JARs, then one job assembles and publishes them.
+
+on:
+ workflow_dispatch:
+ inputs:
+ releaseVersion:
+ description: 'Release version override (optional; defaults to the POM version without -SNAPSHOT)'
+ required: false
+ type: string
+ developmentVersion:
+ description: 'Next development version override (optional, must end with -SNAPSHOT)'
+ required: false
+ type: string
+ skip_publish:
+ description: 'Skip publish (dry-run validation)'
+ required: false
+ type: boolean
+ default: false
+
+permissions:
+ contents: write # push release commit and tag
+ id-token: write # assume the OIDC role for secret retrieval
+
+# Share the repo-wide "release" group with release.yml so RIC and the pure-Java
+# modules can never publish concurrently. Never cancel in-flight: it could leave
+# a half-published state.
+concurrency:
+ group: release
+ cancel-in-progress: false
+
+env:
+ MODULE: aws-lambda-java-runtime-interface-client
+ RELEASE_VERSION_INPUT: ${{ github.event.inputs.releaseVersion }}
+ DEVELOPMENT_VERSION_INPUT: ${{ github.event.inputs.developmentVersion }}
+ MAVEN_ARGS: "-B --no-transfer-progress"
+ AWS_REGION: ${{ vars.AWS_REGION_MAVEN_RELEASE }}
+ OIDC_ROLE_ARN: ${{ secrets.AWS_ROLE_MAVEN_RELEASE }}
+
+jobs:
+ # Build each architecture's native libs (glibc + musl) on a native runner.
+ build-natives:
+ strategy:
+ fail-fast: true
+ matrix:
+ include:
+ - arch: x86_64
+ runner: ubuntu-latest
+ profiles: linux-x86_64 linux_musl-x86_64
+ - arch: aarch64
+ runner: ubuntu-24.04-arm
+ profiles: linux-aarch64 linux_musl-aarch64
+ runs-on: ${{ matrix.runner }}
+ timeout-minutes: 45
+ steps:
+ # Manual (workflow_dispatch) releases must only run from main, never from
+ # an arbitrary branch that could carry unreviewed release logic. Guarding
+ # the first job blocks the whole pipeline (release needs build-natives).
+ - 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
+
+ - name: Set up JDK 8
+ uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
+ with:
+ java-version: 8
+ distribution: corretto
+ cache: maven
+
+ - name: Resolve and validate release version
+ uses: ./.github/actions/resolve-release-version
+ with:
+ module: ${{ env.MODULE }}
+ release-version-override: ${{ env.RELEASE_VERSION_INPUT }}
+
+ # -DskipTests: only installed so the module compiles, not released here.
+ - name: Install intra-repo dependencies
+ run: |
+ for dep in aws-lambda-java-core aws-lambda-java-serialization; do
+ mvn install -DskipTests --file "$dep/pom.xml"
+ done
+
+ # Build at the release version (matches the JAR names the release job
+ # attaches).
+ - name: Build native classifier JARs (${{ matrix.arch }})
+ env:
+ IS_JAVA_8: true
+ run: |
+ mvn versions:set -DnewVersion="$EFFECTIVE_RELEASE_VERSION" -DgenerateBackupPoms=false --file "$MODULE/pom.xml"
+ for profile in ${{ matrix.profiles }}; do
+ echo "::group::Building $profile"
+ mvn package -P "$profile" -DmultiArch=false -DskipTests --file "$MODULE/pom.xml"
+ echo "::endgroup::"
+ done
+
+ # JARs to attach + .so files to assemble the fat main JAR.
+ - name: Upload native artifacts
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
+ with:
+ name: ric-natives-${{ matrix.arch }}
+ if-no-files-found: error
+ path: |
+ ${{ env.MODULE }}/target/*-linux*.jar
+ ${{ env.MODULE }}/target/classes/jni/*.so
+
+ # Assemble all native builds and publish.
+ release:
+ needs: build-natives
+ runs-on: ubuntu-latest
+ environment: Release
+ timeout-minutes: 30
+ steps:
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ with:
+ fetch-depth: 0 # full history for tagging/pushing
+
+ - name: Set up JDK 8
+ uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
+ with:
+ java-version: 8
+ distribution: corretto
+ cache: maven
+
+ - name: Resolve and validate release version
+ uses: ./.github/actions/resolve-release-version
+ with:
+ module: ${{ env.MODULE }}
+ release-version-override: ${{ env.RELEASE_VERSION_INPUT }}
+
+ - name: Resolve next development version and tag
+ run: |
+ # Next development version: use the override, or bump the patch.
+ if [[ -n "$DEVELOPMENT_VERSION_INPUT" ]]; then
+ if [[ "$DEVELOPMENT_VERSION_INPUT" != *-SNAPSHOT ]]; then
+ echo "::error::developmentVersion '$DEVELOPMENT_VERSION_INPUT' must end with -SNAPSHOT"
+ exit 1
+ fi
+ NEXT_DEV_VERSION="$DEVELOPMENT_VERSION_INPUT"
+ else
+ IFS='.' read -r MA MI PA <<< "$EFFECTIVE_RELEASE_VERSION"
+ NEXT_DEV_VERSION="${MA}.${MI}.$((PA + 1))-SNAPSHOT"
+ fi
+
+ echo "NEXT_DEV_VERSION=$NEXT_DEV_VERSION" >> "$GITHUB_ENV"
+ echo "TAG_NAME=${MODULE}-${EFFECTIVE_RELEASE_VERSION}" >> "$GITHUB_ENV"
+ echo "::notice::Releasing $MODULE $EFFECTIVE_RELEASE_VERSION (next dev $NEXT_DEV_VERSION)"
+
+ - name: Configure git user
+ run: |
+ git config user.name "github-actions[bot]"
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+
+ # -DskipTests: only installed so the module compiles, not released here.
+ - name: Install intra-repo dependencies
+ run: |
+ for dep in aws-lambda-java-core aws-lambda-java-serialization; do
+ mvn install -DskipTests --file "$dep/pom.xml"
+ done
+
+ - name: Set release version
+ run: mvn versions:set -DnewVersion="$EFFECTIVE_RELEASE_VERSION" -DgenerateBackupPoms=false --file "$MODULE/pom.xml"
+
+ # Test gate before publish.
+ - name: Run tests
+ env:
+ IS_JAVA_8: true
+ run: mvn test --file "$MODULE/pom.xml"
+
+ # JARs to attach + .so files for the fat main JAR.
+ - name: Download native artifacts
+ uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
+ with:
+ pattern: ric-natives-*
+ path: ric-natives
+
+ - name: Stage native artifacts
+ run: |
+ mkdir -p "$MODULE/target/classes/jni"
+ find ric-natives -name '*.jar' -exec cp {} "$MODULE/target/" \;
+ find ric-natives -name '*.so' -exec cp {} "$MODULE/target/classes/jni/" \;
+ echo "Staged native artifacts:"
+ ls -1 "$MODULE/target/"*-linux*.jar "$MODULE/target/classes/jni/"*.so
+
+ - name: Configure AWS credentials (OIDC)
+ if: ${{ github.event.inputs.skip_publish != 'true' }}
+ uses: ./.github/actions/configure-release-aws-credentials
+ with:
+ aws-region: ${{ env.AWS_REGION }}
+ role-to-assume: ${{ env.OIDC_ROLE_ARN }}
+ role-session-name: GitHubActionsRicMavenCentralRelease
+
+ # Fetch signing material and publish in a single step so the GPG passphrase
+ # and Sonatype token stay in this shell and never cross a $GITHUB_ENV
+ # boundary, where a later (possibly compromised) step could read them.
+ # -DmultiArch=false builds only the host .so; the aarch_64 .so is already
+ # staged, so the main JAR still bundles all four. build-helper attaches
+ # the staged classifier JARs. Gate already ran, so -DskipTests.
+ - name: Publish to Maven Central
+ if: ${{ github.event.inputs.skip_publish != 'true' }}
+ env:
+ IS_JAVA_8: true
+ run: |
+ # Scrub the settings.xml (contains the Sonatype token) and the keyring
+ # on exit, so no sensitive file is left on the runner even on failure.
+ MAVEN_SETTINGS="$RUNNER_TEMP/settings.xml"
+ export GNUPGHOME=$(mktemp -d)
+ trap 'rm -rf "$MAVEN_SETTINGS" "$GNUPGHOME"' EXIT
+
+ # --- Signing key + Sonatype token (shared secrets from LambdaMavenDeploy) ---
+ GPG_JSON=$(aws secretsmanager get-secret-value --secret-id maven.gpg.keys --query SecretString --output text)
+ CREDS_JSON=$(aws secretsmanager get-secret-value --secret-id maven.sonatype.creds --query SecretString --output text)
+ GPG_PRIVATE_KEY=$(jq -r '.private' <<< "$GPG_JSON")
+ GPG_PASSPHRASE=$(jq -r '.passphrase' <<< "$GPG_JSON")
+ SONATYPE_USERNAME=$(jq -r '."maven-central-login"' <<< "$CREDS_JSON")
+ SONATYPE_PASSWORD=$(jq -r '."maven-central-password"' <<< "$CREDS_JSON")
+ echo "::add-mask::$GPG_PASSPHRASE"
+ echo "::add-mask::$SONATYPE_USERNAME"
+ echo "::add-mask::$SONATYPE_PASSWORD"
+
+ # Import the key with loopback pinentry so Maven can sign non-interactively.
+ chmod 700 "$GNUPGHOME"
+ echo "allow-loopback-pinentry" > "$GNUPGHOME/gpg-agent.conf"
+ echo "pinentry-mode loopback" > "$GNUPGHOME/gpg.conf"
+ 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}')
+
+ # settings.xml with the Sonatype token (server id "central").
+ {
+ echo ''
+ echo "central"
+ echo "${SONATYPE_USERNAME}"
+ echo "${SONATYPE_PASSWORD}"
+ echo ''
+ } > "$MAVEN_SETTINGS"
+
+ # --- Publish ---
+ mvn deploy -Prelease -DskipTests -DmultiArch=false \
+ -s "$MAVEN_SETTINGS" \
+ -Dgpg.keyname="$GPG_KEYNAME" -Dgpg.passphrase="$GPG_PASSPHRASE" \
+ --file "$MODULE/pom.xml"
+
+ - name: Tag and push (only after publish succeeds)
+ if: ${{ github.event.inputs.skip_publish != 'true' }}
+ run: |
+ git commit -am "chore(ric): release ${EFFECTIVE_RELEASE_VERSION}"
+ git tag "$TAG_NAME"
+ mvn versions:set -DnewVersion="$NEXT_DEV_VERSION" -DgenerateBackupPoms=false --file "$MODULE/pom.xml"
+ git commit -am "chore(ric): prepare next development ${NEXT_DEV_VERSION}"
+ git push --atomic origin "HEAD:${GITHUB_REF_NAME}" "refs/tags/${TAG_NAME}"
+
+ # Dry-run: validate assembly, no publish/push.
+ - name: Dry-run assemble (no publish)
+ if: ${{ github.event.inputs.skip_publish == 'true' }}
+ env:
+ IS_JAVA_8: true
+ run: mvn package -DskipTests -DmultiArch=false --file "$MODULE/pom.xml"
+
+ # Nothing was pushed, so this only cleans the runner.
+ - name: Roll back local tag on failure
+ if: ${{ failure() && github.event.inputs.skip_publish != 'true' }}
+ run: |
+ git tag -d "$TAG_NAME" 2>/dev/null || true
+ echo "::warning::Release failed. The remote was not modified; safe to retry."
+
+ - name: Summary
+ if: ${{ github.event.inputs.skip_publish != 'true' }}
+ run: |
+ echo "## Release Summary" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
+ echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
+ echo "| Module | \`$MODULE\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| Version | \`$EFFECTIVE_RELEASE_VERSION\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| Tag | \`$TAG_NAME\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| Artifacts | main JAR + linux/linux_musl x x86_64/aarch_64 classifier JARs |" >> $GITHUB_STEP_SUMMARY
+ echo "| Built natively | x86_64 on ubuntu-latest, aarch_64 on ubuntu-24.04-arm (no QEMU) |" >> $GITHUB_STEP_SUMMARY
+ echo "| Maven Central | [com.amazonaws:$MODULE:$EFFECTIVE_RELEASE_VERSION](https://central.sonatype.com/artifact/com.amazonaws/$MODULE/$EFFECTIVE_RELEASE_VERSION) |" >> $GITHUB_STEP_SUMMARY
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 00000000..2305ade7
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,263 @@
+name: Release to Maven Central
+
+# Builds, tests, and publishes a module to Maven Central in one environment.
+
+on:
+ workflow_dispatch:
+ inputs:
+ module:
+ description: 'Module to release (directory name, e.g. aws-lambda-java-log4j2)'
+ required: true
+ type: choice
+ # aws-lambda-java-runtime-interface-client is intentionally excluded: it
+ # ships a cross-compiled JNI native library and has its own dedicated
+ # pipeline, .github/workflows/release-runtime-interface-client.yml.
+ options:
+ - 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
+ releaseVersion:
+ description: 'Release version override (optional; defaults to the POM version without -SNAPSHOT)'
+ required: false
+ type: string
+ developmentVersion:
+ description: 'Next development version override (optional, must end with -SNAPSHOT)'
+ required: false
+ type: string
+ skip_publish:
+ description: 'Skip publish (dry-run validation)'
+ required: false
+ type: boolean
+ default: false
+
+permissions:
+ contents: write
+ id-token: write
+
+# Serialize all releases repo-wide to avoid concurrent pushes racing on the
+# default branch. Never cancel in-flight: it could leave a half-published state.
+concurrency:
+ group: release
+ cancel-in-progress: false
+
+env:
+ MODULE: ${{ github.event.inputs.module }}
+ RELEASE_VERSION_INPUT: ${{ github.event.inputs.releaseVersion }}
+ DEVELOPMENT_VERSION_INPUT: ${{ github.event.inputs.developmentVersion }}
+ # 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 }}
+ OIDC_ROLE_ARN: ${{ secrets.AWS_ROLE_MAVEN_RELEASE }}
+
+jobs:
+ # Pre-publish gate for log4j2: deploy a real Lambda, invoke it,
+ # and assert the log line reaches CloudWatch. Binds the end-to-end validation
+ # to the publish event itself. Skipped for every other module, which are
+ # covered by their own tests (or the cross-module gate below).
+ integration-test:
+ if: ${{ github.event.inputs.module == 'aws-lambda-java-log4j2' }}
+ uses: ./.github/workflows/run-integration-test.yml
+ secrets: inherit
+
+ release:
+ needs: [integration-test]
+ # Publish when the gate passed, or when it was skipped for a non-log4j2
+ # module. A failed or cancelled gate blocks the release.
+ if: ${{ always() && (needs.integration-test.result == 'success' || needs.integration-test.result == 'skipped') }}
+ runs-on: ubuntu-latest
+ environment: Release
+ timeout-minutes: 30
+
+ steps:
+ # Manual (workflow_dispatch) releases must only run from main, never from
+ # an arbitrary branch that could carry unreviewed release logic.
+ - 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
+
+ # Pinned JDK 8: building on a newer JDK can silently break the artifact.
+ - name: Set up JDK 8
+ uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
+ with:
+ java-version: 8
+ distribution: corretto
+ cache: maven
+
+ - name: Resolve and validate release version
+ uses: ./.github/actions/resolve-release-version
+ with:
+ module: ${{ env.MODULE }}
+ release-version-override: ${{ env.RELEASE_VERSION_INPUT }}
+ validate-module-dir: "true"
+
+ - name: Validate development version override
+ run: |
+ if [[ -n "$DEVELOPMENT_VERSION_INPUT" && "$DEVELOPMENT_VERSION_INPUT" != *-SNAPSHOT ]]; then
+ echo "::error::developmentVersion '$DEVELOPMENT_VERSION_INPUT' must end with -SNAPSHOT"
+ exit 1
+ fi
+ echo "::notice::Releasing $MODULE $EFFECTIVE_RELEASE_VERSION (POM currently $CURRENT_VERSION)"
+
+ - name: Configure git user
+ run: |
+ git config user.name "github-actions[bot]"
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+
+ - name: Install intra-repo dependencies
+ run: |
+ # Installed so the target compiles. -DskipTests: not released here,
+ # only the target module gets the full verify gate below.
+ declare -A DEPS
+ DEPS[aws-lambda-java-core]=""
+ DEPS[aws-lambda-java-events]=""
+ DEPS[aws-lambda-java-serialization]=""
+ DEPS[aws-lambda-java-log4j2]="aws-lambda-java-core"
+ DEPS[aws-lambda-java-events-sdk-transformer]="aws-lambda-java-events"
+ DEPS[aws-lambda-java-tests]="aws-lambda-java-core aws-lambda-java-serialization aws-lambda-java-events"
+
+ DEP_LIST="${DEPS[$MODULE]}"
+ if [[ -n "$DEP_LIST" ]]; then
+ for dep in $DEP_LIST; do
+ echo "::group::Installing dependency: $dep"
+ mvn install -DskipTests --file "$dep/pom.xml"
+ echo "::endgroup::"
+ done
+ else
+ echo "::notice::No intra-repo dependencies for $MODULE"
+ fi
+
+ - name: Run tests
+ run: mvn verify --file "$MODULE/pom.xml"
+
+ # 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.
+ - name: Run cross-module test gate
+ run: |
+ case "$MODULE" in
+ aws-lambda-java-serialization)
+ MOD_VER=$(mvn -q -DforceStdout help:evaluate -Dexpression=project.version --file "$MODULE/pom.xml")
+ MOD_VER="${MOD_VER//[$'\r\n']/}"
+ 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::No cross-module test gate for $MODULE"
+ ;;
+ esac
+
+ - name: Configure AWS credentials (OIDC)
+ if: ${{ github.event.inputs.skip_publish != 'true' }}
+ uses: ./.github/actions/configure-release-aws-credentials
+ with:
+ aws-region: ${{ env.AWS_REGION }}
+ role-to-assume: ${{ env.OIDC_ROLE_ARN }}
+ role-session-name: GitHubActionsMavenCentralRelease
+
+ # Fetch signing material and publish in a single step so the GPG passphrase
+ # and Sonatype token stay in this shell and never cross a $GITHUB_ENV
+ # boundary, where a later (possibly compromised) step could read them.
+ # prepare/perform aren't atomic: prepare locally, publish, push only after.
+ - name: Release (prepare locally, publish, then push)
+ if: ${{ github.event.inputs.skip_publish != 'true' }}
+ run: |
+ # Scrub the settings.xml (contains the Sonatype token) and the keyring
+ # on exit, so no sensitive file is left on the runner even on failure.
+ MAVEN_SETTINGS="$RUNNER_TEMP/settings.xml"
+ export GNUPGHOME=$(mktemp -d)
+ trap 'rm -rf "$MAVEN_SETTINGS" "$GNUPGHOME"' EXIT
+
+ # --- Signing key + Sonatype token (shared secrets from LambdaMavenDeploy) ---
+ GPG_JSON=$(aws secretsmanager get-secret-value --secret-id maven.gpg.keys --query SecretString --output text)
+ CREDS_JSON=$(aws secretsmanager get-secret-value --secret-id maven.sonatype.creds --query SecretString --output text)
+ GPG_PRIVATE_KEY=$(jq -r '.private' <<< "$GPG_JSON")
+ GPG_PASSPHRASE=$(jq -r '.passphrase' <<< "$GPG_JSON")
+ SONATYPE_USERNAME=$(jq -r '."maven-central-login"' <<< "$CREDS_JSON")
+ SONATYPE_PASSWORD=$(jq -r '."maven-central-password"' <<< "$CREDS_JSON")
+ echo "::add-mask::$GPG_PASSPHRASE"
+ echo "::add-mask::$SONATYPE_USERNAME"
+ echo "::add-mask::$SONATYPE_PASSWORD"
+
+ # Import the key with loopback pinentry so Maven can sign non-interactively.
+ chmod 700 "$GNUPGHOME"
+ echo "allow-loopback-pinentry" > "$GNUPGHOME/gpg-agent.conf"
+ echo "pinentry-mode loopback" > "$GNUPGHOME/gpg.conf"
+ 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}')
+
+ # settings.xml with the Sonatype token (server id "central").
+ {
+ echo ''
+ echo "central"
+ echo "${SONATYPE_USERNAME}"
+ echo "${SONATYPE_PASSWORD}"
+ echo ''
+ } > "$MAVEN_SETTINGS"
+
+ # --- Release: build args as an array so each value is a single,
+ # properly quoted argument (no word-splitting of untrusted input). ---
+ RELEASE_ARGS=(-DreleaseVersion="$EFFECTIVE_RELEASE_VERSION")
+ if [[ -n "$DEVELOPMENT_VERSION_INPUT" ]]; then
+ RELEASE_ARGS+=(-DdevelopmentVersion="$DEVELOPMENT_VERSION_INPUT")
+ fi
+
+ # Prepare locally (no push): release commits + tag.
+ mvn release:prepare -DpushChanges=false "${RELEASE_ARGS[@]}" --file "$MODULE/pom.xml"
+
+ # perform forks a fresh build, so pass settings/gpg via -Darguments.
+ mvn release:perform -DlocalCheckout=true \
+ -Darguments="-s $MAVEN_SETTINGS -Prelease -Dgpg.keyname=$GPG_KEYNAME -Dgpg.passphrase=$GPG_PASSPHRASE" \
+ --file "$MODULE/pom.xml"
+
+ # Push commits + tag atomically, only after publish succeeded.
+ git push --atomic origin \
+ "HEAD:${GITHUB_REF_NAME}" \
+ "refs/tags/${MODULE}-${EFFECTIVE_RELEASE_VERSION}"
+
+ - name: Dry-run release (prepare only, no publish)
+ if: ${{ github.event.inputs.skip_publish == 'true' }}
+ run: |
+ RELEASE_ARGS=(-DreleaseVersion="$EFFECTIVE_RELEASE_VERSION")
+ if [[ -n "$DEVELOPMENT_VERSION_INPUT" ]]; then
+ RELEASE_ARGS+=(-DdevelopmentVersion="$DEVELOPMENT_VERSION_INPUT")
+ fi
+ mvn release:prepare -DdryRun=true "${RELEASE_ARGS[@]}" --file "$MODULE/pom.xml"
+ mvn release:clean --file "$MODULE/pom.xml" || true
+
+ # Nothing was pushed, so this only cleans the runner for a retry.
+ - name: Roll back release on failure
+ if: ${{ failure() && github.event.inputs.skip_publish != 'true' }}
+ 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
+ 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
+ echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
+ echo "| Module | \`$MODULE\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| Version | \`$EFFECTIVE_RELEASE_VERSION\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| Tag | \`$TAG_NAME\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| Maven Central | [com.amazonaws:$MODULE:$EFFECTIVE_RELEASE_VERSION](https://central.sonatype.com/artifact/com.amazonaws/$MODULE/$EFFECTIVE_RELEASE_VERSION) |" >> $GITHUB_STEP_SUMMARY
diff --git a/aws-lambda-java-core/pom.xml b/aws-lambda-java-core/pom.xml
index 0a11aa51..e9464e3d 100644
--- a/aws-lambda-java-core/pom.xml
+++ b/aws-lambda-java-core/pom.xml
@@ -5,7 +5,7 @@
com.amazonaws
aws-lambda-java-core
- 1.4.0
+ 1.4.0-SNAPSHOT
jar
AWS Lambda Java Core Library
@@ -22,6 +22,9 @@
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
@@ -38,6 +41,17 @@
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 3.1.1
+
+ aws-lambda-java-core-@{project.version}
+ true
+ release
+ deploy
+
+
org.apache.maven.plugins
maven-toolchains-plugin
@@ -140,6 +154,7 @@
true
central
+ true
diff --git a/aws-lambda-java-events-sdk-transformer/pom.xml b/aws-lambda-java-events-sdk-transformer/pom.xml
index 11054be1..1072f4cc 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-events-sdk-transformer
- 3.1.1
+ 3.1.1-SNAPSHOT
jar
AWS Lambda Java Events SDK Transformer Library
@@ -24,6 +24,9 @@
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
@@ -79,6 +82,17 @@
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 3.1.1
+
+ aws-lambda-java-events-sdk-transformer-@{project.version}
+ true
+ release
+ deploy
+
+
org.apache.maven.plugins
maven-toolchains-plugin
@@ -192,6 +206,7 @@
true
central
+ true
diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml
index 1ac5d798..7ab9aa93 100644
--- a/aws-lambda-java-events/pom.xml
+++ b/aws-lambda-java-events/pom.xml
@@ -5,7 +5,7 @@
com.amazonaws
aws-lambda-java-events
- 3.16.1
+ 3.16.1-SNAPSHOT
jar
AWS Lambda Java Events Library
@@ -22,6 +22,9 @@
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
@@ -65,6 +68,17 @@
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 3.1.1
+
+ aws-lambda-java-events-@{project.version}
+ true
+ release
+ deploy
+
+
@@ -187,6 +201,7 @@
true
central
+ true
diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml
index a03d3d3b..432c4f5c 100644
--- a/aws-lambda-java-log4j2/pom.xml
+++ b/aws-lambda-java-log4j2/pom.xml
@@ -5,7 +5,7 @@
com.amazonaws
aws-lambda-java-log4j2
- 1.6.4
+ 1.6.4-SNAPSHOT
jar
AWS Lambda Java Log4j 2.x Libraries
@@ -22,6 +22,9 @@
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
@@ -77,6 +80,17 @@
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 3.1.1
+
+ aws-lambda-java-log4j2-@{project.version}
+ true
+ release
+ deploy
+
+
org.apache.maven.plugins
maven-toolchains-plugin
@@ -183,6 +197,7 @@
true
central
+ true
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index ac62fd5b..a9c49c95 100644
--- a/aws-lambda-java-runtime-interface-client/pom.xml
+++ b/aws-lambda-java-runtime-interface-client/pom.xml
@@ -4,7 +4,7 @@
4.0.0
com.amazonaws
aws-lambda-java-runtime-interface-client
- 2.12.0
+ 2.12.0-SNAPSHOT
jar
AWS Lambda Java Runtime Interface Client
@@ -21,6 +21,9 @@
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
@@ -115,6 +118,17 @@
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 3.1.1
+
+ aws-lambda-java-runtime-interface-client-@{project.version}
+ true
+ release
+ deploy
+
+
org.apache.maven.plugins
maven-toolchains-plugin
@@ -402,6 +416,7 @@
true
central
+ true
diff --git a/aws-lambda-java-serialization/pom.xml b/aws-lambda-java-serialization/pom.xml
index 503f3e76..613b204c 100644
--- a/aws-lambda-java-serialization/pom.xml
+++ b/aws-lambda-java-serialization/pom.xml
@@ -4,7 +4,7 @@
com.amazonaws
aws-lambda-java-serialization
- 1.4.1
+ 1.4.1-SNAPSHOT
jar
AWS Lambda Java Runtime Serialization
@@ -19,6 +19,9 @@
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
@@ -175,6 +178,7 @@
true
central
+ true
@@ -191,6 +195,17 @@
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 3.1.1
+
+ aws-lambda-java-serialization-@{project.version}
+ true
+ release
+ deploy
+
+
org.apache.maven.plugins
maven-toolchains-plugin
diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml
index 4a25586c..b1daf410 100644
--- a/aws-lambda-java-tests/pom.xml
+++ b/aws-lambda-java-tests/pom.xml
@@ -5,7 +5,7 @@
com.amazonaws
aws-lambda-java-tests
- 1.1.3
+ 1.1.3-SNAPSHOT
jar
AWS Lambda Java Tests
@@ -20,6 +20,9 @@
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
@@ -236,6 +239,7 @@
true
central
+ true
@@ -245,6 +249,17 @@
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 3.1.1
+
+ aws-lambda-java-tests-@{project.version}
+ true
+ release
+ deploy
+
+
org.apache.maven.plugins
maven-toolchains-plugin