diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 60617434..f9d86434 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 }} @@ -162,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 @@ -174,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" @@ -252,6 +259,62 @@ 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) + if: ${{ github.event.inputs.skip_publish != 'true' }} + run: | + # (1) Module's lastPublished annotation. + 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 + + # 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 +336,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/.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 new file mode 100644 index 00000000..6b453a08 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,51 @@ +# 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, 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. + +## 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..a71dd719 100644 --- a/aws-lambda-java-core/pom.xml +++ b/aws-lambda-java-core/pom.xml @@ -3,9 +3,17 @@ 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 + 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..5248ac57 100644 --- a/aws-lambda-java-events-sdk-transformer/pom.xml +++ b/aws-lambda-java-events-sdk-transformer/pom.xml @@ -3,9 +3,16 @@ 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 + jar AWS Lambda Java Events SDK Transformer Library @@ -68,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 3bef204f..9103fbbc 100644 --- a/aws-lambda-java-events/pom.xml +++ b/aws-lambda-java-events/pom.xml @@ -3,9 +3,17 @@ 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 + jar AWS Lambda Java Events Library diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml index af39b277..1f09b3db 100644 --- a/aws-lambda-java-log4j2/pom.xml +++ b/aws-lambda-java-log4j2/pom.xml @@ -1,9 +1,16 @@ 4.0.0 - com.amazonaws + + com.amazonaws + aws-lambda-java-libs-parent + 1.0.0 + ../pom.xml + + aws-lambda-java-log4j2 1.6.6-SNAPSHOT + jar AWS Lambda Java Log4j 2.x Libraries @@ -50,7 +57,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 c9285672..40981c0e 100644 --- a/aws-lambda-java-serialization/pom.xml +++ b/aws-lambda-java-serialization/pom.xml @@ -2,9 +2,17 @@ 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 + jar AWS Lambda Java Runtime Serialization diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml index bb0c7ab7..dbe8d08f 100644 --- a/aws-lambda-java-tests/pom.xml +++ b/aws-lambda-java-tests/pom.xml @@ -3,9 +3,16 @@ 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 + jar AWS Lambda Java Tests @@ -43,8 +50,7 @@ --> 5.9.2 0.8.7 - 1.4.1 - 3.16.1 + 3.18.0 3.27.7 @@ -53,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 + + + + + + +