- * This class is intentionally package-private to support updates to
- * the aws-lambda-java-events and aws-lambda-java-serialization packages.
- * Consider making it public if there's a real request for it.
- *
*/
-class LambdaEventAssert {
+public class LambdaEventAssert {
private static final ObjectMapper MAPPER = new ObjectMapper();
From 7230727de124386f9e9e49c04f2586a384b1bb02 Mon Sep 17 00:00:00 2001
From: Maxime David
Date: Tue, 31 Mar 2026 13:40:49 -0400
Subject: [PATCH 071/129] fix: pin GitHub Actions (#601)
---
.github/workflows/repo-sync.yml | 4 ++--
.../runtime-interface-client_merge_to_main.yml | 12 ++++++------
.github/workflows/runtime-interface-client_pr.yml | 4 ++--
.github/workflows/samples.yml | 2 +-
4 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/.github/workflows/repo-sync.yml b/.github/workflows/repo-sync.yml
index 6a918fde3..4934754d8 100644
--- a/.github/workflows/repo-sync.yml
+++ b/.github/workflows/repo-sync.yml
@@ -22,7 +22,7 @@ jobs:
steps:
- uses: actions/checkout@v6
if: ${{ env.IS_CONFIGURED == 'true' }}
- - uses: repo-sync/github-sync@v2
+ - uses: repo-sync/github-sync@3832fe8e2be32372e1b3970bbae8e7079edeec88 # v2.3.0
name: Sync repo to branch
if: ${{ env.IS_CONFIGURED == 'true' }}
with:
@@ -30,7 +30,7 @@ jobs:
source_branch: main
destination_branch: ${{ secrets.INTERMEDIATE_BRANCH }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- - uses: repo-sync/pull-request@v2
+ - uses: repo-sync/pull-request@7e79a9f5dc3ad0ce53138f01df2fad14a04831c5 # v2.12.1
name: Create pull request
if: ${{ env.IS_CONFIGURED == 'true' }}
with:
diff --git a/.github/workflows/runtime-interface-client_merge_to_main.yml b/.github/workflows/runtime-interface-client_merge_to_main.yml
index f66310755..d0d479111 100644
--- a/.github/workflows/runtime-interface-client_merge_to_main.yml
+++ b/.github/workflows/runtime-interface-client_merge_to_main.yml
@@ -28,20 +28,20 @@ jobs:
contents: read
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Set up JDK 1.8
- uses: actions/setup-java@v5
+ uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
java-version: 8
distribution: corretto
cache: maven
- name: Set up QEMU
- uses: docker/setup-qemu-action@v3
+ uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
+ uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
with:
install: true
@@ -62,7 +62,7 @@ jobs:
if: env.ENABLE_SNAPSHOT != null
env:
ENABLE_SNAPSHOT: ${{ secrets.ENABLE_SNAPSHOT }}
- uses: aws-actions/configure-aws-credentials@v4
+ uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4
with:
aws-region: ${{ secrets.AWS_REGION }}
role-to-assume: ${{ secrets.AWS_ROLE }}
@@ -91,6 +91,6 @@ jobs:
- name: Upload coverage to Codecov
if: env.CODECOV_TOKEN != null
- uses: codecov/codecov-action@v5
+ uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.github/workflows/runtime-interface-client_pr.yml b/.github/workflows/runtime-interface-client_pr.yml
index 645f1069c..e0522005b 100644
--- a/.github/workflows/runtime-interface-client_pr.yml
+++ b/.github/workflows/runtime-interface-client_pr.yml
@@ -58,7 +58,7 @@ jobs:
cache: maven
- name: Set up QEMU
- uses: docker/setup-qemu-action@v3
+ uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
@@ -90,6 +90,6 @@ jobs:
- name: Upload coverage to Codecov
if: env.CODECOV_TOKEN != null
- uses: codecov/codecov-action@v5
+ uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.github/workflows/samples.yml b/.github/workflows/samples.yml
index ef961c3e0..68e25827d 100644
--- a/.github/workflows/samples.yml
+++ b/.github/workflows/samples.yml
@@ -73,7 +73,7 @@ jobs:
# Build custom-serialization samples
- name: install sam
- uses: aws-actions/setup-sam@v2
+ uses: aws-actions/setup-sam@d78e1a4a9656d3b223e59b80676a797f20093133 # v2
- name: test fastJson
run: cd samples/custom-serialization/fastJson && sam build && sam local invoke -e events/event.json | grep 200
- name: test gson
From c4dcbab4ffeda26ec9dff997d6ef02a9ee2ab013 Mon Sep 17 00:00:00 2001
From: Maxime David
Date: Wed, 1 Apr 2026 08:43:15 -0400
Subject: [PATCH 072/129] fix: pinning actions (#602)
---
.github/workflows/aws-lambda-java-profiler.yml | 8 ++++----
.github/workflows/runtime-interface-client_pr.yml | 12 ++++++------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/aws-lambda-java-profiler.yml b/.github/workflows/aws-lambda-java-profiler.yml
index 485d93110..a098bfd14 100644
--- a/.github/workflows/aws-lambda-java-profiler.yml
+++ b/.github/workflows/aws-lambda-java-profiler.yml
@@ -22,17 +22,17 @@ jobs:
contents: read
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Set up JDK
- uses: actions/setup-java@v5
+ uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
java-version: 21
distribution: corretto
cache: maven
- name: Issue AWS credentials
- uses: aws-actions/configure-aws-credentials@v4
+ uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4
with:
aws-region: ${{ secrets.AWS_REGION_PROFILER_EXTENSION_INTEGRATION_TEST }}
role-to-assume: ${{ secrets.AWS_ROLE_PROFILER_EXTENSION_INTEGRATION_TEST }}
@@ -68,7 +68,7 @@ jobs:
run: ./integration_tests/download_from_s3.sh
- name: Upload profiles
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: profiles
path: /tmp/s3-artifacts
diff --git a/.github/workflows/runtime-interface-client_pr.yml b/.github/workflows/runtime-interface-client_pr.yml
index e0522005b..a0d8c6cc8 100644
--- a/.github/workflows/runtime-interface-client_pr.yml
+++ b/.github/workflows/runtime-interface-client_pr.yml
@@ -22,10 +22,10 @@ jobs:
smoke-test:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Set up JDK 1.8
- uses: actions/setup-java@v5
+ uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
java-version: 8
distribution: corretto
@@ -48,10 +48,10 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Set up JDK 1.8
- uses: actions/setup-java@v5
+ uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
java-version: 8
distribution: corretto
@@ -61,7 +61,7 @@ jobs:
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
+ uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
with:
install: true
@@ -83,7 +83,7 @@ jobs:
IS_JAVA_8: true
- name: Save the built jar
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: aws-lambda-java-runtime-interface-client
path: ./aws-lambda-java-runtime-interface-client/target/aws-lambda-java-runtime-interface-client-*.jar
From 04c165c61d4d916171295443c0e75268c9a2a9e0 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 13 May 2026 12:02:38 +0100
Subject: [PATCH 073/129] chore(deps): bump org.apache.logging.log4j:log4j-core
(#603)
Bumps org.apache.logging.log4j:log4j-core from 2.25.3 to 2.25.4.
---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-core
dependency-version: 2.25.4
dependency-type: direct:production
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
aws-lambda-java-log4j2/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml
index 0124598a0..7c45c10bb 100644
--- a/aws-lambda-java-log4j2/pom.xml
+++ b/aws-lambda-java-log4j2/pom.xml
@@ -34,7 +34,7 @@
1.81.8
- 2.25.3
+ 2.25.4
From 319b771fb20729d649b95a448c69b2777a063b07 Mon Sep 17 00:00:00 2001
From: Davide Melfi
Date: Wed, 13 May 2026 18:08:29 +0100
Subject: [PATCH 074/129] chore(release): release aws-lambda-java-log4j2 ver
1.6.3 (#604)
---
aws-lambda-java-log4j2/README.md | 10 +++++-----
aws-lambda-java-log4j2/RELEASE.CHANGELOG.md | 8 ++++++++
aws-lambda-java-log4j2/pom.xml | 2 +-
3 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/aws-lambda-java-log4j2/README.md b/aws-lambda-java-log4j2/README.md
index f13121750..b626226ad 100644
--- a/aws-lambda-java-log4j2/README.md
+++ b/aws-lambda-java-log4j2/README.md
@@ -10,22 +10,22 @@ Example for Maven pom.xml
com.amazonawsaws-lambda-java-log4j2
- 1.6.0
+ 1.6.3org.apache.logging.log4jlog4j-core
- 2.17.1
+ 2.25.4org.apache.logging.log4jlog4j-api
- 2.17.1
+ 2.25.4org.apache.logging.log4jlog4j-layout-template-json
- 2.17.1
+ 2.25.4
....
@@ -73,7 +73,7 @@ If you are using the [John Rengelman](https://github.com/johnrengelman/shadow) G
dependencies{
...
- implementation group: 'com.amazonaws', name: 'aws-lambda-java-log4j2', version: '1.6.0'
+ implementation group: 'com.amazonaws', name: 'aws-lambda-java-log4j2', version: '1.6.3'
implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: log4jVersion
implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: log4jVersion
}
diff --git a/aws-lambda-java-log4j2/RELEASE.CHANGELOG.md b/aws-lambda-java-log4j2/RELEASE.CHANGELOG.md
index 49535d388..44528432d 100644
--- a/aws-lambda-java-log4j2/RELEASE.CHANGELOG.md
+++ b/aws-lambda-java-log4j2/RELEASE.CHANGELOG.md
@@ -1,3 +1,11 @@
+### May 13, 2026
+`1.6.3`:
+- Updated `log4j-core` and `log4j-api` dependencies to `2.25.4`
+
+### February 2026
+`1.6.2`:
+- Updated `log4j-core` and `log4j-api` dependencies to `2.25.3`
+
### October 24, 2023
`1.6.0`:
- Log level and log format support
diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml
index 7c45c10bb..570f8ce34 100644
--- a/aws-lambda-java-log4j2/pom.xml
+++ b/aws-lambda-java-log4j2/pom.xml
@@ -5,7 +5,7 @@
com.amazonawsaws-lambda-java-log4j2
- 1.6.1
+ 1.6.3jarAWS Lambda Java Log4j 2.x Libraries
From 0360241778aaf4f4deca83efa6ed6463867f324c Mon Sep 17 00:00:00 2001
From: Davide Melfi
Date: Fri, 15 May 2026 14:23:52 +0100
Subject: [PATCH 075/129] chore(release): release
aws-lambda-runtime-interface-client ver 2.11.0 (#605)
---
aws-lambda-java-runtime-interface-client/README.md | 4 ++--
aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md | 4 ++++
aws-lambda-java-runtime-interface-client/pom.xml | 4 ++--
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/aws-lambda-java-runtime-interface-client/README.md b/aws-lambda-java-runtime-interface-client/README.md
index c448e7a89..b72a6238c 100644
--- a/aws-lambda-java-runtime-interface-client/README.md
+++ b/aws-lambda-java-runtime-interface-client/README.md
@@ -70,7 +70,7 @@ pom.xml
com.amazonawsaws-lambda-java-runtime-interface-client
- 2.10.1
+ 2.11.0
@@ -203,7 +203,7 @@ platform-specific JAR by setting the ``.
com.amazonawsaws-lambda-java-runtime-interface-client
- 2.10.1
+ 2.11.0linux-x86_64
```
diff --git a/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md b/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
index 94a8a8057..883bd56da 100644
--- a/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
+++ b/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
@@ -1,3 +1,7 @@
+### May 13, 2026
+`2.11.0`
+- Update aws-lambda-java-serialization dependency to 1.4.0
+
### March 19, 2026
`2.10.1`
- Revert aws-lambda-java-serialization dependency to 1.2.0
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index a09fd3df7..47e79a623 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.0com.amazonawsaws-lambda-java-runtime-interface-client
- 2.10.1
+ 2.11.0jarAWS Lambda Java Runtime Interface Client
@@ -67,7 +67,7 @@
com.amazonawsaws-lambda-java-serialization
- 1.2.0
+ 1.4.0software.amazon.awssdk
From 93f6d540705e5b2e24d9baf2f73507f00e2d7ff8 Mon Sep 17 00:00:00 2001
From: Davide Melfi
Date: Tue, 19 May 2026 19:13:38 +0100
Subject: [PATCH 076/129] Update Log4J version to fix regression (#613)
* chore: update version
* chore: updating release note and changelog
---
aws-lambda-java-log4j2/README.md | 4 ++--
aws-lambda-java-log4j2/RELEASE.CHANGELOG.md | 4 ++++
aws-lambda-java-log4j2/pom.xml | 2 +-
3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/aws-lambda-java-log4j2/README.md b/aws-lambda-java-log4j2/README.md
index b626226ad..480df21df 100644
--- a/aws-lambda-java-log4j2/README.md
+++ b/aws-lambda-java-log4j2/README.md
@@ -10,7 +10,7 @@ Example for Maven pom.xml
com.amazonawsaws-lambda-java-log4j2
- 1.6.3
+ 1.6.4org.apache.logging.log4j
@@ -73,7 +73,7 @@ If you are using the [John Rengelman](https://github.com/johnrengelman/shadow) G
dependencies{
...
- implementation group: 'com.amazonaws', name: 'aws-lambda-java-log4j2', version: '1.6.3'
+ implementation group: 'com.amazonaws', name: 'aws-lambda-java-log4j2', version: '1.6.4'
implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: log4jVersion
implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: log4jVersion
}
diff --git a/aws-lambda-java-log4j2/RELEASE.CHANGELOG.md b/aws-lambda-java-log4j2/RELEASE.CHANGELOG.md
index 44528432d..5f43862a3 100644
--- a/aws-lambda-java-log4j2/RELEASE.CHANGELOG.md
+++ b/aws-lambda-java-log4j2/RELEASE.CHANGELOG.md
@@ -1,3 +1,7 @@
+### May 19, 2026
+`1.6.4`:
+- Fix regression in `1.6.3`
+
### May 13, 2026
`1.6.3`:
- Updated `log4j-core` and `log4j-api` dependencies to `2.25.4`
diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml
index 570f8ce34..6f142d57c 100644
--- a/aws-lambda-java-log4j2/pom.xml
+++ b/aws-lambda-java-log4j2/pom.xml
@@ -5,7 +5,7 @@
com.amazonawsaws-lambda-java-log4j2
- 1.6.3
+ 1.6.4jarAWS Lambda Java Log4j 2.x Libraries
From 8adb3d76a813964e1ae2ca3aeded62b0407ed80f Mon Sep 17 00:00:00 2001
From: Davide Melfi
Date: Wed, 20 May 2026 15:35:50 +0100
Subject: [PATCH 077/129] chore (update): update version of serialization to
1.4.1 (#614)
---
aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md | 2 +-
aws-lambda-java-runtime-interface-client/pom.xml | 2 +-
aws-lambda-java-serialization/RELEASE.CHANGELOG.md | 4 ++++
aws-lambda-java-serialization/pom.xml | 2 +-
aws-lambda-java-tests/pom.xml | 2 +-
5 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md b/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
index 883bd56da..2391045fc 100644
--- a/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
+++ b/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
@@ -1,6 +1,6 @@
### May 13, 2026
`2.11.0`
-- Update aws-lambda-java-serialization dependency to 1.4.0
+- Update aws-lambda-java-serialization dependency to 1.4.1
### March 19, 2026
`2.10.1`
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index 47e79a623..2ba71c43c 100644
--- a/aws-lambda-java-runtime-interface-client/pom.xml
+++ b/aws-lambda-java-runtime-interface-client/pom.xml
@@ -67,7 +67,7 @@
com.amazonawsaws-lambda-java-serialization
- 1.4.0
+ 1.4.1software.amazon.awssdk
diff --git a/aws-lambda-java-serialization/RELEASE.CHANGELOG.md b/aws-lambda-java-serialization/RELEASE.CHANGELOG.md
index d68d7b1fe..3bb977937 100644
--- a/aws-lambda-java-serialization/RELEASE.CHANGELOG.md
+++ b/aws-lambda-java-serialization/RELEASE.CHANGELOG.md
@@ -1,3 +1,7 @@
+### May 20, 2026
+`1.4.1`:
+- Fix build issue
+
### March 26, 2026
`1.4.0`:
- Update `jackson-databind` dependency from 2.15.4 to 2.18.6
diff --git a/aws-lambda-java-serialization/pom.xml b/aws-lambda-java-serialization/pom.xml
index d412fd765..60a3c67a9 100644
--- a/aws-lambda-java-serialization/pom.xml
+++ b/aws-lambda-java-serialization/pom.xml
@@ -4,7 +4,7 @@
com.amazonawsaws-lambda-java-serialization
- 1.4.0
+ 1.4.1jarAWS Lambda Java Runtime Serialization
diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml
index e63e529a2..5e5f19b33 100644
--- a/aws-lambda-java-tests/pom.xml
+++ b/aws-lambda-java-tests/pom.xml
@@ -40,7 +40,7 @@
-->
5.9.20.8.7
- 1.4.0
+ 1.4.13.16.13.18.03.27.7
From 1901fac6f7224288396cdc4b44bf0ae53a0f35a5 Mon Sep 17 00:00:00 2001
From: Davide Melfi
Date: Sat, 23 May 2026 08:20:20 +0100
Subject: [PATCH 078/129] build: Pin compilation to JDK 8 via Maven Toolchains
---
aws-lambda-java-core/pom.xml | 26 +++++++++++++++++++
.../pom.xml | 21 +++++++++++++++
aws-lambda-java-events/pom.xml | 26 +++++++++++++++++++
.../pom.xml | 21 +++++++++++++++
aws-lambda-java-serialization/pom.xml | 21 +++++++++++++++
aws-lambda-java-tests/pom.xml | 21 +++++++++++++++
6 files changed, 136 insertions(+)
diff --git a/aws-lambda-java-core/pom.xml b/aws-lambda-java-core/pom.xml
index cca9d0cdf..0a11aa517 100644
--- a/aws-lambda-java-core/pom.xml
+++ b/aws-lambda-java-core/pom.xml
@@ -36,6 +36,32 @@
1.8
+
+
+
+ org.apache.maven.plugins
+ maven-toolchains-plugin
+ 3.2.0
+
+
+
+
+ [1.8,9)
+
+
+
+
+
+
+ toolchain
+
+
+
+
+
+
+
dev
diff --git a/aws-lambda-java-events-sdk-transformer/pom.xml b/aws-lambda-java-events-sdk-transformer/pom.xml
index 6de599ef7..11054be12 100644
--- a/aws-lambda-java-events-sdk-transformer/pom.xml
+++ b/aws-lambda-java-events-sdk-transformer/pom.xml
@@ -79,6 +79,27 @@
+
+ org.apache.maven.plugins
+ maven-toolchains-plugin
+ 3.2.0
+
+
+
+
+ [1.8,9)
+
+
+
+
+
+
+ toolchain
+
+
+
+ maven-surefire-plugin${maven-surefire-plugin.version}
diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml
index c8c40e0c7..1ac5d7981 100644
--- a/aws-lambda-java-events/pom.xml
+++ b/aws-lambda-java-events/pom.xml
@@ -42,6 +42,32 @@
5.12.2
+
+
+
+ org.apache.maven.plugins
+ maven-toolchains-plugin
+ 3.2.0
+
+
+
+
+ [1.8,9)
+
+
+
+
+
+
+ toolchain
+
+
+
+
+
+
+
sonatype-nexus-staging
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index 2ba71c43c..fa543df00 100644
--- a/aws-lambda-java-runtime-interface-client/pom.xml
+++ b/aws-lambda-java-runtime-interface-client/pom.xml
@@ -115,6 +115,27 @@
+
+ org.apache.maven.plugins
+ maven-toolchains-plugin
+ 3.2.0
+
+
+
+
+ [1.8,9)
+
+
+
+
+
+
+ toolchain
+
+
+
+ maven-install-pluginorg.apache.maven.plugins
diff --git a/aws-lambda-java-serialization/pom.xml b/aws-lambda-java-serialization/pom.xml
index 60a3c67a9..503f3e76f 100644
--- a/aws-lambda-java-serialization/pom.xml
+++ b/aws-lambda-java-serialization/pom.xml
@@ -191,6 +191,27 @@
+
+ org.apache.maven.plugins
+ maven-toolchains-plugin
+ 3.2.0
+
+
+
+
+ [1.8,9)
+
+
+
+
+
+
+ toolchain
+
+
+
+ org.apache.maven.pluginsmaven-shade-plugin
diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml
index 5e5f19b33..4a25586ce 100644
--- a/aws-lambda-java-tests/pom.xml
+++ b/aws-lambda-java-tests/pom.xml
@@ -245,6 +245,27 @@
+
+ org.apache.maven.plugins
+ maven-toolchains-plugin
+ 3.2.0
+
+
+
+
+ [1.8,9)
+
+
+
+
+
+
+ toolchain
+
+
+
+ org.apache.maven.pluginsmaven-compiler-plugin
From 2714c2c38c11fd198f8e3ce75feae7d3627a5933 Mon Sep 17 00:00:00 2001
From: Ryan Schmitt
Date: Sat, 23 May 2026 06:44:21 -0700
Subject: [PATCH 079/129] test(log4j2): Add initial test suite covering plugin
registration (#615)
This package previously had no tests and no JUnit dependency. Add
JUnit Jupiter, the surefire plugin, and an initial test class that
exercises the full plugin resolution path end-to-end: a log4j2.xml
on the test classpath, a real LogManager-issued logger, and stdout
capture (LambdaAppender writes through LambdaRuntime.getLogger() to
System.out).
The TEXT test routes the root logger through LambdaTextFormat with a
deterministic PatternLayout and asserts each level appears. The JSON
test adds a second LambdaAppender with format="JSON" backed by
JsonTemplateLayout + LambdaLayout.json, attached via additivity=false
to a "json-test" logger, and asserts the messages show up
JSON-encoded.
Add log4j-layout-template-json at test scope so the JSON path can
resolve at test time. Users are still expected to bring their own
copy at runtime (peer-dependency model, like PatternLayout); the
published artifact's dependency surface is unchanged.
The tests succeed on Java 8 and fail on Java 25, because annotation
processors are not run by default on Java 25, Log4j2Plugins.dat is
not generated for our plugins, and both tests surface the resulting
CLASS_NOT_FOUND from the log4j status logger.
---
aws-lambda-java-log4j2/pom.xml | 25 +++++-
.../log4j2/LambdaAppenderPluginTest.java | 86 +++++++++++++++++++
.../src/test/resources/log4j2.xml | 25 ++++++
3 files changed, 135 insertions(+), 1 deletion(-)
create mode 100644 aws-lambda-java-log4j2/src/test/java/com/amazonaws/services/lambda/runtime/log4j2/LambdaAppenderPluginTest.java
create mode 100644 aws-lambda-java-log4j2/src/test/resources/log4j2.xml
diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml
index 6f142d57c..469c2e1f0 100644
--- a/aws-lambda-java-log4j2/pom.xml
+++ b/aws-lambda-java-log4j2/pom.xml
@@ -35,6 +35,7 @@
1.81.82.25.4
+ 5.12.2
@@ -60,8 +61,30 @@
log4j-api${log4j.version}
+
+ org.apache.logging.log4j
+ log4j-layout-template-json
+ ${log4j.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit-jupiter.version}
+ test
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.5.2
+
+
+
+
dev
@@ -146,4 +169,4 @@
-
\ No newline at end of file
+
diff --git a/aws-lambda-java-log4j2/src/test/java/com/amazonaws/services/lambda/runtime/log4j2/LambdaAppenderPluginTest.java b/aws-lambda-java-log4j2/src/test/java/com/amazonaws/services/lambda/runtime/log4j2/LambdaAppenderPluginTest.java
new file mode 100644
index 000000000..0bcd057a6
--- /dev/null
+++ b/aws-lambda-java-log4j2/src/test/java/com/amazonaws/services/lambda/runtime/log4j2/LambdaAppenderPluginTest.java
@@ -0,0 +1,86 @@
+/* Copyright 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved. */
+
+package com.amazonaws.services.lambda.runtime.log4j2;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class LambdaAppenderPluginTest {
+
+ private final PrintStream originalOut = System.out;
+ private ByteArrayOutputStream captured;
+
+ @BeforeEach
+ void redirectStdout() throws UnsupportedEncodingException {
+ captured = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(captured, true, StandardCharsets.UTF_8.name()));
+ }
+
+ @AfterEach
+ void restoreStdout() {
+ System.setOut(originalOut);
+ }
+
+ @Test
+ void lambdaAppenderEmitsLogsAtVariousLevels() throws UnsupportedEncodingException {
+ Logger logger = LogManager.getLogger(LambdaAppenderPluginTest.class);
+
+ logger.debug("debug-msg");
+ logger.info("info-msg");
+ logger.warn("warn-msg");
+ logger.error("error-msg");
+
+ String output = captured.toString(StandardCharsets.UTF_8.name());
+
+ // The PatternLayout in src/test/resources/log4j2.xml is "%-5p %c{1} - %m%n",
+ // so each event should appear as " LambdaAppenderPluginTest - ".
+ assertTrue(output.contains("DEBUG LambdaAppenderPluginTest - debug-msg"),
+ "expected DEBUG line in output but got:\n" + output);
+ assertTrue(output.contains("INFO LambdaAppenderPluginTest - info-msg"),
+ "expected INFO line in output but got:\n" + output);
+ assertTrue(output.contains("WARN LambdaAppenderPluginTest - warn-msg"),
+ "expected WARN line in output but got:\n" + output);
+ assertTrue(output.contains("ERROR LambdaAppenderPluginTest - error-msg"),
+ "expected ERROR line in output but got:\n" + output);
+
+ // Sanity check: log4j should not have fallen back to its default
+ // ConsoleAppender / status logger error message.
+ assertFalse(output.contains("ERROR StatusLogger"),
+ "log4j status logger reported an error, output was:\n" + output);
+ }
+
+ @Test
+ void lambdaAppenderEmitsJsonForJsonFormatLogger() throws UnsupportedEncodingException {
+ // The "json-test" logger is configured in src/test/resources/log4j2.xml
+ // with additivity=false to a second LambdaAppender using format="JSON"
+ // and JsonTemplateLayout backed by LambdaLayout.json.
+ Logger logger = LogManager.getLogger("json-test");
+
+ logger.info("json-info-msg");
+ logger.error("json-error-msg");
+
+ String output = captured.toString(StandardCharsets.UTF_8.name());
+
+ assertTrue(output.contains("json-info-msg"),
+ "expected json-info-msg in output but got:\n" + output);
+ assertTrue(output.contains("json-error-msg"),
+ "expected json-error-msg in output but got:\n" + output);
+
+ // Output should look like JSON, not the text PatternLayout from the
+ // root logger — so it must contain JSON field punctuation around the
+ // message rather than the "INFO json-test - ..." text pattern.
+ assertTrue(output.contains("\"message\":\"json-info-msg\""),
+ "expected JSON-encoded message field but got:\n" + output);
+ }
+}
diff --git a/aws-lambda-java-log4j2/src/test/resources/log4j2.xml b/aws-lambda-java-log4j2/src/test/resources/log4j2.xml
new file mode 100644
index 000000000..7b43094e2
--- /dev/null
+++ b/aws-lambda-java-log4j2/src/test/resources/log4j2.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ %-5p %c{1} - %m%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
From 0abf6d7b52e6b7e4d4ed129ecb1b06188eaa14d6 Mon Sep 17 00:00:00 2001
From: Ryan Schmitt
Date: Sat, 23 May 2026 06:55:56 -0700
Subject: [PATCH 080/129] build(log4j2): Pin compilation to JDK 8 via Maven
Toolchains (#616)
Release 1.6.3 was built on a JDK that does not run annotation processors
by default, which silently dropped the Log4j2 plugin descriptor
(META-INF/.../Log4j2Plugins.dat) for LambdaAppender, LambdaTextFormat,
and LambdaJsonFormat. The published artifact was broken at runtime:
log4j could not resolve , , or
elements in user log4j2.xml configurations.
Configure maven-toolchains-plugin to require a JDK 8 toolchain so javac
comes from a JDK that runs annotation processors by default, regardless
of which JVM Maven is invoked under. The version range [1.8,9) matches
both "1.8" and "8".
The existing GitHub Actions workflow at
.github/workflows/aws-lambda-java-log4j2.yml uses actions/setup-java@v5
with java-version: 8 and distribution: corretto. setup-java@v5
auto-generates a ~/.m2/toolchains.xml entry with 8,
which the [1.8,9) range matches, so no workflow changes are required.
When no matching JDK 8 toolchain is available, the build now fails fast
at the validate phase with a clear "Cannot find matching toolchain
definitions" error instead of silently producing an artifact missing its
plugin descriptor.
Co-authored-by: Davide Melfi
---
aws-lambda-java-log4j2/pom.xml | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml
index 469c2e1f0..a03d3d3b6 100644
--- a/aws-lambda-java-log4j2/pom.xml
+++ b/aws-lambda-java-log4j2/pom.xml
@@ -79,6 +79,26 @@
org.apache.maven.plugins
+ maven-toolchains-plugin
+ 3.2.0
+
+
+
+
+ [1.8,9)
+
+
+
+
+
+
+ toolchain
+
+
+
+
+ maven-surefire-plugin3.5.2
From cfefd3bb692597d1f5effa9c99f84021cd35f0e0 Mon Sep 17 00:00:00 2001
From: Jonathan Tuliani
Date: Fri, 29 May 2026 15:16:43 +0100
Subject: [PATCH 081/129] Update README.md to add note re v1.6.3 regression
(#618)
Added note regarding v1.6.3.
---
aws-lambda-java-log4j2/README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/aws-lambda-java-log4j2/README.md b/aws-lambda-java-log4j2/README.md
index 480df21df..d8e40ebea 100644
--- a/aws-lambda-java-log4j2/README.md
+++ b/aws-lambda-java-log4j2/README.md
@@ -1,5 +1,7 @@
# Using log4j2 with AWS Lambda
+**IMPORTANT: The v1.6.3 release contained a regression (see [#612](https://github.com/aws/aws-lambda-java-libs/issues/612)) resulting in missing logs. Please upgrade to v1.6.4 or later. We apologize for the inconvenience.**
+
### 1. Pull in log4j2 dependencies
Example for Maven pom.xml
From 845ae2a86b8ee4db8c8037b8c29b49d510ffd448 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Mon, 29 Jun 2026 12:11:22 +0100
Subject: [PATCH 082/129] Add end-to-end integration tests
---
.github/workflows/build-integration-test.yml | 56 ++++++++++
.github/workflows/run-integration-test.yml | 102 +++++++++++++++++
.../log4j2-test-function/pom.xml | 77 +++++++++++++
.../main/java/integ/Log4j2TestHandler.java | 30 +++++
.../src/main/resources/log4j2.xml | 17 +++
lambda-integration-tests/run-tests.sh | 103 ++++++++++++++++++
lambda-integration-tests/samconfig.toml | 24 ++++
lambda-integration-tests/template.yaml | 34 ++++++
8 files changed, 443 insertions(+)
create mode 100644 .github/workflows/build-integration-test.yml
create mode 100644 .github/workflows/run-integration-test.yml
create mode 100644 lambda-integration-tests/log4j2-test-function/pom.xml
create mode 100644 lambda-integration-tests/log4j2-test-function/src/main/java/integ/Log4j2TestHandler.java
create mode 100644 lambda-integration-tests/log4j2-test-function/src/main/resources/log4j2.xml
create mode 100755 lambda-integration-tests/run-tests.sh
create mode 100644 lambda-integration-tests/samconfig.toml
create mode 100644 lambda-integration-tests/template.yaml
diff --git a/.github/workflows/build-integration-test.yml b/.github/workflows/build-integration-test.yml
new file mode 100644
index 000000000..5f5e82d13
--- /dev/null
+++ b/.github/workflows/build-integration-test.yml
@@ -0,0 +1,56 @@
+# this workflow verifies that the integration test Lambda function builds successfully.
+# it does NOT deploy or run the tests (that requires AWS credentials and is done in
+# run-integration-test.yml).
+
+name: Build integration tests
+
+on:
+ push:
+ branches: [ main ]
+ paths:
+ - 'aws-lambda-java-log4j2/**'
+ - 'aws-lambda-java-core/**'
+ - 'lambda-integration-tests/**'
+ pull_request:
+ branches: [ '*' ]
+ paths:
+ - 'aws-lambda-java-log4j2/**'
+ - 'aws-lambda-java-core/**'
+ - 'lambda-integration-tests/**'
+ - '.github/workflows/build-integration-test.yml'
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v6
+
+ - name: Set up JDK
+ uses: actions/setup-java@v5
+ with:
+ java-version: |
+ 8
+ 21
+ distribution: corretto
+ cache: maven
+
+ - name: Install core with Maven
+ run: |
+ export JAVA_HOME=$JAVA_HOME_8_X64
+ mvn -B install --file aws-lambda-java-core/pom.xml
+
+ - name: Install log4j2 with Maven
+ run: |
+ export JAVA_HOME=$JAVA_HOME_8_X64
+ mvn -B install --file aws-lambda-java-log4j2/pom.xml
+
+ # build the integration test function
+ # this verifies that the function compiles and packages correctly.
+ # the tests will run in run-integration-test.yml which deploys to AWS.
+ - name: Package integration test function
+ run: |
+ export JAVA_HOME=$JAVA_HOME_21_X64
+ mvn -B package --file lambda-integration-tests/log4j2-test-function/pom.xml
diff --git a/.github/workflows/run-integration-test.yml b/.github/workflows/run-integration-test.yml
new file mode 100644
index 000000000..667e76d96
--- /dev/null
+++ b/.github/workflows/run-integration-test.yml
@@ -0,0 +1,102 @@
+# this workflow deploys a Lambda function that uses aws-lambda-java-log4j2,
+# invokes it, and verifies that logs arrive in CloudWatch.
+
+name: Run integration tests
+
+permissions:
+ id-token: write
+ contents: read
+
+on:
+ workflow_dispatch:
+ push:
+ branches: [ main ]
+ paths:
+ - 'aws-lambda-java-log4j2/**'
+ - 'aws-lambda-java-core/**'
+ - 'lambda-integration-tests/**'
+
+jobs:
+ run-integration-tests:
+ # Only run on the main repo, not forks
+ if: ${{ github.repository_owner == 'aws' }}
+ runs-on: ubuntu-latest
+ concurrency:
+ group: integration-test
+ cancel-in-progress: false
+ steps:
+ - uses: actions/checkout@v6
+
+ - name: Set up JDK
+ uses: actions/setup-java@v5
+ with:
+ java-version: |
+ 8
+ 21
+ distribution: corretto
+ cache: maven
+
+ - name: Install SAM CLI
+ uses: aws-actions/setup-sam@v2
+ with:
+ use-installer: true
+
+ - name: Configure AWS credentials
+ uses: aws-actions/configure-aws-credentials@v6.0.0
+ with:
+ role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
+ role-session-name: ${{ secrets.ROLE_SESSION_NAME }}
+ aws-region: ${{ secrets.AWS_REGION }}
+
+ - name: Install core with Maven
+ run: |
+ export JAVA_HOME=$JAVA_HOME_8_X64
+ mvn -B install --file aws-lambda-java-core/pom.xml
+
+ - name: Install log4j2 with Maven
+ run: |
+ export JAVA_HOME=$JAVA_HOME_8_X64
+ mvn -B install --file aws-lambda-java-log4j2/pom.xml
+
+ - name: Build SAM stack
+ run: |
+ export JAVA_HOME=$JAVA_HOME_21_X64
+ cd lambda-integration-tests && sam build
+
+ - name: Validate SAM stack
+ run: cd lambda-integration-tests && sam validate --lint
+
+ - name: Deploy stack
+ id: deploy_stack
+ env:
+ AWS_REGION: ${{ secrets.AWS_REGION }}
+ run: |
+ cd lambda-integration-tests
+ stackName="aws-lambda-java-log4j2-integ-test-$GITHUB_RUN_ID"
+ echo "STACK_NAME=$stackName" >> "$GITHUB_OUTPUT"
+ echo "Stack name = $stackName"
+ sam deploy \
+ --stack-name "${stackName}" \
+ --parameter-overrides "ParameterKey=LambdaRole,ParameterValue=${{ secrets.AWS_LAMBDA_ROLE }}" \
+ --no-confirm-changeset \
+ --no-progressbar \
+ --resolve-s3 \
+ --capabilities CAPABILITY_IAM \
+ 2>&1 | tee /tmp/sam-deploy.log | tail -n 20
+ LOG4J2_TEST_FUNCTION=$(sam list stack-outputs --stack-name "${stackName}" --output json | jq -r '.[] | select(.OutputKey=="Log4j2TestFunction") | .OutputValue')
+ echo "LOG4J2_TEST_FUNCTION=$LOG4J2_TEST_FUNCTION" >> "$GITHUB_OUTPUT"
+ echo "Function name: $LOG4J2_TEST_FUNCTION"
+
+ - name: Run integration test
+ env:
+ LOG4J2_TEST_FUNCTION: ${{ steps.deploy_stack.outputs.LOG4J2_TEST_FUNCTION }}
+ AWS_REGION: ${{ secrets.AWS_REGION }}
+ run: ./lambda-integration-tests/run-tests.sh
+
+ - name: Cleanup
+ if: always() && steps.deploy_stack.outputs.STACK_NAME
+ env:
+ AWS_REGION: ${{ secrets.AWS_REGION }}
+ STACK_NAME: ${{ steps.deploy_stack.outputs.STACK_NAME }}
+ run: |
+ sam delete --stack-name "${STACK_NAME}" --no-prompts --region "${AWS_REGION}"
diff --git a/lambda-integration-tests/log4j2-test-function/pom.xml b/lambda-integration-tests/log4j2-test-function/pom.xml
new file mode 100644
index 000000000..b036d1dea
--- /dev/null
+++ b/lambda-integration-tests/log4j2-test-function/pom.xml
@@ -0,0 +1,77 @@
+
+ 4.0.0
+
+ com.amazonaws
+ log4j2-integration-test-function
+ 1.0.0
+ jar
+
+ Log4j2 Integration Test Function
+
+ Lambda function used to verify that aws-lambda-java-log4j2 correctly emits logs to CloudWatch.
+
+
+
+ 21
+ 21
+ UTF-8
+ 2.25.4
+
+
+
+
+ com.amazonaws
+ aws-lambda-java-core
+ 1.4.0
+
+
+ com.amazonaws
+ aws-lambda-java-log4j2
+ 1.6.4
+
+
+ org.apache.logging.log4j
+ log4j-core
+ ${log4j.version}
+
+
+ org.apache.logging.log4j
+ log4j-api
+ ${log4j.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.6.1
+
+
+ package
+
+ shade
+
+
+
+
+
+
+
+
+
+
+
+ com.github.edwgiz
+ maven-shade-plugin.log4j2-cachefile-transformer
+ 2.8.1
+
+
+
+
+
+
diff --git a/lambda-integration-tests/log4j2-test-function/src/main/java/integ/Log4j2TestHandler.java b/lambda-integration-tests/log4j2-test-function/src/main/java/integ/Log4j2TestHandler.java
new file mode 100644
index 000000000..d81a3fa27
--- /dev/null
+++ b/lambda-integration-tests/log4j2-test-function/src/main/java/integ/Log4j2TestHandler.java
@@ -0,0 +1,30 @@
+package integ;
+
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.RequestHandler;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.util.Map;
+
+/**
+ * integration test handler that logs a marker string using Log4j2 with the LambdaAppender.
+ * the test verifies that the marker appears in CloudWatch Logs, confirming end-to-end
+ * log delivery through the aws-lambda-java-log4j2 library.
+ */
+public class Log4j2TestHandler implements RequestHandler, String> {
+
+ private static final Logger logger = LogManager.getLogger(Log4j2TestHandler.class);
+
+ @Override
+ public String handleRequest(Map event, Context context) {
+ String marker = event.getOrDefault("marker", "NO_MARKER_PROVIDED");
+
+ logger.info("INTEG_TEST_MARKER: {}", marker);
+ logger.debug("Debug level message with marker: {}", marker);
+ logger.warn("Warning level message with marker: {}", marker);
+ logger.error("Error level message with marker: {}", marker);
+
+ return "OK:" + marker;
+ }
+}
diff --git a/lambda-integration-tests/log4j2-test-function/src/main/resources/log4j2.xml b/lambda-integration-tests/log4j2-test-function/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..1cbc36bd0
--- /dev/null
+++ b/lambda-integration-tests/log4j2-test-function/src/main/resources/log4j2.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss} %X{AWSRequestId} %-5p %c{1}:%L - %m%n
+
+
+
+
+
+
+
+
+
+
diff --git a/lambda-integration-tests/run-tests.sh b/lambda-integration-tests/run-tests.sh
new file mode 100755
index 000000000..844cc5655
--- /dev/null
+++ b/lambda-integration-tests/run-tests.sh
@@ -0,0 +1,103 @@
+# integration test script for aws-lambda-java-log4j2.
+# invokes the deployed lambda function and verifies logs appear in CloudWatch.
+
+set -euo pipefail
+
+FUNCTION_NAME="${LOG4J2_TEST_FUNCTION:?LOG4J2_TEST_FUNCTION env var is required}"
+REGION="${AWS_REGION:?AWS_REGION env var is required}"
+MARKER="integ-test-$(date +%s)-${RANDOM}"
+
+echo "=== Log4j2 Integration Test ==="
+echo "Function: ${FUNCTION_NAME}"
+echo "Region: ${REGION}"
+echo "Marker: ${MARKER}"
+echo ""
+
+# invoke the lambda function
+echo ">>> Invoking Lambda function..."
+INVOKE_OUTPUT=$(aws lambda invoke \
+ --function-name "${FUNCTION_NAME}" \
+ --region "${REGION}" \
+ --payload "{\"marker\": \"${MARKER}\"}" \
+ --cli-binary-format raw-in-base64-out \
+ --output json \
+ /tmp/integ-test-response.json) || {
+ echo "FAIL: aws lambda invoke command failed with exit code $?"
+ echo "Output: ${INVOKE_OUTPUT:-}"
+ exit 1
+}
+
+echo "Invoke output: ${INVOKE_OUTPUT}"
+RESPONSE=$(cat /tmp/integ-test-response.json)
+echo "Response payload: ${RESPONSE}"
+
+# check for lambda execution errors
+FUNCTION_ERROR=$(echo "${INVOKE_OUTPUT}" | jq -r '.FunctionError // empty')
+if [ -n "${FUNCTION_ERROR}" ]; then
+ echo "FAIL: Lambda function returned an execution error (FunctionError: ${FUNCTION_ERROR})"
+ echo "Error response: ${RESPONSE}"
+ exit 1
+fi
+
+# verify the function executed successfully
+if echo "${RESPONSE}" | grep -q "OK:${MARKER}"; then
+ echo ">>> Function invocation successful."
+else
+ echo "FAIL: Unexpected response from Lambda function."
+ echo "Expected response containing: OK:${MARKER}"
+ echo "Got: ${RESPONSE}"
+ exit 1
+fi
+
+# query CloudWatch logs for the marker
+LOG_GROUP="/aws/lambda/${FUNCTION_NAME}"
+echo ""
+echo ">>> Querying CloudWatch Logs group: ${LOG_GROUP}"
+
+MAX_ATTEMPTS=5
+WAIT_SECONDS=10
+FOUND=false
+
+for attempt in $(seq 1 $MAX_ATTEMPTS); do
+ echo ">>> Attempt ${attempt}/${MAX_ATTEMPTS}: waiting ${WAIT_SECONDS}s for log propagation..."
+ sleep "${WAIT_SECONDS}"
+
+ LOGS_OUTPUT=$(aws logs filter-log-events \
+ --log-group-name "${LOG_GROUP}" \
+ --region "${REGION}" \
+ --filter-pattern "\"INTEG_TEST_MARKER\" \"${MARKER}\"" \
+ --start-time $(($(date +%s) * 1000 - 120000)) \
+ --output json 2>&1)
+
+ if echo "${LOGS_OUTPUT}" | grep -q "INTEG_TEST_MARKER: ${MARKER}"; then
+ FOUND=true
+ break
+ fi
+
+ echo " Marker not found yet."
+ WAIT_SECONDS=$((WAIT_SECONDS * 2))
+done
+
+# verify the marker was found
+if [ "${FOUND}" = true ]; then
+ echo ""
+ echo "=== PASS: Log4j2 integration test succeeded ==="
+ echo "The marker '${MARKER}' was found in CloudWatch Logs (attempt ${attempt})."
+ echo "This confirms that the LambdaAppender plugin was discovered by Log4j2"
+ echo "and logs are being delivered to CloudWatch correctly."
+else
+ echo ""
+ echo "=== FAIL: Log4j2 integration test failed ==="
+ echo "The marker '${MARKER}' was NOT found in CloudWatch Logs after ${MAX_ATTEMPTS} attempts."
+ echo "This indicates that the LambdaAppender was not discovered by Log4j2,"
+ echo "likely due to a missing Log4j2Plugins.dat in the packaged JAR."
+ echo ""
+ echo "Dumping all recent log events for debugging:"
+ aws logs filter-log-events \
+ --log-group-name "${LOG_GROUP}" \
+ --region "${REGION}" \
+ --start-time $(($(date +%s) * 1000 - 120000)) \
+ --limit 50 \
+ --output text 2>&1 || true
+ exit 1
+fi
diff --git a/lambda-integration-tests/samconfig.toml b/lambda-integration-tests/samconfig.toml
new file mode 100644
index 000000000..5e6597861
--- /dev/null
+++ b/lambda-integration-tests/samconfig.toml
@@ -0,0 +1,24 @@
+version = 0.1
+
+[default]
+[default.build.parameters]
+cached = true
+parallel = true
+build_in_source = true
+
+[default.validate.parameters]
+lint = true
+
+[default.deploy.parameters]
+capabilities = "CAPABILITY_IAM"
+confirm_changeset = true
+resolve_s3 = true
+
+[default.sync.parameters]
+watch = true
+
+[default.local_start_api.parameters]
+warm_containers = "EAGER"
+
+[default.local_start_lambda.parameters]
+warm_containers = "EAGER"
diff --git a/lambda-integration-tests/template.yaml b/lambda-integration-tests/template.yaml
new file mode 100644
index 000000000..101e586e0
--- /dev/null
+++ b/lambda-integration-tests/template.yaml
@@ -0,0 +1,34 @@
+AWSTemplateFormatVersion: '2010-09-09'
+Transform: AWS::Serverless-2016-10-31
+Description: aws-lambda-java-log4j2 integration tests
+
+Parameters:
+ LambdaRole:
+ Type: String
+
+Globals:
+ Function:
+ Timeout: 30
+ MemorySize: 512
+
+Resources:
+ Log4j2TestFunction:
+ Type: AWS::Serverless::Function
+ Metadata:
+ BuildMethod: java21
+ Properties:
+ CodeUri: log4j2-test-function/
+ Handler: integ.Log4j2TestHandler::handleRequest
+ Runtime: java21
+ Role: !Ref LambdaRole
+ Environment:
+ Variables:
+ AWS_LAMBDA_LOG_FORMAT: TEXT
+
+Outputs:
+ Log4j2TestFunction:
+ Description: "Log4j2 integration test function name"
+ Value: !Ref Log4j2TestFunction
+ Log4j2TestFunctionArn:
+ Description: "Log4j2 integration test function ARN"
+ Value: !GetAtt Log4j2TestFunction.Arn
From 76ec4ed320237b95fdc6f391d9003dd63f505a63 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Tue, 30 Jun 2026 15:48:49 +0100
Subject: [PATCH 083/129] Pin GitHub Actions to commit SHAs
---
.github/workflows/build-integration-test.yml | 4 ++--
.github/workflows/run-integration-test.yml | 8 ++++----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/build-integration-test.yml b/.github/workflows/build-integration-test.yml
index 5f5e82d13..748e0e1eb 100644
--- a/.github/workflows/build-integration-test.yml
+++ b/.github/workflows/build-integration-test.yml
@@ -26,10 +26,10 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Set up JDK
- uses: actions/setup-java@v5
+ uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
with:
java-version: |
8
diff --git a/.github/workflows/run-integration-test.yml b/.github/workflows/run-integration-test.yml
index 667e76d96..bd77684e3 100644
--- a/.github/workflows/run-integration-test.yml
+++ b/.github/workflows/run-integration-test.yml
@@ -25,10 +25,10 @@ jobs:
group: integration-test
cancel-in-progress: false
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Set up JDK
- uses: actions/setup-java@v5
+ uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0
with:
java-version: |
8
@@ -37,12 +37,12 @@ jobs:
cache: maven
- name: Install SAM CLI
- uses: aws-actions/setup-sam@v2
+ uses: aws-actions/setup-sam@f84ec7d548307efafe33230528756de3c5841a17 # v2
with:
use-installer: true
- name: Configure AWS credentials
- uses: aws-actions/configure-aws-credentials@v6.0.0
+ uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
role-session-name: ${{ secrets.ROLE_SESSION_NAME }}
From 9610b52294854aa895872a61d5aeb34cdd65af5d Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Wed, 1 Jul 2026 10:59:28 +0100
Subject: [PATCH 084/129] fix: run integ test on both architectures
---
.github/test-matrix.json | 14 ++++++++++
.github/workflows/build-integration-test.yml | 20 +++++++++++++-
.github/workflows/run-integration-test.yml | 28 ++++++++++++++++----
lambda-integration-tests/template.yaml | 8 ++++++
4 files changed, 64 insertions(+), 6 deletions(-)
create mode 100644 .github/test-matrix.json
diff --git a/.github/test-matrix.json b/.github/test-matrix.json
new file mode 100644
index 000000000..ef6ea1b9e
--- /dev/null
+++ b/.github/test-matrix.json
@@ -0,0 +1,14 @@
+{
+ "arch": [
+ {
+ "runner": "ubuntu-latest",
+ "label": "x64",
+ "sam_arch": "x86_64"
+ },
+ {
+ "runner": "ubuntu-24.04-arm",
+ "label": "arm64",
+ "sam_arch": "arm64"
+ }
+ ]
+}
diff --git a/.github/workflows/build-integration-test.yml b/.github/workflows/build-integration-test.yml
index 748e0e1eb..e9e5a3adf 100644
--- a/.github/workflows/build-integration-test.yml
+++ b/.github/workflows/build-integration-test.yml
@@ -23,8 +23,26 @@ permissions:
contents: read
jobs:
- build:
+ load-matrix:
runs-on: ubuntu-latest
+ outputs:
+ matrix: ${{ steps.set.outputs.matrix }}
+ steps:
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+
+ - name: Load test matrix
+ id: set
+ run: |
+ MATRIX=$(jq -c '.' .github/test-matrix.json)
+ echo "matrix=${MATRIX}" >> "$GITHUB_OUTPUT"
+
+ build:
+ needs: load-matrix
+ runs-on: ${{ matrix.arch.runner }}
+ strategy:
+ fail-fast: false
+ matrix: ${{ fromJson(needs.load-matrix.outputs.matrix) }}
+ name: "build (${{ matrix.arch.label }})"
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
diff --git a/.github/workflows/run-integration-test.yml b/.github/workflows/run-integration-test.yml
index bd77684e3..a43bd2112 100644
--- a/.github/workflows/run-integration-test.yml
+++ b/.github/workflows/run-integration-test.yml
@@ -17,12 +17,30 @@ on:
- 'lambda-integration-tests/**'
jobs:
+ load-matrix:
+ runs-on: ubuntu-latest
+ outputs:
+ matrix: ${{ steps.set.outputs.matrix }}
+ steps:
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+
+ - name: Load test matrix
+ id: set
+ run: |
+ MATRIX=$(jq -c '.' .github/test-matrix.json)
+ echo "matrix=${MATRIX}" >> "$GITHUB_OUTPUT"
+
run-integration-tests:
- # Only run on the main repo, not forks
+ needs: load-matrix
+ # Only run on the main repo, not forks
if: ${{ github.repository_owner == 'aws' }}
- runs-on: ubuntu-latest
+ runs-on: ${{ matrix.arch.runner }}
+ strategy:
+ fail-fast: false
+ matrix: ${{ fromJson(needs.load-matrix.outputs.matrix) }}
+ name: "integration-test (${{ matrix.arch.label }})"
concurrency:
- group: integration-test
+ group: integration-test-${{ matrix.arch.label }}
cancel-in-progress: false
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
@@ -72,12 +90,12 @@ jobs:
AWS_REGION: ${{ secrets.AWS_REGION }}
run: |
cd lambda-integration-tests
- stackName="aws-lambda-java-log4j2-integ-test-$GITHUB_RUN_ID"
+ stackName="aws-lambda-java-log4j2-integ-test-${{ matrix.arch.label }}-$GITHUB_RUN_ID"
echo "STACK_NAME=$stackName" >> "$GITHUB_OUTPUT"
echo "Stack name = $stackName"
sam deploy \
--stack-name "${stackName}" \
- --parameter-overrides "ParameterKey=LambdaRole,ParameterValue=${{ secrets.AWS_LAMBDA_ROLE }}" \
+ --parameter-overrides "ParameterKey=LambdaRole,ParameterValue=${{ secrets.AWS_LAMBDA_ROLE }} ParameterKey=Architecture,ParameterValue=${{ matrix.arch.sam_arch }}" \
--no-confirm-changeset \
--no-progressbar \
--resolve-s3 \
diff --git a/lambda-integration-tests/template.yaml b/lambda-integration-tests/template.yaml
index 101e586e0..01a10a706 100644
--- a/lambda-integration-tests/template.yaml
+++ b/lambda-integration-tests/template.yaml
@@ -5,6 +5,12 @@ Description: aws-lambda-java-log4j2 integration tests
Parameters:
LambdaRole:
Type: String
+ Architecture:
+ Type: String
+ Default: x86_64
+ AllowedValues:
+ - x86_64
+ - arm64
Globals:
Function:
@@ -20,6 +26,8 @@ Resources:
CodeUri: log4j2-test-function/
Handler: integ.Log4j2TestHandler::handleRequest
Runtime: java21
+ Architectures:
+ - !Ref Architecture
Role: !Ref LambdaRole
Environment:
Variables:
From 0e35558c79d389ab4d31a6bb33270f8264e2faf8 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Wed, 1 Jul 2026 11:34:09 +0100
Subject: [PATCH 085/129] fix: changing to precreated bucket
---
.github/workflows/build-integration-test.yml | 14 +++++++++++++-
.github/workflows/run-integration-test.yml | 2 +-
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/build-integration-test.yml b/.github/workflows/build-integration-test.yml
index e9e5a3adf..8a77db7d4 100644
--- a/.github/workflows/build-integration-test.yml
+++ b/.github/workflows/build-integration-test.yml
@@ -36,7 +36,7 @@ jobs:
MATRIX=$(jq -c '.' .github/test-matrix.json)
echo "matrix=${MATRIX}" >> "$GITHUB_OUTPUT"
- build:
+ build-arch:
needs: load-matrix
runs-on: ${{ matrix.arch.runner }}
strategy:
@@ -72,3 +72,15 @@ jobs:
run: |
export JAVA_HOME=$JAVA_HOME_21_X64
mvn -B package --file lambda-integration-tests/log4j2-test-function/pom.xml
+
+ build:
+ needs: build-arch
+ if: always()
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check build results
+ run: |
+ if [ "${{ needs.build-arch.result }}" != "success" ]; then
+ echo "Build failed on one or more architectures"
+ exit 1
+ fi
diff --git a/.github/workflows/run-integration-test.yml b/.github/workflows/run-integration-test.yml
index a43bd2112..6115dd528 100644
--- a/.github/workflows/run-integration-test.yml
+++ b/.github/workflows/run-integration-test.yml
@@ -98,7 +98,7 @@ jobs:
--parameter-overrides "ParameterKey=LambdaRole,ParameterValue=${{ secrets.AWS_LAMBDA_ROLE }} ParameterKey=Architecture,ParameterValue=${{ matrix.arch.sam_arch }}" \
--no-confirm-changeset \
--no-progressbar \
- --resolve-s3 \
+ --s3-bucket "${{ secrets.S3_BUCKET }}" \
--capabilities CAPABILITY_IAM \
2>&1 | tee /tmp/sam-deploy.log | tail -n 20
LOG4J2_TEST_FUNCTION=$(sam list stack-outputs --stack-name "${stackName}" --output json | jq -r '.[] | select(.OutputKey=="Log4j2TestFunction") | .OutputValue')
From cb9c4f6d70a19a7e9f7e1d3e5d2e69cd3c7062c1 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Wed, 1 Jul 2026 15:19:18 +0100
Subject: [PATCH 086/129] fix: renaming secrets
---
.github/workflows/run-integration-test.yml | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/run-integration-test.yml b/.github/workflows/run-integration-test.yml
index 6115dd528..75a2f11c0 100644
--- a/.github/workflows/run-integration-test.yml
+++ b/.github/workflows/run-integration-test.yml
@@ -62,9 +62,9 @@ jobs:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0
with:
- role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
- role-session-name: ${{ secrets.ROLE_SESSION_NAME }}
- aws-region: ${{ secrets.AWS_REGION }}
+ role-to-assume: ${{ secrets.AWS_ROLE_LOG4J2_INTEG_TEST }}
+ role-session-name: GitHubActionsLog4j2IntegTest
+ aws-region: ${{ secrets.AWS_REGION_LOG4J2_INTEG_TEST }}
- name: Install core with Maven
run: |
@@ -87,7 +87,7 @@ jobs:
- name: Deploy stack
id: deploy_stack
env:
- AWS_REGION: ${{ secrets.AWS_REGION }}
+ AWS_REGION: ${{ secrets.AWS_REGION_LOG4J2_INTEG_TEST }}
run: |
cd lambda-integration-tests
stackName="aws-lambda-java-log4j2-integ-test-${{ matrix.arch.label }}-$GITHUB_RUN_ID"
@@ -95,10 +95,10 @@ jobs:
echo "Stack name = $stackName"
sam deploy \
--stack-name "${stackName}" \
- --parameter-overrides "ParameterKey=LambdaRole,ParameterValue=${{ secrets.AWS_LAMBDA_ROLE }} ParameterKey=Architecture,ParameterValue=${{ matrix.arch.sam_arch }}" \
+ --parameter-overrides "ParameterKey=LambdaRole,ParameterValue=${{ secrets.AWS_LAMBDA_ROLE_LOG4J2_INTEG_TEST }} ParameterKey=Architecture,ParameterValue=${{ matrix.arch.sam_arch }}" \
--no-confirm-changeset \
--no-progressbar \
- --s3-bucket "${{ secrets.S3_BUCKET }}" \
+ --s3-bucket "${{ secrets.S3_BUCKET_LOG4J2_INTEG_TEST }}" \
--capabilities CAPABILITY_IAM \
2>&1 | tee /tmp/sam-deploy.log | tail -n 20
LOG4J2_TEST_FUNCTION=$(sam list stack-outputs --stack-name "${stackName}" --output json | jq -r '.[] | select(.OutputKey=="Log4j2TestFunction") | .OutputValue')
@@ -108,13 +108,13 @@ jobs:
- name: Run integration test
env:
LOG4J2_TEST_FUNCTION: ${{ steps.deploy_stack.outputs.LOG4J2_TEST_FUNCTION }}
- AWS_REGION: ${{ secrets.AWS_REGION }}
+ AWS_REGION: ${{ secrets.AWS_REGION_LOG4J2_INTEG_TEST }}
run: ./lambda-integration-tests/run-tests.sh
- name: Cleanup
if: always() && steps.deploy_stack.outputs.STACK_NAME
env:
- AWS_REGION: ${{ secrets.AWS_REGION }}
+ AWS_REGION: ${{ secrets.AWS_REGION_LOG4J2_INTEG_TEST }}
STACK_NAME: ${{ steps.deploy_stack.outputs.STACK_NAME }}
run: |
sam delete --stack-name "${STACK_NAME}" --no-prompts --region "${AWS_REGION}"
From 361bbfcc17ddc1b122956f52dccb956e56004c7e Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Thu, 2 Jul 2026 14:48:24 +0100
Subject: [PATCH 087/129] fix: use architecture-aware JAVA_HOME on matrix
runners
---
.github/test-matrix.json | 6 ++++--
.github/workflows/build-integration-test.yml | 6 +++---
.github/workflows/run-integration-test.yml | 6 +++---
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/.github/test-matrix.json b/.github/test-matrix.json
index ef6ea1b9e..7e6539cb6 100644
--- a/.github/test-matrix.json
+++ b/.github/test-matrix.json
@@ -3,12 +3,14 @@
{
"runner": "ubuntu-latest",
"label": "x64",
- "sam_arch": "x86_64"
+ "sam_arch": "x86_64",
+ "java_suffix": "X64"
},
{
"runner": "ubuntu-24.04-arm",
"label": "arm64",
- "sam_arch": "arm64"
+ "sam_arch": "arm64",
+ "java_suffix": "ARM64"
}
]
}
diff --git a/.github/workflows/build-integration-test.yml b/.github/workflows/build-integration-test.yml
index 8a77db7d4..2a6bb30c5 100644
--- a/.github/workflows/build-integration-test.yml
+++ b/.github/workflows/build-integration-test.yml
@@ -57,12 +57,12 @@ jobs:
- name: Install core with Maven
run: |
- export JAVA_HOME=$JAVA_HOME_8_X64
+ export JAVA_HOME=$JAVA_HOME_8_${{ matrix.arch.java_suffix }}
mvn -B install --file aws-lambda-java-core/pom.xml
- name: Install log4j2 with Maven
run: |
- export JAVA_HOME=$JAVA_HOME_8_X64
+ export JAVA_HOME=$JAVA_HOME_8_${{ matrix.arch.java_suffix }}
mvn -B install --file aws-lambda-java-log4j2/pom.xml
# build the integration test function
@@ -70,7 +70,7 @@ jobs:
# the tests will run in run-integration-test.yml which deploys to AWS.
- name: Package integration test function
run: |
- export JAVA_HOME=$JAVA_HOME_21_X64
+ export JAVA_HOME=$JAVA_HOME_21_${{ matrix.arch.java_suffix }}
mvn -B package --file lambda-integration-tests/log4j2-test-function/pom.xml
build:
diff --git a/.github/workflows/run-integration-test.yml b/.github/workflows/run-integration-test.yml
index 75a2f11c0..1b857f45c 100644
--- a/.github/workflows/run-integration-test.yml
+++ b/.github/workflows/run-integration-test.yml
@@ -68,17 +68,17 @@ jobs:
- name: Install core with Maven
run: |
- export JAVA_HOME=$JAVA_HOME_8_X64
+ export JAVA_HOME=$JAVA_HOME_8_${{ matrix.arch.java_suffix }}
mvn -B install --file aws-lambda-java-core/pom.xml
- name: Install log4j2 with Maven
run: |
- export JAVA_HOME=$JAVA_HOME_8_X64
+ export JAVA_HOME=$JAVA_HOME_8_${{ matrix.arch.java_suffix }}
mvn -B install --file aws-lambda-java-log4j2/pom.xml
- name: Build SAM stack
run: |
- export JAVA_HOME=$JAVA_HOME_21_X64
+ export JAVA_HOME=$JAVA_HOME_21_${{ matrix.arch.java_suffix }}
cd lambda-integration-tests && sam build
- name: Validate SAM stack
From cffc264baa32c1735c86e91e89e65810024307ff Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Thu, 2 Jul 2026 17:02:17 +0100
Subject: [PATCH 088/129] fix: remove resolve_s3 from samconfig to avoid
conflict with --s3-bucket
---
lambda-integration-tests/samconfig.toml | 1 -
1 file changed, 1 deletion(-)
diff --git a/lambda-integration-tests/samconfig.toml b/lambda-integration-tests/samconfig.toml
index 5e6597861..f1f665e48 100644
--- a/lambda-integration-tests/samconfig.toml
+++ b/lambda-integration-tests/samconfig.toml
@@ -12,7 +12,6 @@ lint = true
[default.deploy.parameters]
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
-resolve_s3 = true
[default.sync.parameters]
watch = true
From fff1ffc83f3fcc0314f76c798d9963b337b2bff6 Mon Sep 17 00:00:00 2001
From: Davide Melfi
Date: Thu, 2 Jul 2026 18:59:13 +0100
Subject: [PATCH 089/129] chore: introducing functionName
---
lambda-integration-tests/template.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/lambda-integration-tests/template.yaml b/lambda-integration-tests/template.yaml
index 01a10a706..a12e5f656 100644
--- a/lambda-integration-tests/template.yaml
+++ b/lambda-integration-tests/template.yaml
@@ -23,6 +23,7 @@ Resources:
Metadata:
BuildMethod: java21
Properties:
+ FunctionName: !Sub "${AWS::StackName}-fn"
CodeUri: log4j2-test-function/
Handler: integ.Log4j2TestHandler::handleRequest
Runtime: java21
From 3af9bdf819844738ccf632f695dd06f98d3c5eb1 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Fri, 3 Jul 2026 10:56:42 +0100
Subject: [PATCH 090/129] fix: verify stack status after deploy before running
tests
---
.github/workflows/run-integration-test.yml | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/.github/workflows/run-integration-test.yml b/.github/workflows/run-integration-test.yml
index 1b857f45c..ad46d7fd6 100644
--- a/.github/workflows/run-integration-test.yml
+++ b/.github/workflows/run-integration-test.yml
@@ -101,6 +101,24 @@ jobs:
--s3-bucket "${{ secrets.S3_BUCKET_LOG4J2_INTEG_TEST }}" \
--capabilities CAPABILITY_IAM \
2>&1 | tee /tmp/sam-deploy.log | tail -n 20
+
+ # Verify stack is in a healthy state
+ STACK_STATUS=$(aws cloudformation describe-stacks \
+ --stack-name "${stackName}" \
+ --region "${AWS_REGION}" \
+ --query 'Stacks[0].StackStatus' \
+ --output text 2>&1)
+ echo "Stack status: $STACK_STATUS"
+ if [ "$STACK_STATUS" != "CREATE_COMPLETE" ] && [ "$STACK_STATUS" != "UPDATE_COMPLETE" ]; then
+ echo "FAIL: Stack is not in a healthy state (status: $STACK_STATUS)"
+ aws cloudformation describe-stack-events \
+ --stack-name "${stackName}" \
+ --region "${AWS_REGION}" \
+ --query 'StackEvents[?ResourceStatus==`CREATE_FAILED` || ResourceStatus==`UPDATE_FAILED`].[LogicalResourceId,ResourceStatusReason]' \
+ --output table 2>&1 || true
+ exit 1
+ fi
+
LOG4J2_TEST_FUNCTION=$(sam list stack-outputs --stack-name "${stackName}" --output json | jq -r '.[] | select(.OutputKey=="Log4j2TestFunction") | .OutputValue')
echo "LOG4J2_TEST_FUNCTION=$LOG4J2_TEST_FUNCTION" >> "$GITHUB_OUTPUT"
echo "Function name: $LOG4J2_TEST_FUNCTION"
From 52bd30d7415eba7b6012c19e4c17cf4f2dfb53dc Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Tue, 14 Jul 2026 17:09:13 +0100
Subject: [PATCH 091/129] build: Add maven-release-plugin and SCM config to all
modules
Add maven-release-plugin configuration with module-specific tag formats
and SCM connection details to enable automated Maven deployments across
all library modules.
---
aws-lambda-java-core/pom.xml | 20 +++++++++++++++++++
.../pom.xml | 15 ++++++++++++++
aws-lambda-java-events/pom.xml | 20 +++++++++++++++++++
aws-lambda-java-log4j2/pom.xml | 15 ++++++++++++++
.../pom.xml | 15 ++++++++++++++
aws-lambda-java-serialization/pom.xml | 15 ++++++++++++++
aws-lambda-java-tests/pom.xml | 15 ++++++++++++++
7 files changed, 115 insertions(+)
diff --git a/aws-lambda-java-core/pom.xml b/aws-lambda-java-core/pom.xml
index cca9d0cdf..b0277d3e0 100644
--- a/aws-lambda-java-core/pom.xml
+++ b/aws-lambda-java-core/pom.xml
@@ -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
@@ -36,6 +39,22 @@
1.8
+
+
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 3.1.1
+
+ aws-lambda-java-core-@{project.version}
+ true
+ release
+ deploy
+
+
+
+
+
dev
@@ -114,6 +133,7 @@
truecentral
+ true
diff --git a/aws-lambda-java-events-sdk-transformer/pom.xml b/aws-lambda-java-events-sdk-transformer/pom.xml
index 6de599ef7..d05cd63d5 100644
--- a/aws-lambda-java-events-sdk-transformer/pom.xml
+++ b/aws-lambda-java-events-sdk-transformer/pom.xml
@@ -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
+
+ maven-surefire-plugin${maven-surefire-plugin.version}
@@ -171,6 +185,7 @@
truecentral
+ true
diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml
index c8c40e0c7..9c19cdc05 100644
--- a/aws-lambda-java-events/pom.xml
+++ b/aws-lambda-java-events/pom.xml
@@ -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
@@ -83,6 +86,22 @@
+
+
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 3.1.1
+
+ aws-lambda-java-events-@{project.version}
+ true
+ release
+ deploy
+
+
+
+
+
dev
@@ -161,6 +180,7 @@
truecentral
+ true
diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml
index a03d3d3b6..fd0ce8114 100644
--- a/aws-lambda-java-log4j2/pom.xml
+++ b/aws-lambda-java-log4j2/pom.xml
@@ -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.pluginsmaven-toolchains-plugin
@@ -183,6 +197,7 @@
truecentral
+ true
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index 2ba71c43c..fa580e7d1 100644
--- a/aws-lambda-java-runtime-interface-client/pom.xml
+++ b/aws-lambda-java-runtime-interface-client/pom.xml
@@ -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
+
+ maven-install-pluginorg.apache.maven.plugins
@@ -381,6 +395,7 @@
truecentral
+ true
diff --git a/aws-lambda-java-serialization/pom.xml b/aws-lambda-java-serialization/pom.xml
index 60a3c67a9..74b9f669c 100644
--- a/aws-lambda-java-serialization/pom.xml
+++ b/aws-lambda-java-serialization/pom.xml
@@ -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 @@
truecentral
+ 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.pluginsmaven-shade-plugin
diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml
index 5e5f19b33..c0eef7929 100644
--- a/aws-lambda-java-tests/pom.xml
+++ b/aws-lambda-java-tests/pom.xml
@@ -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 @@
truecentral
+ 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.pluginsmaven-compiler-plugin
From 4acf4aa4f34bb78e04492bb890e419be1209252d Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Tue, 14 Jul 2026 17:13:25 +0100
Subject: [PATCH 092/129] fix: Add toolchains.xml to codebuild agent for JDK 8
resolution
The maven-toolchains-plugin requires JDK 8 to be declared in
~/.m2/toolchains.xml. The smoke test Docker agent has Corretto 8
installed but was missing this file, causing the build to fail.
---
.../test/integration/codebuild-local/Dockerfile.agent | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/Dockerfile.agent b/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/Dockerfile.agent
index 3dbdb3c68..3ebbbb3a2 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/Dockerfile.agent
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/Dockerfile.agent
@@ -11,4 +11,8 @@ COPY --from=docker/buildx-bin:latest /buildx /usr/libexec/docker/cli-plugins/doc
ENV PATH="$PATH:/apache-maven/bin"
RUN mkdir /apache-maven && \
curl https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.tar.gz | \
- tar -xz -C /apache-maven --strip-components 1
\ No newline at end of file
+ tar -xz -C /apache-maven --strip-components 1
+
+# Declare JDK 8 in toolchains.xml so maven-toolchains-plugin can resolve it
+RUN mkdir -p /root/.m2 && \
+ printf '\n\n \n jdk\n \n 8\n \n \n /usr/lib/jvm/java-1.8.0-amazon-corretto\n \n \n\n' > /root/.m2/toolchains.xml
From 8a3267a39c8bdf72789eaf1838032532fd90d3c4 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Wed, 15 Jul 2026 11:57:02 +0100
Subject: [PATCH 093/129] fix: Use heredoc and $JAVA_HOME for toolchains.xml
---
.../integration/codebuild-local/Dockerfile.agent | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/Dockerfile.agent b/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/Dockerfile.agent
index 3ebbbb3a2..350305e81 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/Dockerfile.agent
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/Dockerfile.agent
@@ -15,4 +15,17 @@ RUN mkdir /apache-maven && \
# Declare JDK 8 in toolchains.xml so maven-toolchains-plugin can resolve it
RUN mkdir -p /root/.m2 && \
- printf '\n\n \n jdk\n \n 8\n \n \n /usr/lib/jvm/java-1.8.0-amazon-corretto\n \n \n\n' > /root/.m2/toolchains.xml
+ cat > /root/.m2/toolchains.xml <
+
+
+ jdk
+
+ 8
+
+
+ ${JAVA_HOME}
+
+
+
+EOF
From 3bdc9511c1cb6b56ad0d23d85a9f71c8d1d762b5 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Wed, 15 Jul 2026 13:22:22 +0100
Subject: [PATCH 094/129] docs: Add toolchains.xml example and setup guide
---
CONTRIBUTING.md | 19 +++++++++++++++++++
toolchains.xml.example | 21 +++++++++++++++++++++
2 files changed, 40 insertions(+)
create mode 100644 toolchains.xml.example
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a1241783c..7e8164689 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -36,6 +36,25 @@ To send us a pull request, please:
5. Send us a pull request, answering any default questions in the pull request interface.
6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
+
+## Build Prerequisites
+
+This project uses the Maven Toolchains Plugin to pin compilation to JDK 8. If you don't have a `~/.m2/toolchains.xml` configured, builds will fail with:
+
+```
+No toolchain found for type jdk [ version='[1.8,9)' ]
+```
+
+To fix this, copy the example file to your Maven config directory and update the path:
+
+```bash
+cp toolchains.xml.example ~/.m2/toolchains.xml
+```
+
+Then edit `~/.m2/toolchains.xml` and set `` to your local JDK 8 installation path.
+
+Note: if you use `actions/setup-java` in CI (as our GitHub Actions workflows do), this file is generated automatically.
+
GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
diff --git a/toolchains.xml.example b/toolchains.xml.example
new file mode 100644
index 000000000..b57490761
--- /dev/null
+++ b/toolchains.xml.example
@@ -0,0 +1,21 @@
+
+
+
+
+ jdk
+
+ 8
+
+
+ /path/to/your/jdk8
+
+
+
From 544ee077db405850e8c28bc7d926118268a8f58f Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Wed, 15 Jul 2026 17:59:03 +0100
Subject: [PATCH 095/129] ci: Add automated Maven Central release workflow
Add .github/workflows/release.yml, a workflow_dispatch pipeline that
builds, tests, and publishes a single module to Maven Central in one
pinned JDK 8 environment, replacing the manual mvn deploy from a
developer workstation.
The release step prepares locally, publishes, then pushes the commits
and module-scoped tag atomically, so a failed publish never leaves an
orphan tag on the remote; a failure path rolls back the runner state.
Releases are serialized repo-wide via a shared concurrency group.
Signing/publishing secrets are not wired yet, so only the dry-run
path (skip_publish) works without credentials for now.
Set all module versions to -SNAPSHOT as the release plugin's expected
starting point, and merge a duplicate top-level section in the
events POM introduced when the toolchains change (PR #617) met the
release-plugin config on this branch.
---
.github/workflows/release.yml | 187 ++++++++++++++++++
aws-lambda-java-core/pom.xml | 2 +-
.../pom.xml | 2 +-
aws-lambda-java-events/pom.xml | 29 ++-
aws-lambda-java-log4j2/pom.xml | 2 +-
.../pom.xml | 2 +-
aws-lambda-java-serialization/pom.xml | 2 +-
aws-lambda-java-tests/pom.xml | 2 +-
8 files changed, 205 insertions(+), 23 deletions(-)
create mode 100644 .github/workflows/release.yml
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 000000000..6d899990b
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,187 @@
+name: Release to Maven Central
+
+# Automated release pipeline: builds, tests, and publishes a module to Maven
+# Central in one controlled environment. Signing/publishing secrets are still
+# to be handled; until then use skip_publish (dry-run), which needs none.
+
+on:
+ workflow_dispatch:
+ inputs:
+ module:
+ description: 'Module to release (directory name, e.g. aws-lambda-java-log4j2)'
+ required: true
+ type: choice
+ options:
+ - aws-lambda-java-core
+ - aws-lambda-java-events
+ - aws-lambda-java-events-sdk-transformer
+ - aws-lambda-java-log4j2
+ - aws-lambda-java-runtime-interface-client
+ - 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 # push release commits and tag
+ id-token: write # reserved for future secrets handling
+
+# 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"
+
+jobs:
+ release:
+ runs-on: ubuntu-latest
+ environment: Release
+ timeout-minutes: 30
+
+ steps:
+ - 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: Validate inputs and resolve versions
+ run: |
+ 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
+
+ # 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
+
+ # releaseVersion input is an optional override; default strips -SNAPSHOT.
+ EFFECTIVE_RELEASE_VERSION="${RELEASE_VERSION_INPUT:-${CURRENT_VERSION%-SNAPSHOT}}"
+
+ if [[ -n "$DEVELOPMENT_VERSION_INPUT" && "$DEVELOPMENT_VERSION_INPUT" != *-SNAPSHOT ]]; then
+ echo "::error::developmentVersion '$DEVELOPMENT_VERSION_INPUT' must end with -SNAPSHOT"
+ exit 1
+ fi
+
+ # Build the release plugin version args once; reused by both paths.
+ RELEASE_ARGS="-DreleaseVersion=$EFFECTIVE_RELEASE_VERSION"
+ if [[ -n "$DEVELOPMENT_VERSION_INPUT" ]]; then
+ RELEASE_ARGS="$RELEASE_ARGS -DdevelopmentVersion=$DEVELOPMENT_VERSION_INPUT"
+ fi
+
+ echo "EFFECTIVE_RELEASE_VERSION=$EFFECTIVE_RELEASE_VERSION" >> "$GITHUB_ENV"
+ echo "RELEASE_ARGS=$RELEASE_ARGS" >> "$GITHUB_ENV"
+ 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"
+
+ # TODO(secrets): signing/publishing credentials are still to be handled.
+ # Until then, only skip_publish=true (dry-run) works, as it needs none.
+
+ - name: Install intra-repo dependencies
+ run: |
+ # Modules that must be installed locally before the target builds.
+ 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-runtime-interface-client]="aws-lambda-java-core aws-lambda-java-serialization"
+ 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
+
+ # No skip-tests option: never release an unverified artifact.
+ - name: Run tests
+ run: mvn verify --file "$MODULE/pom.xml"
+
+ # prepare/perform aren't atomic. Prepare locally (no push), publish, then
+ # push only after the artifact is live, so a failed publish never leaves an
+ # orphan tag on the remote. On failure, the rollback step cleans the runner.
+ - name: Release (prepare locally, publish, then push)
+ if: ${{ github.event.inputs.skip_publish != 'true' }}
+ run: |
+ # 1. Prepare locally (no push): create the release commits + tag.
+ mvn release:prepare -DpushChanges=false $RELEASE_ARGS --file "$MODULE/pom.xml"
+
+ # 2. Publish to Maven Central from the local tag.
+ mvn release:perform -DlocalCheckout=true --file "$MODULE/pom.xml"
+
+ # 3. Push commits and tag atomically (both or neither).
+ 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: |
+ 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 321098784..e9464e3d1 100644
--- a/aws-lambda-java-core/pom.xml
+++ b/aws-lambda-java-core/pom.xml
@@ -5,7 +5,7 @@
com.amazonawsaws-lambda-java-core
- 1.4.0
+ 1.4.0-SNAPSHOTjarAWS 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 9b83b2e13..1072f4cc6 100644
--- a/aws-lambda-java-events-sdk-transformer/pom.xml
+++ b/aws-lambda-java-events-sdk-transformer/pom.xml
@@ -5,7 +5,7 @@
com.amazonawsaws-lambda-java-events-sdk-transformer
- 3.1.1
+ 3.1.1-SNAPSHOTjarAWS Lambda Java Events SDK Transformer Library
diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml
index e5dc3329c..7ab9aa938 100644
--- a/aws-lambda-java-events/pom.xml
+++ b/aws-lambda-java-events/pom.xml
@@ -5,7 +5,7 @@
com.amazonawsaws-lambda-java-events
- 3.16.1
+ 3.16.1-SNAPSHOTjarAWS Lambda Java Events Library
@@ -68,6 +68,17 @@
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 3.1.1
+
+ aws-lambda-java-events-@{project.version}
+ true
+ release
+ deploy
+
+
@@ -112,22 +123,6 @@
-
-
-
- org.apache.maven.plugins
- maven-release-plugin
- 3.1.1
-
- aws-lambda-java-events-@{project.version}
- true
- release
- deploy
-
-
-
-
-
dev
diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml
index fd0ce8114..432c4f5c4 100644
--- a/aws-lambda-java-log4j2/pom.xml
+++ b/aws-lambda-java-log4j2/pom.xml
@@ -5,7 +5,7 @@
com.amazonawsaws-lambda-java-log4j2
- 1.6.4
+ 1.6.4-SNAPSHOTjarAWS Lambda Java Log4j 2.x Libraries
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index 66e2f2fe2..0cf33d828 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.0com.amazonawsaws-lambda-java-runtime-interface-client
- 2.11.0
+ 2.11.0-SNAPSHOTjarAWS Lambda Java Runtime Interface Client
diff --git a/aws-lambda-java-serialization/pom.xml b/aws-lambda-java-serialization/pom.xml
index 713fdfcb8..613b204c6 100644
--- a/aws-lambda-java-serialization/pom.xml
+++ b/aws-lambda-java-serialization/pom.xml
@@ -4,7 +4,7 @@
com.amazonawsaws-lambda-java-serialization
- 1.4.1
+ 1.4.1-SNAPSHOTjarAWS Lambda Java Runtime Serialization
diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml
index 3272b3f44..b1daf4105 100644
--- a/aws-lambda-java-tests/pom.xml
+++ b/aws-lambda-java-tests/pom.xml
@@ -5,7 +5,7 @@
com.amazonawsaws-lambda-java-tests
- 1.1.3
+ 1.1.3-SNAPSHOTjarAWS Lambda Java Tests
From c9e1061841d88ab37b60a5879c97841b7f674b86 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Tue, 21 Jul 2026 16:53:06 +0100
Subject: [PATCH 096/129] ci: Wire OIDC secrets and add native RIC release
workflow
---
.../release-runtime-interface-client.yml | 288 ++++++++++++++++++
.github/workflows/release.yml | 86 ++++--
2 files changed, 355 insertions(+), 19 deletions(-)
create mode 100644 .github/workflows/release-runtime-interface-client.yml
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
new file mode 100644
index 000000000..43090d1b7
--- /dev/null
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -0,0 +1,288 @@
+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:
+ - 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 release version
+ run: |
+ 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
+ echo "EFFECTIVE_RELEASE_VERSION=${RELEASE_VERSION_INPUT:-${CURRENT_VERSION%-SNAPSHOT}}" >> "$GITHUB_ENV"
+
+ # -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: Validate inputs and resolve versions
+ run: |
+ 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
+
+ EFFECTIVE_RELEASE_VERSION="${RELEASE_VERSION_INPUT:-${CURRENT_VERSION%-SNAPSHOT}}"
+
+ # 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 "EFFECTIVE_RELEASE_VERSION=$EFFECTIVE_RELEASE_VERSION" >> "$GITHUB_ENV"
+ 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: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4
+ with:
+ aws-region: ${{ env.AWS_REGION }}
+ role-to-assume: ${{ env.OIDC_ROLE_ARN }}
+ role-session-name: GitHubActionsRicMavenCentralRelease
+ role-duration-seconds: 3600
+
+ - name: Fetch signing key and Sonatype credentials
+ if: ${{ github.event.inputs.skip_publish != 'true' }}
+ run: |
+ # Shared secrets from LambdaMavenDeploy; nothing stored in GitHub.
+ 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.
+ GNUPGHOME=$(mktemp -d)
+ chmod 700 "$GNUPGHOME"
+ echo "allow-loopback-pinentry" > "$GNUPGHOME/gpg-agent.conf"
+ echo "pinentry-mode loopback" > "$GNUPGHOME/gpg.conf"
+ export GNUPGHOME
+ 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").
+ SETTINGS="$RUNNER_TEMP/settings.xml"
+ {
+ echo ''
+ echo "central"
+ echo "${SONATYPE_USERNAME}"
+ echo "${SONATYPE_PASSWORD}"
+ echo ''
+ } > "$SETTINGS"
+
+ echo "GNUPGHOME=$GNUPGHOME" >> "$GITHUB_ENV"
+ echo "GPG_KEYNAME=$GPG_KEYNAME" >> "$GITHUB_ENV"
+ echo "GPG_PASSPHRASE=$GPG_PASSPHRASE" >> "$GITHUB_ENV"
+ echo "MAVEN_SETTINGS=$SETTINGS" >> "$GITHUB_ENV"
+
+ # -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: |
+ 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
index 6d899990b..e148c0131 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,8 +1,6 @@
name: Release to Maven Central
-# Automated release pipeline: builds, tests, and publishes a module to Maven
-# Central in one controlled environment. Signing/publishing secrets are still
-# to be handled; until then use skip_publish (dry-run), which needs none.
+# Builds, tests, and publishes a module to Maven Central in one environment.
on:
workflow_dispatch:
@@ -11,12 +9,14 @@ on:
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-runtime-interface-client
- aws-lambda-java-serialization
- aws-lambda-java-tests
releaseVersion:
@@ -34,8 +34,8 @@ on:
default: false
permissions:
- contents: write # push release commits and tag
- id-token: write # reserved for future secrets handling
+ 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.
@@ -49,6 +49,8 @@ env:
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:
release:
@@ -111,19 +113,16 @@ jobs:
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- # TODO(secrets): signing/publishing credentials are still to be handled.
- # Until then, only skip_publish=true (dry-run) works, as it needs none.
-
- name: Install intra-repo dependencies
run: |
- # Modules that must be installed locally before the target builds.
+ # 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-runtime-interface-client]="aws-lambda-java-core aws-lambda-java-serialization"
DEPS[aws-lambda-java-tests]="aws-lambda-java-core aws-lambda-java-serialization aws-lambda-java-events"
DEP_LIST="${DEPS[$MODULE]}"
@@ -137,23 +136,72 @@ jobs:
echo "::notice::No intra-repo dependencies for $MODULE"
fi
- # No skip-tests option: never release an unverified artifact.
- name: Run tests
run: mvn verify --file "$MODULE/pom.xml"
- # prepare/perform aren't atomic. Prepare locally (no push), publish, then
- # push only after the artifact is live, so a failed publish never leaves an
- # orphan tag on the remote. On failure, the rollback step cleans the runner.
+ - name: Configure AWS credentials (OIDC)
+ if: ${{ github.event.inputs.skip_publish != 'true' }}
+ uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4
+ with:
+ aws-region: ${{ env.AWS_REGION }}
+ role-to-assume: ${{ env.OIDC_ROLE_ARN }}
+ role-session-name: GitHubActionsMavenCentralRelease
+ role-duration-seconds: 3600
+
+ - name: Fetch signing key and Sonatype credentials
+ if: ${{ github.event.inputs.skip_publish != 'true' }}
+ run: |
+ # Shared secrets from LambdaMavenDeploy; nothing stored in GitHub.
+ 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.
+ GNUPGHOME=$(mktemp -d)
+ chmod 700 "$GNUPGHOME"
+ echo "allow-loopback-pinentry" > "$GNUPGHOME/gpg-agent.conf"
+ echo "pinentry-mode loopback" > "$GNUPGHOME/gpg.conf"
+ export GNUPGHOME
+ 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").
+ SETTINGS="$RUNNER_TEMP/settings.xml"
+ {
+ echo ''
+ echo "central"
+ echo "${SONATYPE_USERNAME}"
+ echo "${SONATYPE_PASSWORD}"
+ echo ''
+ } > "$SETTINGS"
+
+ # Pass to later steps (values already masked).
+ echo "GNUPGHOME=$GNUPGHOME" >> "$GITHUB_ENV"
+ echo "GPG_KEYNAME=$GPG_KEYNAME" >> "$GITHUB_ENV"
+ echo "GPG_PASSPHRASE=$GPG_PASSPHRASE" >> "$GITHUB_ENV"
+ echo "MAVEN_SETTINGS=$SETTINGS" >> "$GITHUB_ENV"
+
+ # 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: |
- # 1. Prepare locally (no push): create the release commits + tag.
+ # Prepare locally (no push): release commits + tag.
mvn release:prepare -DpushChanges=false $RELEASE_ARGS --file "$MODULE/pom.xml"
- # 2. Publish to Maven Central from the local tag.
- mvn release:perform -DlocalCheckout=true --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"
- # 3. Push commits and tag atomically (both or neither).
+ # Push commits + tag atomically, only after publish succeeded.
git push --atomic origin \
"HEAD:${GITHUB_REF_NAME}" \
"refs/tags/${MODULE}-${EFFECTIVE_RELEASE_VERSION}"
From 371508e543ebf1757d7796c1debed0b1a0fb1c54 Mon Sep 17 00:00:00 2001
From: Vipin Gupta
Date: Tue, 21 Jul 2026 12:39:39 +0000
Subject: [PATCH 097/129] feat(runtime-interface-client): Add
Lambda-Runtime-Invocation-Id support for cross-wiring protection
Echo the invocation ID received from RAPID on /next back on /response
and /error, enabling RAPID to detect and reject stale responses from
timed-out invocations. Fully backward compatible.
---
.../RELEASE.CHANGELOG.md | 4 +
.../pom.xml | 2 +-
.../lambda/runtime/api/client/AWSLambda.java | 4 +-
.../runtimeapi/LambdaRuntimeApiClient.java | 6 +-
.../LambdaRuntimeApiClientImpl.java | 20 +++--
.../api/client/runtimeapi/NativeClient.java | 2 +-
.../runtimeapi/dto/InvocationRequest.java | 13 ++++
...ime_api_client_runtimeapi_NativeClient.cpp | 18 ++++-
...ntime_api_client_runtimeapi_NativeClient.h | 2 +-
.../include/aws/lambda-runtime/runtime.h | 12 ++-
.../deps/aws-lambda-cpp-0.2.7/src/runtime.cpp | 33 ++++++--
.../runtime/api/client/AWSLambdaTest.java | 77 +++++++++++++++----
.../LambdaRuntimeApiClientImplTest.java | 34 ++++++--
.../codebuild-local/Dockerfile.agent | 4 +-
14 files changed, 182 insertions(+), 49 deletions(-)
diff --git a/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md b/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
index 2391045fc..97d177034 100644
--- a/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
+++ b/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md
@@ -1,3 +1,7 @@
+### July 17, 2026
+`2.12.0`
+- Add `Lambda-Runtime-Invocation-Id` header support for cross-wiring protection. The RIC now echoes the invocation ID received from RAPID on `/next` back on `/response` and `/error`, enabling RAPID to detect and reject stale responses from timed-out invocations.
+
### May 13, 2026
`2.11.0`
- Update aws-lambda-java-serialization dependency to 1.4.1
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index fa543df00..ac62fd5b3 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.0com.amazonawsaws-lambda-java-runtime-interface-client
- 2.11.0
+ 2.12.0jarAWS Lambda Java Runtime Interface Client
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java
index e5b221a80..b9aa0fd11 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java
@@ -315,7 +315,7 @@ private static void startRuntimeLoop(LambdaRequestHandler lambdaRequestHandler,
try {
ByteArrayOutputStream payload = lambdaRequestHandler.call(request);
- runtimeClient.reportInvocationSuccess(request.getId(), payload.toByteArray());
+ runtimeClient.reportInvocationSuccess(request.getId(), payload.toByteArray(), request.getInvocationId());
// clear interrupted flag in case if it was set by user's code
Thread.interrupted();
} catch (Throwable t) {
@@ -323,7 +323,7 @@ private static void startRuntimeLoop(LambdaRequestHandler lambdaRequestHandler,
userFault = UserFault.makeUserFault(t);
shouldExit = exitLoopOnErrors && (t instanceof VirtualMachineError || t instanceof IOError || userFault.fatal);
LambdaError error = createLambdaErrorFromThrowableOrUserFault(t);
- runtimeClient.reportInvocationError(request.getId(), error);
+ runtimeClient.reportInvocationError(request.getId(), error, request.getInvocationId());
} finally {
if (userFault != null) {
lambdaLogger.log(userFault.reportableError(), lambdaLogger.getLogFormat() == LogFormat.JSON ? LogLevel.ERROR : LogLevel.UNDEFINED);
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClient.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClient.java
index a62aeb9b8..042bd2579 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClient.java
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClient.java
@@ -34,15 +34,17 @@ public interface LambdaRuntimeApiClient {
* Report invocation success
* @param requestId request id
* @param response byte array representing response
+ * @param invocationId invocation id for cross-wiring protection (may be null)
*/
- void reportInvocationSuccess(String requestId, byte[] response) throws IOException;
+ void reportInvocationSuccess(String requestId, byte[] response, String invocationId) throws IOException;
/**
* Report invocation error
* @param requestId request id
* @param error error to report
+ * @param invocationId invocation id for cross-wiring protection (may be null)
*/
- void reportInvocationError(String requestId, LambdaError error) throws IOException;
+ void reportInvocationError(String requestId, LambdaError error, String invocationId) throws IOException;
/**
* SnapStart endpoint to report that beforeCheckoint hooks were executed
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImpl.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImpl.java
index caca69aa7..fce12eade 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImpl.java
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImpl.java
@@ -34,6 +34,7 @@ public class LambdaRuntimeApiClientImpl implements LambdaRuntimeApiClient {
private static final String DEFAULT_CONTENT_TYPE = "application/json";
private static final String XRAY_ERROR_CAUSE_HEADER = "Lambda-Runtime-Function-XRay-Error-Cause";
private static final String ERROR_TYPE_HEADER = "Lambda-Runtime-Function-Error-Type";
+ private static final String INVOCATION_ID_HEADER = "Lambda-Runtime-Invocation-Id";
// 1MiB
private static final int XRAY_ERROR_CAUSE_MAX_HEADER_SIZE = 1024 * 1024;
@@ -55,7 +56,7 @@ public LambdaRuntimeApiClientImpl(String hostnameAndPort) {
@Override
public void reportInitError(LambdaError error) throws IOException {
String endpoint = this.baseUrl + "/2018-06-01/runtime/init/error";
- reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE);
+ reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE, null);
}
@Override
@@ -123,14 +124,15 @@ public InvocationRequest nextInvocationWithExponentialBackoff(LambdaContextLogge
}
@Override
- public void reportInvocationSuccess(String requestId, byte[] response) {
- NativeClient.postInvocationResponse(requestId.getBytes(UTF_8), response);
+ public void reportInvocationSuccess(String requestId, byte[] response, String invocationId) {
+ byte[] invocationIdBytes = invocationId != null ? invocationId.getBytes(UTF_8) : null;
+ NativeClient.postInvocationResponse(requestId.getBytes(UTF_8), response, invocationIdBytes);
}
@Override
- public void reportInvocationError(String requestId, LambdaError error) throws IOException {
+ public void reportInvocationError(String requestId, LambdaError error, String invocationId) throws IOException {
String endpoint = invocationEndpoint + requestId + "/error";
- reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE);
+ reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE, invocationId);
}
@Override
@@ -145,13 +147,17 @@ public void restoreNext() throws IOException {
@Override
public void reportRestoreError(LambdaError error) throws IOException {
String endpoint = this.baseUrl + "/2018-06-01/runtime/restore/error";
- reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE);
+ reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE, null);
}
- void reportLambdaError(String endpoint, LambdaError error, int maxXrayHeaderSize) throws IOException {
+ void reportLambdaError(String endpoint, LambdaError error, int maxXrayHeaderSize, String invocationId) throws IOException {
Map headers = new HashMap<>();
headers.put(ERROR_TYPE_HEADER, error.errorType.getRapidError());
+ if (invocationId != null) {
+ headers.put(INVOCATION_ID_HEADER, invocationId);
+ }
+
if (error.xRayErrorCause != null) {
byte[] xRayErrorCauseJson = DtoSerializers.serialize(error.xRayErrorCause);
if (xRayErrorCauseJson != null && xRayErrorCauseJson.length < maxXrayHeaderSize) {
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java
index 101aea4d0..5c690814b 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java
@@ -21,6 +21,6 @@ static void init(String awsLambdaRuntimeApi) {
static native InvocationRequest next();
- static native void postInvocationResponse(byte[] requestId, byte[] response);
+ static native void postInvocationResponse(byte[] requestId, byte[] response, byte[] invocationId);
}
diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/dto/InvocationRequest.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/dto/InvocationRequest.java
index 656945b41..a589cb024 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/dto/InvocationRequest.java
+++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/dto/InvocationRequest.java
@@ -45,6 +45,11 @@ public class InvocationRequest {
*/
private String tenantId;
+ /**
+ * The invocation ID for cross-wiring protection.
+ */
+ private String invocationId;
+
private byte[] content;
public String getId() {
@@ -107,6 +112,14 @@ public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}
+ public String getInvocationId() {
+ return invocationId;
+ }
+
+ public void setInvocationId(String invocationId) {
+ this.invocationId = invocationId;
+ }
+
public byte[] getContent() {
return content;
}
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp
index f06796616..fb6cd3ca3 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp
@@ -21,6 +21,7 @@ static jfieldID clientContextField;
static jfieldID cognitoIdentityField;
static jfieldID xrayTraceIdField;
static jfieldID tenantIdField;
+static jfieldID invocationIdField;
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
@@ -43,6 +44,7 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
clientContextField = env->GetFieldID(invocationRequestClass , "clientContext", "Ljava/lang/String;");
cognitoIdentityField = env->GetFieldID(invocationRequestClass , "cognitoIdentity", "Ljava/lang/String;");
tenantIdField = env->GetFieldID(invocationRequestClass, "tenantId", "Ljava/lang/String;");
+ invocationIdField = env->GetFieldID(invocationRequestClass, "invocationId", "Ljava/lang/String;");
return JNI_VERSION;
}
@@ -112,6 +114,10 @@ JNIEXPORT jobject JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_
CHECK_EXCEPTION(env, env->SetObjectField(invocationRequest, tenantIdField, env->NewStringUTF(response.tenant_id.c_str())));
}
+ if(response.invocation_id != ""){
+ CHECK_EXCEPTION(env, env->SetObjectField(invocationRequest, invocationIdField, env->NewStringUTF(response.invocation_id.c_str())));
+ }
+
bytes = reinterpret_cast(response.payload.c_str());
CHECK_EXCEPTION(env, jArray = env->NewByteArray(response.payload.length()));
CHECK_EXCEPTION(env, env->SetByteArrayRegion(jArray, 0, response.payload.length(), bytes));
@@ -124,7 +130,7 @@ JNIEXPORT jobject JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_
}
JNIEXPORT void JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient_postInvocationResponse
- (JNIEnv *env, jobject thisObject, jbyteArray jrequestId, jbyteArray jresponseArray) {
+ (JNIEnv *env, jobject thisObject, jbyteArray jrequestId, jbyteArray jresponseArray, jbyteArray jinvocationId) {
std::string payload = toNativeString(env, jresponseArray);
if ((env)->ExceptionOccurred()){
return;
@@ -134,8 +140,16 @@ JNIEXPORT void JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_run
return;
}
+ std::string invocationId;
+ if (jinvocationId != nullptr) {
+ invocationId = toNativeString(env, jinvocationId);
+ if ((env)->ExceptionOccurred()){
+ return;
+ }
+ }
+
auto response = aws::lambda_runtime::invocation_response::success(payload, "application/json");
- auto outcome = CLIENT->post_success(requestId, response);
+ auto outcome = CLIENT->post_success(requestId, response, invocationId);
if (!outcome.is_success()) {
std::string errorMessage("Failed to post invocation response.");
throwLambdaRuntimeClientException(env, errorMessage, outcome.get_failure());
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h
index 7219109b0..0f1aaa2ca 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h
@@ -17,7 +17,7 @@ JNIEXPORT jobject JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_
(JNIEnv *, jobject);
JNIEXPORT void JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient_postInvocationResponse
- (JNIEnv *, jobject, jbyteArray, jbyteArray);
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray);
#ifdef __cplusplus
}
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/runtime.h b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/runtime.h
index c4868c1ba..96f90eaa2 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/runtime.h
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/runtime.h
@@ -66,6 +66,11 @@ struct invocation_request {
*/
std::string tenant_id;
+ /**
+ * Invocation ID for cross-wiring protection.
+ */
+ std::string invocation_id;
+
/**
* The number of milliseconds left before lambda terminates the current execution.
*/
@@ -154,11 +159,15 @@ class runtime {
/**
* Tells lambda that the function has succeeded.
*/
+ post_outcome post_success(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id);
+
post_outcome post_success(std::string const& request_id, invocation_response const& handler_response);
/**
* Tells lambda that the function has failed.
*/
+ post_outcome post_failure(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id);
+
post_outcome post_failure(std::string const& request_id, invocation_response const& handler_response);
private:
@@ -167,7 +176,8 @@ class runtime {
post_outcome do_post(
std::string const& url,
std::string const& request_id,
- invocation_response const& handler_response);
+ invocation_response const& handler_response,
+ std::string const& invocation_id);
private:
std::string const m_user_agent_header;
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/runtime.cpp b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/runtime.cpp
index 84a84b439..2d86a1d7e 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/runtime.cpp
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/runtime.cpp
@@ -41,6 +41,7 @@ static constexpr auto COGNITO_IDENTITY_HEADER = "lambda-runtime-cognito-identity
static constexpr auto DEADLINE_MS_HEADER = "lambda-runtime-deadline-ms";
static constexpr auto FUNCTION_ARN_HEADER = "lambda-runtime-invoked-function-arn";
static constexpr auto TENANT_ID_HEADER = "lambda-runtime-aws-tenant-id";
+static constexpr auto INVOCATION_ID_HEADER = "lambda-runtime-invocation-id";
thread_local static CURL* m_curl_handle = curl_easy_init();
enum Endpoints {
@@ -306,25 +307,40 @@ runtime::next_outcome runtime::get_next()
if (resp.has_header(TENANT_ID_HEADER)) {
req.tenant_id = resp.get_header(TENANT_ID_HEADER);
}
+
+ if (resp.has_header(INVOCATION_ID_HEADER)) {
+ req.invocation_id = resp.get_header(INVOCATION_ID_HEADER);
+ }
return next_outcome(req);
}
-runtime::post_outcome runtime::post_success(std::string const& request_id, invocation_response const& handler_response)
+runtime::post_outcome runtime::post_success(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id)
{
std::string const url = m_endpoints[Endpoints::RESULT] + request_id + "/response";
- return do_post(url, request_id, handler_response);
+ return do_post(url, request_id, handler_response, invocation_id);
}
-runtime::post_outcome runtime::post_failure(std::string const& request_id, invocation_response const& handler_response)
+runtime::post_outcome runtime::post_success(std::string const& request_id, invocation_response const& handler_response)
+{
+ return post_success(request_id, handler_response, "");
+}
+
+runtime::post_outcome runtime::post_failure(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id)
{
std::string const url = m_endpoints[Endpoints::RESULT] + request_id + "/error";
- return do_post(url, request_id, handler_response);
+ return do_post(url, request_id, handler_response, invocation_id);
+}
+
+runtime::post_outcome runtime::post_failure(std::string const& request_id, invocation_response const& handler_response)
+{
+ return post_failure(request_id, handler_response, "");
}
runtime::post_outcome runtime::do_post(
std::string const& url,
std::string const& request_id,
- invocation_response const& handler_response)
+ invocation_response const& handler_response,
+ std::string const& invocation_id)
{
set_curl_post_result_options();
curl_easy_setopt(lambda_runtime::m_curl_handle, CURLOPT_URL, url.c_str());
@@ -341,6 +357,9 @@ runtime::post_outcome runtime::do_post(
headers = curl_slist_append(headers, "Expect:");
headers = curl_slist_append(headers, "transfer-encoding:");
headers = curl_slist_append(headers, m_user_agent_header.c_str());
+ if (!invocation_id.empty()) {
+ headers = curl_slist_append(headers, (std::string(INVOCATION_ID_HEADER) + ": " + invocation_id).c_str());
+ }
auto const& payload = handler_response.get_payload();
logging::log_debug(
LOG_TAG, "calculating content length... %s", ("content-length: " + std::to_string(payload.length())).c_str());
@@ -436,13 +455,13 @@ void run_handler(std::function c
logging::log_info(LOG_TAG, "Invoking user handler completed.");
if (res.is_success()) {
- const auto post_outcome = rt.post_success(req.request_id, res);
+ const auto post_outcome = rt.post_success(req.request_id, res, req.invocation_id);
if (!handle_post_outcome(post_outcome, req.request_id)) {
return; // TODO: implement a better retry strategy
}
}
else {
- const auto post_outcome = rt.post_failure(req.request_id, res);
+ const auto post_outcome = rt.post_failure(req.request_id, res, req.invocation_id);
if (!handle_post_outcome(post_outcome, req.request_id)) {
return; // TODO: implement a better retry strategy
}
diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambdaTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambdaTest.java
index 49b59c2cd..100465531 100644
--- a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambdaTest.java
+++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambdaTest.java
@@ -242,7 +242,7 @@ void testConcurrentRunWithPlatformThreads() throws Throwable {
AWSLambda.startRuntimeLoops(lambdaRequestHandler, lambdaLogger, concurrencyConfig, runtimeClient);
// Success Reports Must Equal number of tasks that ran successfully.
- verify(runtimeClient, times(7)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any());
+ verify(runtimeClient, times(7)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any(), any());
// Hashmap keys should equal the number of threads (runtime loops).
assertEquals(4, SampleHandler.hashMap.size());
// Hashmap total count should equal all tasks that ran * number of iterations per task
@@ -280,11 +280,11 @@ void testConcurrentRunWithPlatformThreadsWithFailures() throws Throwable {
verify(lambdaLogger, times(6)).log(anyString(), eq(LogLevel.ERROR));
// Failed invokes should be reported.
- verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any());
- verify(runtimeClient).reportInvocationError(eq(UserFaultID), any());
+ verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any(), any());
+ verify(runtimeClient).reportInvocationError(eq(UserFaultID), any(), any());
// Success Reports Must Equal number of tasks that ran successfully.
- verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any());
+ verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any(), any());
// Hashmap keys should equal the minumum between(number of threads (runtime loops) AND number of tasks that ran successfully).
assertEquals(2, SampleHandler.hashMap.size());
@@ -326,12 +326,12 @@ void testConcurrentModeLoopDoesNotExitExceptForLambdaRuntimeClientMaxRetriesExce
verify(lambdaLogger, times(4)).log(anyString(), eq(LogLevel.ERROR));
// Failed invokes should be reported.
- verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any());
- verify(runtimeClient).reportInvocationError(eq(UserFaultID), any());
- verify(runtimeClient).reportInvocationError(eq(IOErrorID), any());
+ verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any(), any());
+ verify(runtimeClient).reportInvocationError(eq(UserFaultID), any(), any());
+ verify(runtimeClient).reportInvocationError(eq(IOErrorID), any(), any());
// Success Reports Must Equal number of tasks that ran successfully.
- verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any());
+ verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any(), any());
// Hashmap keys should equal the minumum between(number of threads (runtime loops) AND number of tasks that ran successfully).
assertEquals(1, SampleHandler.hashMap.size());
@@ -516,12 +516,12 @@ void testSequentialWithFatalUserFaultErrorStopsLoop() throws Throwable {
verify(lambdaLogger, times(2)).log(anyString(), eq(LogLevel.ERROR));
// Failed invokes should be reported.
- verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any());
- verify(runtimeClient).reportInvocationError(eq(UserFaultID), any());
+ verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any(), any());
+ verify(runtimeClient).reportInvocationError(eq(UserFaultID), any(), any());
// Success Reports Must Equal number of tasks that ran successfully. And only 2 Error reports for failImmediatelyRequest and userFaultRequest.
- verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any());
- verify(runtimeClient, times(2)).reportInvocationError(any(), any());
+ verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any(), any());
+ verify(runtimeClient, times(2)).reportInvocationError(any(), any(), any());
// Hashmap keys should equal one as it is not multithreaded.
assertEquals(1, SampleHandler.hashMap.size());
@@ -562,12 +562,12 @@ void testSequentialWithVirtualMachineErrorStopsLoop() throws Throwable {
verify(lambdaLogger, times(2)).log(anyString(), eq(LogLevel.ERROR));
// Failed invokes should be reported.
- verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any());
- verify(runtimeClient).reportInvocationError(eq(IOErrorID), any());
+ verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any(), any());
+ verify(runtimeClient).reportInvocationError(eq(IOErrorID), any(), any());
// Success Reports Must Equal number of tasks that ran successfully. And only 2 Error reports for failImmediatelyRequest and virtualMachineErrorRequest.
- verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any());
- verify(runtimeClient, times(2)).reportInvocationError(any(), any());
+ verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any(), any());
+ verify(runtimeClient, times(2)).reportInvocationError(any(), any(), any());
// Hashmap keys should equal one as it is not multithreaded.
assertEquals(1, SampleHandler.hashMap.size());
@@ -575,4 +575,49 @@ void testSequentialWithVirtualMachineErrorStopsLoop() throws Throwable {
// Hashmap total count should equal all tasks that ran * number of iterations per task
assertEquals(2 * SampleHandler.nOfIterations, SampleHandler.globalCounter.get());
}
+
+ @Test
+ @Timeout(value = 1, unit = TimeUnit.MINUTES)
+ void testInvocationIdIsPassedToReportSuccess() throws Throwable {
+ when(concurrencyConfig.isMultiConcurrent()).thenReturn(false);
+
+ InvocationRequest requestWithInvId = getFakeInvocationRequest(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE);
+ requestWithInvId.setInvocationId("test-inv-uuid-1234");
+
+ // Fatal error to stop the loop after one successful invocation
+ InvocationRequest fatalRequest = mock(InvocationRequest.class);
+ when(fatalRequest.getId()).thenThrow(UserFault.makeUserFault(new IOError(new Throwable()), true)).thenReturn("fatal");
+
+ when(runtimeClient.nextInvocation())
+ .thenReturn(requestWithInvId)
+ .thenReturn(fatalRequest);
+
+ AWSLambda.startRuntimeLoops(lambdaRequestHandler, lambdaLogger, concurrencyConfig, runtimeClient);
+
+ verify(runtimeClient).reportInvocationSuccess(
+ eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any(), eq("test-inv-uuid-1234"));
+ }
+
+ @Test
+ @Timeout(value = 1, unit = TimeUnit.MINUTES)
+ void testInvocationIdIsPassedToReportError() throws Throwable {
+ when(lambdaLogger.getLogFormat()).thenReturn(LogFormat.JSON);
+ when(concurrencyConfig.isMultiConcurrent()).thenReturn(false);
+
+ InvocationRequest requestWithInvId = getFakeInvocationRequest(SampleHandler.FAIL_IMMEDIATELY_OP_MODE);
+ requestWithInvId.setInvocationId("test-inv-uuid-5678");
+
+ // Fatal error to stop the loop after one error invocation
+ InvocationRequest fatalRequest = mock(InvocationRequest.class);
+ when(fatalRequest.getId()).thenThrow(UserFault.makeUserFault(new IOError(new Throwable()), true)).thenReturn("fatal");
+
+ when(runtimeClient.nextInvocation())
+ .thenReturn(requestWithInvId)
+ .thenReturn(fatalRequest);
+
+ AWSLambda.startRuntimeLoops(lambdaRequestHandler, lambdaLogger, concurrencyConfig, runtimeClient);
+
+ verify(runtimeClient).reportInvocationError(
+ eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any(), eq("test-inv-uuid-5678"));
+ }
}
\ No newline at end of file
diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImplTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImplTest.java
index 710c1565e..9d5929263 100644
--- a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImplTest.java
+++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImplTest.java
@@ -244,7 +244,7 @@ public void reportInvocationErrorTest() {
mockWebServer.enqueue(mockResponse);
LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType);
- lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError);
+ lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError, null);
RecordedRequest recordedRequest = mockWebServer.takeRequest();
HttpUrl actualUrl = recordedRequest.getRequestUrl();
String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/invocation/1234/error";
@@ -274,7 +274,7 @@ public void reportInvocationErrorTestWrongStatusCode() {
mockWebServer.enqueue(mockResponse);
LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType);
- lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError);
+ lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError, null);
fail();
} catch(LambdaRuntimeClientException e) {
String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/invocation/1234/error";
@@ -318,7 +318,7 @@ public void reportLambdaErrorWithXRayTest() {
XRayErrorCause xRayErrorCause = new XRayErrorCause(workingDirectory, exceptions, paths);
LambdaError lambdaError = new LambdaError(errorRequest, xRayErrorCause, rapidErrorType);
- lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError);
+ lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError, null);
RecordedRequest recordedRequest = mockWebServer.takeRequest();
String xrayErrorCauseHeader = recordedRequest.getHeader("Lambda-Runtime-Function-XRay-Error-Cause");
@@ -339,7 +339,7 @@ public void reportInvocationSuccessTest() {
mockWebServer.enqueue(mockResponse);
String response = "{\"msg\":\"test\"}";
- lambdaRuntimeApiClientImpl.reportInvocationSuccess(requestId, response.getBytes());
+ lambdaRuntimeApiClientImpl.reportInvocationSuccess(requestId, response.getBytes(), null);
RecordedRequest recordedRequest = mockWebServer.takeRequest();
HttpUrl actualUrl = recordedRequest.getRequestUrl();
String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/invocation/1234/response";
@@ -456,7 +456,7 @@ public void createUrlMalformedTest() {
RapidErrorType rapidErrorType = RapidErrorType.AfterRestoreError;
LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType);
RuntimeException thrown = assertThrows(RuntimeException.class, ()->{
- lambdaRuntimeApiClientImpl.reportLambdaError("invalidurl", lambdaError, 100);
+ lambdaRuntimeApiClientImpl.reportLambdaError("invalidurl", lambdaError, 100, null);
});
assertTrue(thrown.getLocalizedMessage().contains("java.net.MalformedURLException"));
}
@@ -483,7 +483,7 @@ public void lambdaReportErrorXRayHeaderTooLongTest() {
XRayErrorCause xRayErrorCause = new XRayErrorCause(workingDirectory, exceptions, paths);
LambdaError lambdaError = new LambdaError(errorRequest, xRayErrorCause, rapidErrorType);
- lambdaRuntimeApiClientImpl.reportLambdaError("http://" + getHostnamePort(), lambdaError, 10);
+ lambdaRuntimeApiClientImpl.reportLambdaError("http://" + getHostnamePort(), lambdaError, 10, null);
RecordedRequest recordedRequest = mockWebServer.takeRequest();
String xrayErrorCauseHeader = recordedRequest.getHeader("Lambda-Runtime-Function-XRay-Error-Cause");
@@ -511,6 +511,28 @@ private void verifyNextInvocationRequest() throws Exception {
assertEquals("", actualBody);
}
+ @Test
+ public void reportInvocationErrorWithInvocationIdTest() {
+ try {
+ RapidErrorType rapidErrorType = RapidErrorType.AfterRestoreError;
+
+ MockResponse mockResponse = new MockResponse();
+ mockResponse.setResponseCode(HTTP_ACCEPTED);
+ mockWebServer.enqueue(mockResponse);
+
+ String invocationId = "test-invocation-uuid-1234";
+ LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType);
+ lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError, invocationId);
+ RecordedRequest recordedRequest = mockWebServer.takeRequest();
+
+ String invocationIdHeader = recordedRequest.getHeader("Lambda-Runtime-Invocation-Id");
+ assertEquals(invocationId, invocationIdHeader);
+ } catch(Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
private String getHostnamePort() {
return mockWebServer.getHostName() + ":" + mockWebServer.getPort();
}
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/Dockerfile.agent b/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/Dockerfile.agent
index 350305e81..2b1ba299e 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/Dockerfile.agent
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/Dockerfile.agent
@@ -1,9 +1,7 @@
FROM public.ecr.aws/amazoncorretto/amazoncorretto:8
# Install docker and buildx extension
-RUN amazon-linux-extras enable docker && \
- yum clean metadata && \
- yum install -y docker tar gzip unzip file
+RUN yum install -y docker tar gzip unzip file findutils
COPY --from=docker/buildx-bin:latest /buildx /usr/libexec/docker/cli-plugins/docker-buildx
From f00150c1ef60696ee02041afbbd808b842a3bfbd Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Tue, 28 Jul 2026 15:58:21 +0100
Subject: [PATCH 098/129] refactor(release): reusable CI actions and review
hardening
- Extract resolve-release-version and configure-release-aws-credentials composite actions shared by both release workflows
- Fetch signing key + Sonatype token inside the publish step so secrets never cross $GITHUB_ENV; scrub settings.xml and keyring on exit
- Guard releases to the main branch; cut OIDC role session to 300s
- Set RIC to 2.12.0-SNAPSHOT so the release pipeline can publish it
---
.../action.yml | 27 ++++++
.../resolve-release-version/action.yml | 54 +++++++++++
.../release-runtime-interface-client.yml | 83 ++++++++---------
.github/workflows/release.yml | 93 +++++++++----------
.../pom.xml | 2 +-
5 files changed, 166 insertions(+), 93 deletions(-)
create mode 100644 .github/actions/configure-release-aws-credentials/action.yml
create mode 100644 .github/actions/resolve-release-version/action.yml
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 000000000..a02a1e9a4
--- /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 000000000..06d3f4f1e
--- /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
index 43090d1b7..6cc3bd6ec 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -57,6 +57,16 @@ jobs:
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
@@ -66,15 +76,11 @@ jobs:
distribution: corretto
cache: maven
- - name: Resolve release version
- run: |
- 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
- echo "EFFECTIVE_RELEASE_VERSION=${RELEASE_VERSION_INPUT:-${CURRENT_VERSION%-SNAPSHOT}}" >> "$GITHUB_ENV"
+ - 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
@@ -124,17 +130,14 @@ jobs:
distribution: corretto
cache: maven
- - name: Validate inputs and resolve versions
- run: |
- 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
-
- EFFECTIVE_RELEASE_VERSION="${RELEASE_VERSION_INPUT:-${CURRENT_VERSION%-SNAPSHOT}}"
+ - 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
@@ -147,7 +150,6 @@ jobs:
NEXT_DEV_VERSION="${MA}.${MI}.$((PA + 1))-SNAPSHOT"
fi
- echo "EFFECTIVE_RELEASE_VERSION=$EFFECTIVE_RELEASE_VERSION" >> "$GITHUB_ENV"
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)"
@@ -190,20 +192,32 @@ jobs:
- name: Configure AWS credentials (OIDC)
if: ${{ github.event.inputs.skip_publish != 'true' }}
- uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4
+ uses: ./.github/actions/configure-release-aws-credentials
with:
aws-region: ${{ env.AWS_REGION }}
role-to-assume: ${{ env.OIDC_ROLE_ARN }}
role-session-name: GitHubActionsRicMavenCentralRelease
- role-duration-seconds: 3600
- - name: Fetch signing key and Sonatype credentials
+ # 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: |
- # Shared secrets from LambdaMavenDeploy; nothing stored in GitHub.
+ # 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")
@@ -213,38 +227,23 @@ jobs:
echo "::add-mask::$SONATYPE_PASSWORD"
# Import the key with loopback pinentry so Maven can sign non-interactively.
- GNUPGHOME=$(mktemp -d)
chmod 700 "$GNUPGHOME"
echo "allow-loopback-pinentry" > "$GNUPGHOME/gpg-agent.conf"
echo "pinentry-mode loopback" > "$GNUPGHOME/gpg.conf"
- export GNUPGHOME
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").
- SETTINGS="$RUNNER_TEMP/settings.xml"
{
echo ''
echo "central"
echo "${SONATYPE_USERNAME}"
echo "${SONATYPE_PASSWORD}"
echo ''
- } > "$SETTINGS"
+ } > "$MAVEN_SETTINGS"
- echo "GNUPGHOME=$GNUPGHOME" >> "$GITHUB_ENV"
- echo "GPG_KEYNAME=$GPG_KEYNAME" >> "$GITHUB_ENV"
- echo "GPG_PASSPHRASE=$GPG_PASSPHRASE" >> "$GITHUB_ENV"
- echo "MAVEN_SETTINGS=$SETTINGS" >> "$GITHUB_ENV"
-
- # -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: |
+ # --- Publish ---
mvn deploy -Prelease -DskipTests -DmultiArch=false \
-s "$MAVEN_SETTINGS" \
-Dgpg.keyname="$GPG_KEYNAME" -Dgpg.passphrase="$GPG_PASSPHRASE" \
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index e148c0131..d9437b776 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -59,6 +59,15 @@ jobs:
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
@@ -71,41 +80,19 @@ jobs:
distribution: corretto
cache: maven
- - name: Validate inputs and resolve versions
- run: |
- 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
-
- # 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
-
- # releaseVersion input is an optional override; default strips -SNAPSHOT.
- EFFECTIVE_RELEASE_VERSION="${RELEASE_VERSION_INPUT:-${CURRENT_VERSION%-SNAPSHOT}}"
+ - 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
-
- # Build the release plugin version args once; reused by both paths.
- RELEASE_ARGS="-DreleaseVersion=$EFFECTIVE_RELEASE_VERSION"
- if [[ -n "$DEVELOPMENT_VERSION_INPUT" ]]; then
- RELEASE_ARGS="$RELEASE_ARGS -DdevelopmentVersion=$DEVELOPMENT_VERSION_INPUT"
- fi
-
- echo "EFFECTIVE_RELEASE_VERSION=$EFFECTIVE_RELEASE_VERSION" >> "$GITHUB_ENV"
- echo "RELEASE_ARGS=$RELEASE_ARGS" >> "$GITHUB_ENV"
echo "::notice::Releasing $MODULE $EFFECTIVE_RELEASE_VERSION (POM currently $CURRENT_VERSION)"
- name: Configure git user
@@ -141,20 +128,28 @@ jobs:
- name: Configure AWS credentials (OIDC)
if: ${{ github.event.inputs.skip_publish != 'true' }}
- uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4
+ uses: ./.github/actions/configure-release-aws-credentials
with:
aws-region: ${{ env.AWS_REGION }}
role-to-assume: ${{ env.OIDC_ROLE_ARN }}
role-session-name: GitHubActionsMavenCentralRelease
- role-duration-seconds: 3600
- - name: Fetch signing key and Sonatype credentials
+ # 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: |
- # Shared secrets from LambdaMavenDeploy; nothing stored in GitHub.
+ # 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")
@@ -164,37 +159,31 @@ jobs:
echo "::add-mask::$SONATYPE_PASSWORD"
# Import the key with loopback pinentry so Maven can sign non-interactively.
- GNUPGHOME=$(mktemp -d)
chmod 700 "$GNUPGHOME"
echo "allow-loopback-pinentry" > "$GNUPGHOME/gpg-agent.conf"
echo "pinentry-mode loopback" > "$GNUPGHOME/gpg.conf"
- export GNUPGHOME
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").
- SETTINGS="$RUNNER_TEMP/settings.xml"
{
echo ''
echo "central"
echo "${SONATYPE_USERNAME}"
echo "${SONATYPE_PASSWORD}"
echo ''
- } > "$SETTINGS"
+ } > "$MAVEN_SETTINGS"
- # Pass to later steps (values already masked).
- echo "GNUPGHOME=$GNUPGHOME" >> "$GITHUB_ENV"
- echo "GPG_KEYNAME=$GPG_KEYNAME" >> "$GITHUB_ENV"
- echo "GPG_PASSPHRASE=$GPG_PASSPHRASE" >> "$GITHUB_ENV"
- echo "MAVEN_SETTINGS=$SETTINGS" >> "$GITHUB_ENV"
+ # --- 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/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: |
# Prepare locally (no push): release commits + tag.
- mvn release:prepare -DpushChanges=false $RELEASE_ARGS --file "$MODULE/pom.xml"
+ 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 \
@@ -209,7 +198,11 @@ jobs:
- name: Dry-run release (prepare only, no publish)
if: ${{ github.event.inputs.skip_publish == 'true' }}
run: |
- mvn release:prepare -DdryRun=true $RELEASE_ARGS --file "$MODULE/pom.xml"
+ 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.
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index 10a755c8c..a9c49c958 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.0com.amazonawsaws-lambda-java-runtime-interface-client
- 2.12.0
+ 2.12.0-SNAPSHOTjarAWS Lambda Java Runtime Interface Client
From b9418bc3e02c03fd149e4174dcc3d46ef643773d Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Tue, 28 Jul 2026 23:00:17 +0100
Subject: [PATCH 099/129] feat(release): gate publish on module-specific tests
- log4j2 gates on the CloudWatch integration test (reusable workflow), bound to the publish event
- serialization gates on the aws-lambda-java-tests suite (version-overridden), which its own mvn verify does not run
---
.github/workflows/release.yml | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index d9437b776..2305ade7c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -53,7 +53,20 @@ env:
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
@@ -126,6 +139,28 @@ jobs:
- 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
From 8fbec4a175c148f4a736a4a262d890359bd52239 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Thu, 30 Jul 2026 15:39:46 +0100
Subject: [PATCH 100/129] fix(ci): add workflow_call trigger to integration
test
release.yml invokes run-integration-test.yml as a reusable workflow via
uses:, which GitHub requires the called workflow to declare with an
on: workflow_call trigger. Without it the log4j2 release would fail when
resolving the reusable workflow.
---
.github/workflows/run-integration-test.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/run-integration-test.yml b/.github/workflows/run-integration-test.yml
index ad46d7fd6..35456a7c5 100644
--- a/.github/workflows/run-integration-test.yml
+++ b/.github/workflows/run-integration-test.yml
@@ -9,6 +9,7 @@ permissions:
on:
workflow_dispatch:
+ workflow_call:
push:
branches: [ main ]
paths:
From 12e36128374a747c697757083665587625b3d60b Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Tue, 11 Aug 2026 14:25:14 +0100
Subject: [PATCH 101/129] ci: update release signing key source and native
build runners
Point the Maven Central release workflows at the dedicated GPG signing
key secret, and run the RIC native builds on the self-hosted release
runners instead of the default hosted runners.
---
.github/workflows/release-runtime-interface-client.yml | 6 +++---
.github/workflows/release.yml | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
index 6cc3bd6ec..90858d0f9 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -49,10 +49,10 @@ jobs:
matrix:
include:
- arch: x86_64
- runner: ubuntu-latest
+ runner: codebuild-aws-lambda-java-libs-test-trigger-x86-${{ github.run_id }}-${{ github.run_attempt }}
profiles: linux-x86_64 linux_musl-x86_64
- arch: aarch64
- runner: ubuntu-24.04-arm
+ runner: codebuild-aws-lambda-java-libs-test-trigger-arm64-${{ github.run_id }}-${{ github.run_attempt }}
profiles: linux-aarch64 linux_musl-aarch64
runs-on: ${{ matrix.runner }}
timeout-minutes: 45
@@ -216,7 +216,7 @@ jobs:
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)
+ GPG_JSON=$(aws secretsmanager get-secret-value --secret-id lambda-runtimes/java/gpg-signing-key --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")
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 2305ade7c..a08d3b74a 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -183,7 +183,7 @@ jobs:
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)
+ GPG_JSON=$(aws secretsmanager get-secret-value --secret-id lambda-runtimes/java/gpg-signing-key --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")
From a6f23d841826051dff3af0e24d7a41ea05dd3a0c Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Wed, 12 Aug 2026 11:04:21 +0100
Subject: [PATCH 102/129] ci: point release credentials at dedicated secret
Read the Sonatype credentials from the dedicated per-project secret
instead of the shared one, matching the new signing key source.
---
.github/workflows/release-runtime-interface-client.yml | 2 +-
.github/workflows/release.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
index 90858d0f9..7865a96f4 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -217,7 +217,7 @@ jobs:
# --- Signing key + Sonatype token (shared secrets from LambdaMavenDeploy) ---
GPG_JSON=$(aws secretsmanager get-secret-value --secret-id lambda-runtimes/java/gpg-signing-key --query SecretString --output text)
- CREDS_JSON=$(aws secretsmanager get-secret-value --secret-id maven.sonatype.creds --query SecretString --output text)
+ CREDS_JSON=$(aws secretsmanager get-secret-value --secret-id lambda-runtimes/java/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")
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a08d3b74a..500a2c021 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -184,7 +184,7 @@ jobs:
# --- Signing key + Sonatype token (shared secrets from LambdaMavenDeploy) ---
GPG_JSON=$(aws secretsmanager get-secret-value --secret-id lambda-runtimes/java/gpg-signing-key --query SecretString --output text)
- CREDS_JSON=$(aws secretsmanager get-secret-value --secret-id maven.sonatype.creds --query SecretString --output text)
+ CREDS_JSON=$(aws secretsmanager get-secret-value --secret-id lambda-runtimes/java/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")
From 1dcf590a246ce37363648c5760317083ef34a25b Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Wed, 12 Aug 2026 21:38:50 +0100
Subject: [PATCH 103/129] ci: run release jobs on CodeBuild runners
---
.github/workflows/release-runtime-interface-client.yml | 10 +++++-----
.github/workflows/release.yml | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
index 7865a96f4..06cc80930 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -1,9 +1,9 @@
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.
+# native lib is built on its own architecture (x86_64 and aarch64 CodeBuild
+# runners) instead of emulating with QEMU. A build matrix produces the
+# classifier JARs, then one job assembles and publishes them.
on:
workflow_dispatch:
@@ -115,7 +115,7 @@ jobs:
# Assemble all native builds and publish.
release:
needs: build-natives
- runs-on: ubuntu-latest
+ runs-on: codebuild-aws-lambda-java-libs-test-trigger-x86-${{ github.run_id }}-${{ github.run_attempt }}
environment: Release
timeout-minutes: 30
steps:
@@ -283,5 +283,5 @@ jobs:
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 "| Built natively | x86_64 and aarch_64 on CodeBuild runners (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
index 500a2c021..57ec1f3a0 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -67,7 +67,7 @@ jobs:
# 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
+ runs-on: codebuild-aws-lambda-java-libs-test-trigger-x86-${{ github.run_id }}-${{ github.run_attempt }}
environment: Release
timeout-minutes: 30
From 70d79913b267104cab08f2ce2ff232b1d56ebde3 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Thu, 13 Aug 2026 13:43:18 +0100
Subject: [PATCH 104/129] ci(release): configure Maven CodeArtifact mirror
---
.../actions/configure-maven-mirror/action.yml | 42 +++++++++++++
.../release-runtime-interface-client.yml | 61 ++++++++++++++-----
.github/workflows/release.yml | 43 ++++++++++---
3 files changed, 121 insertions(+), 25 deletions(-)
create mode 100644 .github/actions/configure-maven-mirror/action.yml
diff --git a/.github/actions/configure-maven-mirror/action.yml b/.github/actions/configure-maven-mirror/action.yml
new file mode 100644
index 000000000..ce309a8f7
--- /dev/null
+++ b/.github/actions/configure-maven-mirror/action.yml
@@ -0,0 +1,42 @@
+name: Configure Maven CodeArtifact mirror
+description: Configure Maven to resolve dependencies through the release CodeArtifact repository.
+
+runs:
+ using: composite
+ steps:
+ - shell: bash
+ run: |
+ CA_DOMAIN=aws-lambda
+ CA_REPO=maven-central-store
+
+ # Uses the ambient region and caller account.
+ TOKEN=$(aws codeartifact get-authorization-token \
+ --domain "$CA_DOMAIN" --query authorizationToken --output text)
+ echo "::add-mask::$TOKEN"
+
+ CA_URL=$(aws codeartifact get-repository-endpoint \
+ --domain "$CA_DOMAIN" --repository "$CA_REPO" --format maven \
+ --query repositoryEndpoint --output text)
+
+ # * routes all resolution through the mirror;
+ # deployment uses distributionManagement and is unaffected.
+ mkdir -p "$HOME/.m2"
+ cat > "$HOME/.m2/settings.xml" <
+
+
+ codeartifact-mirror
+ aws
+ ${TOKEN}
+
+
+
+
+ codeartifact-mirror
+ release CodeArtifact Maven Central proxy
+ ${CA_URL}
+ *
+
+
+
+ EOF
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
index 06cc80930..772b12cae 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -69,12 +69,22 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- - name: Set up JDK 8
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
- with:
- java-version: 8
- distribution: corretto
- cache: maven
+ # 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
+
+ # Route all mvn resolution through the CodeArtifact mirror. Must precede
+ # resolve-release-version, which invokes `mvn help:evaluate`. Ambient
+ # CodeBuild runner-role creds supply the token; no OIDC step in this job.
+ - name: Configure Maven CodeArtifact mirror
+ uses: ./.github/actions/configure-maven-mirror
- name: Resolve and validate release version
uses: ./.github/actions/resolve-release-version
@@ -112,6 +122,12 @@ jobs:
${{ env.MODULE }}/target/*-linux*.jar
${{ env.MODULE }}/target/classes/jni/*.so
+ # Remove the user settings holding the CodeArtifact mirror token once the
+ # build is done. Ephemeral runner, so defence-in-depth, not load-bearing.
+ - name: Scrub Maven settings
+ if: always()
+ run: rm -f "$HOME/.m2/settings.xml"
+
# Assemble all native builds and publish.
release:
needs: build-natives
@@ -123,12 +139,23 @@ jobs:
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
+ # 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
+
+ # Route all mvn resolution through the CodeArtifact mirror. Must precede
+ # resolve-release-version (which invokes `mvn help:evaluate`) and the OIDC
+ # step (which would shadow the runner-role creds this needs). Runs on every
+ # path, since dependency resolution happens on dry-runs too.
+ - name: Configure Maven CodeArtifact mirror
+ uses: ./.github/actions/configure-maven-mirror
- name: Resolve and validate release version
uses: ./.github/actions/resolve-release-version
@@ -234,7 +261,11 @@ jobs:
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").
+ # Global settings holding only the Sonatype "central" server for upload.
+ # Passed to Maven as -gs (global) so it MERGES with the CodeArtifact
+ # mirror in ~/.m2/settings.xml (user) that the mirror step wrote: deps
+ # resolve through the mirror, upload goes to central, and the mirror
+ # token stays in that user file instead of being re-passed here.
{
echo ''
echo "central"
@@ -243,9 +274,9 @@ jobs:
echo ''
} > "$MAVEN_SETTINGS"
- # --- Publish ---
+ # --- Publish --- (-gs: merge Sonatype creds with the ~/.m2 mirror)
mvn deploy -Prelease -DskipTests -DmultiArch=false \
- -s "$MAVEN_SETTINGS" \
+ -gs "$MAVEN_SETTINGS" \
-Dgpg.keyname="$GPG_KEYNAME" -Dgpg.passphrase="$GPG_PASSPHRASE" \
--file "$MODULE/pom.xml"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 57ec1f3a0..b35982cbf 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -85,13 +85,22 @@ jobs:
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
+ # 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
+
+ # Route all mvn resolution through the CodeArtifact mirror. Runs before the
+ # OIDC step (which would shadow the runner-role creds this needs) and on
+ # every path, since dependency resolution happens on dry-runs too.
+ - name: Configure Maven CodeArtifact mirror
+ uses: ./.github/actions/configure-maven-mirror
- name: Resolve and validate release version
uses: ./.github/actions/resolve-release-version
@@ -201,7 +210,11 @@ jobs:
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").
+ # Global settings holding only the Sonatype "central" server for upload.
+ # Passed to Maven as -gs (global) so it MERGES with the CodeArtifact
+ # mirror in ~/.m2/settings.xml (user) that the mirror step wrote: deps
+ # resolve through the mirror, upload goes to central, and the mirror
+ # token stays in that user file instead of being re-passed here.
{
echo ''
echo "central"
@@ -220,9 +233,11 @@ jobs:
# 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.
+ # 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.
mvn release:perform -DlocalCheckout=true \
- -Darguments="-s $MAVEN_SETTINGS -Prelease -Dgpg.keyname=$GPG_KEYNAME -Dgpg.passphrase=$GPG_PASSPHRASE" \
+ -Darguments="-gs $MAVEN_SETTINGS -Prelease -Dgpg.keyname=$GPG_KEYNAME -Dgpg.passphrase=$GPG_PASSPHRASE" \
--file "$MODULE/pom.xml"
# Push commits + tag atomically, only after publish succeeded.
@@ -261,3 +276,11 @@ jobs:
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
+
+ # Symmetry with the publish step's in-shell scrub: remove the user settings
+ # holding the CodeArtifact mirror token. Last step, after the mvn-using
+ # rollback path, so nothing still needs it. The runner is ephemeral, so
+ # this is defence-in-depth, not load-bearing.
+ - name: Scrub Maven settings
+ if: always()
+ run: rm -f "$HOME/.m2/settings.xml"
From 8266bb52f251fffc37a794a9b2e402bdca879133 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Fri, 14 Aug 2026 11:40:08 +0100
Subject: [PATCH 105/129] chore(release): disable Maven Central autoPublish
---
aws-lambda-java-core/pom.xml | 2 +-
aws-lambda-java-events-sdk-transformer/pom.xml | 2 +-
aws-lambda-java-events/pom.xml | 2 +-
aws-lambda-java-log4j2/pom.xml | 2 +-
aws-lambda-java-runtime-interface-client/pom.xml | 2 +-
aws-lambda-java-serialization/pom.xml | 2 +-
aws-lambda-java-tests/pom.xml | 2 +-
7 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/aws-lambda-java-core/pom.xml b/aws-lambda-java-core/pom.xml
index e9464e3d1..f45b32fb6 100644
--- a/aws-lambda-java-core/pom.xml
+++ b/aws-lambda-java-core/pom.xml
@@ -154,7 +154,7 @@
truecentral
- true
+ false
diff --git a/aws-lambda-java-events-sdk-transformer/pom.xml b/aws-lambda-java-events-sdk-transformer/pom.xml
index 1072f4cc6..f66020068 100644
--- a/aws-lambda-java-events-sdk-transformer/pom.xml
+++ b/aws-lambda-java-events-sdk-transformer/pom.xml
@@ -206,7 +206,7 @@
truecentral
- true
+ false
diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml
index 7ab9aa938..0b69b03e6 100644
--- a/aws-lambda-java-events/pom.xml
+++ b/aws-lambda-java-events/pom.xml
@@ -201,7 +201,7 @@
truecentral
- true
+ false
diff --git a/aws-lambda-java-log4j2/pom.xml b/aws-lambda-java-log4j2/pom.xml
index 432c4f5c4..842ef2d48 100644
--- a/aws-lambda-java-log4j2/pom.xml
+++ b/aws-lambda-java-log4j2/pom.xml
@@ -197,7 +197,7 @@
truecentral
- true
+ false
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index a9c49c958..6db41aa36 100644
--- a/aws-lambda-java-runtime-interface-client/pom.xml
+++ b/aws-lambda-java-runtime-interface-client/pom.xml
@@ -416,7 +416,7 @@
truecentral
- true
+ false
diff --git a/aws-lambda-java-serialization/pom.xml b/aws-lambda-java-serialization/pom.xml
index 613b204c6..8b2b754af 100644
--- a/aws-lambda-java-serialization/pom.xml
+++ b/aws-lambda-java-serialization/pom.xml
@@ -178,7 +178,7 @@
truecentral
- true
+ false
diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml
index b1daf4105..bb0c7ab74 100644
--- a/aws-lambda-java-tests/pom.xml
+++ b/aws-lambda-java-tests/pom.xml
@@ -239,7 +239,7 @@
truecentral
- true
+ false
From 9bdcd398103ff8fb34b3190d23da004951542380 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Fri, 14 Aug 2026 14:09:13 +0100
Subject: [PATCH 106/129] fix(ci): write JDK 8 toolchains.xml for release
builds
---
.../release-runtime-interface-client.yml | 22 +++++++++++++++++++
.github/workflows/release.yml | 11 ++++++++++
2 files changed, 33 insertions(+)
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
index 772b12cae..f08e5ae58 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -79,6 +79,17 @@ jobs:
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
# Route all mvn resolution through the CodeArtifact mirror. Must precede
# resolve-release-version, which invokes `mvn help:evaluate`. Ambient
@@ -149,6 +160,17 @@ jobs:
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
# Route all mvn resolution through the CodeArtifact mirror. Must precede
# resolve-release-version (which invokes `mvn help:evaluate`) and the OIDC
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index b35982cbf..7ff834e56 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -95,6 +95,17 @@ jobs:
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
# Route all mvn resolution through the CodeArtifact mirror. Runs before the
# OIDC step (which would shadow the runner-role creds this needs) and on
From defc14b93ab939d4377c78f75535ba76bcc0906e Mon Sep 17 00:00:00 2001
From: Davide Melfi
Date: Fri, 14 Aug 2026 14:51:00 +0100
Subject: [PATCH 107/129] chore: test fixing
---
.github/workflows/release-runtime-interface-client.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
index f08e5ae58..3792d5821 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -86,7 +86,7 @@ jobs:
jdk8
- $JAVA_8_HOME
+ $JAVA_HOME
EOF
@@ -167,7 +167,7 @@ jobs:
jdk8
- $JAVA_8_HOME
+ $JAVA_HOME
EOF
From e638ff92d1ab6faf1417d2a53fae09a584a51a75 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Fri, 14 Aug 2026 15:06:45 +0100
Subject: [PATCH 108/129] commenting out main branch requirement for testing
---
.../release-runtime-interface-client.yml | 18 +++++++++---------
.github/workflows/release.yml | 12 ++++++------
2 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
index 3792d5821..ed8865b99 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -57,15 +57,15 @@ jobs:
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
+ # # 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
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 7ff834e56..dc446f7f5 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -74,12 +74,12 @@ jobs:
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
+ # - 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:
From a035af9c6cb3935015be4e1ca30c2fd767e175ef Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Fri, 14 Aug 2026 16:19:28 +0100
Subject: [PATCH 109/129] ci(ric): pull JNI base images via ECR pull-through
cache
---
.../release-runtime-interface-client.yml | 21 +++++++++++++++++++
.../src/main/jni/Dockerfile.glibc | 3 ++-
.../src/main/jni/Dockerfile.musl | 3 ++-
.../src/main/jni/build-jni-lib.sh | 8 +++++--
4 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
index ed8865b99..b5122f31b 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -40,6 +40,11 @@ env:
MAVEN_ARGS: "-B --no-transfer-progress"
AWS_REGION: ${{ vars.AWS_REGION_MAVEN_RELEASE }}
OIDC_ROLE_ARN: ${{ secrets.AWS_ROLE_MAVEN_RELEASE }}
+ # ECR pull-through cache used for the native JNI base images. ECR_REGISTRY is
+ # the login target; BASE_REGISTRY (with the /ecr-public prefix) is passed to
+ # the Dockerfiles as a build-arg.
+ ECR_REGISTRY: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ vars.AWS_REGION_MAVEN_RELEASE }}.amazonaws.com
+ BASE_REGISTRY: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ vars.AWS_REGION_MAVEN_RELEASE }}.amazonaws.com/ecr-public
jobs:
# Build each architecture's native libs (glibc + musl) on a native runner.
@@ -103,6 +108,14 @@ jobs:
module: ${{ env.MODULE }}
release-version-override: ${{ env.RELEASE_VERSION_INPUT }}
+ # The native JNI build shells out to `docker build` against the ECR
+ # pull-through cache (see src/main/jni/Dockerfile.*). Authenticate first so
+ # the base-image pulls don't hit public.ecr.aws. Uses ambient runner creds.
+ - name: Log in to Amazon ECR (pull-through cache)
+ run: |
+ aws ecr get-login-password --region "$AWS_REGION" \
+ | docker login --username AWS --password-stdin "$ECR_REGISTRY"
+
# -DskipTests: only installed so the module compiles, not released here.
- name: Install intra-repo dependencies
run: |
@@ -185,6 +198,14 @@ jobs:
module: ${{ env.MODULE }}
release-version-override: ${{ env.RELEASE_VERSION_INPUT }}
+ # The native JNI build shells out to `docker build` against the ECR
+ # pull-through cache (see src/main/jni/Dockerfile.*). Authenticate first so
+ # the base-image pulls don't hit public.ecr.aws. Uses ambient runner creds.
+ - name: Log in to Amazon ECR (pull-through cache)
+ run: |
+ aws ecr get-login-password --region "$AWS_REGION" \
+ | docker login --username AWS --password-stdin "$ECR_REGISTRY"
+
- name: Resolve next development version and tag
run: |
# Next development version: use the override, or bump the patch.
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc
index 1cfcfbb1d..a8adb18e6 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc
@@ -1,4 +1,5 @@
-FROM public.ecr.aws/amazonlinux/amazonlinux:2
+ARG BASE_REGISTRY=public.ecr.aws
+FROM ${BASE_REGISTRY}/amazonlinux/amazonlinux:2
ARG CURL_VERSION
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.musl b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.musl
index 64725c140..5fd7f4882 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.musl
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.musl
@@ -1,4 +1,5 @@
-FROM public.ecr.aws/docker/library/alpine:3
+ARG BASE_REGISTRY=public.ecr.aws
+FROM ${BASE_REGISTRY}/docker/library/alpine:3
ARG CURL_VERSION
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
index b7dbb5a80..69b9a5125 100755
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
@@ -9,6 +9,10 @@ MULTI_ARCH=${2}
BUILD_OS=${3}
BUILD_ARCH=${4}
CURL_VERSION=7.83.1
+# Registry hosting the base images. Defaults to public.ecr.aws for local and
+# GitHub-hosted builds; the release workflow overrides it with the ECR
+# pull-through cache so egress-locked runners don't hit public.ecr.aws.
+BASE_REGISTRY="${BASE_REGISTRY:-public.ecr.aws}"
function get_docker_platform() {
arch=$1
@@ -45,7 +49,7 @@ function build_for_libc_arch() {
if [[ "${MULTI_ARCH}" == "true" ]]; then
docker build --platform="${docker_platform}" -f "${SRC_DIR}/Dockerfile.${libc_impl}" \
- --build-arg CURL_VERSION=${CURL_VERSION} "${SRC_DIR}" -o - \
+ --build-arg CURL_VERSION=${CURL_VERSION} --build-arg BASE_REGISTRY=${BASE_REGISTRY} "${SRC_DIR}" -o - \
| tar -xOf - src/aws-lambda-runtime-interface-client.so > "${artifact}"
else
echo "multi-arch not requested, assuming this is a workaround to goofyness when docker buildx is enabled on Linux CI environments."
@@ -63,7 +67,7 @@ function build_for_libc_arch() {
docker build --platform="${docker_platform}" \
-t "${image_name}" \
-f "${SRC_DIR}/Dockerfile.${libc_impl}" \
- --build-arg CURL_VERSION=${CURL_VERSION} "${SRC_DIR}" ${EXTRA_LOAD_ARG}
+ --build-arg CURL_VERSION=${CURL_VERSION} --build-arg BASE_REGISTRY=${BASE_REGISTRY} "${SRC_DIR}" ${EXTRA_LOAD_ARG}
echo "Docker image has been successfully built"
From 00e7ed523c380a4187b4ff03d23345217b7f9b71 Mon Sep 17 00:00:00 2001
From: Maxime David
Date: Fri, 14 Aug 2026 15:34:13 +0000
Subject: [PATCH 110/129] fix: set AWS_REGION
---
.../src/main/jni/Dockerfile.glibc | 3 +++
.../src/main/jni/build-jni-lib.sh | 5 +++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc
index a8adb18e6..7ad20122c 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc
@@ -2,6 +2,9 @@ ARG BASE_REGISTRY=public.ecr.aws
FROM ${BASE_REGISTRY}/amazonlinux/amazonlinux:2
ARG CURL_VERSION
+ARG AWS_REGION
+
+RUN if [ -n "${AWS_REGION}" ]; then echo "${AWS_REGION}" > /etc/yum/vars/awsregion; fi
RUN yum install -y \
cmake3 \
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
index 69b9a5125..44a290b6a 100755
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
@@ -13,6 +13,7 @@ CURL_VERSION=7.83.1
# GitHub-hosted builds; the release workflow overrides it with the ECR
# pull-through cache so egress-locked runners don't hit public.ecr.aws.
BASE_REGISTRY="${BASE_REGISTRY:-public.ecr.aws}"
+AWS_REGION="${AWS_REGION:-${AWS_DEFAULT_REGION:-}}"
function get_docker_platform() {
arch=$1
@@ -49,7 +50,7 @@ function build_for_libc_arch() {
if [[ "${MULTI_ARCH}" == "true" ]]; then
docker build --platform="${docker_platform}" -f "${SRC_DIR}/Dockerfile.${libc_impl}" \
- --build-arg CURL_VERSION=${CURL_VERSION} --build-arg BASE_REGISTRY=${BASE_REGISTRY} "${SRC_DIR}" -o - \
+ --build-arg CURL_VERSION=${CURL_VERSION} --build-arg BASE_REGISTRY=${BASE_REGISTRY} --build-arg AWS_REGION=${AWS_REGION} "${SRC_DIR}" -o - \
| tar -xOf - src/aws-lambda-runtime-interface-client.so > "${artifact}"
else
echo "multi-arch not requested, assuming this is a workaround to goofyness when docker buildx is enabled on Linux CI environments."
@@ -67,7 +68,7 @@ function build_for_libc_arch() {
docker build --platform="${docker_platform}" \
-t "${image_name}" \
-f "${SRC_DIR}/Dockerfile.${libc_impl}" \
- --build-arg CURL_VERSION=${CURL_VERSION} --build-arg BASE_REGISTRY=${BASE_REGISTRY} "${SRC_DIR}" ${EXTRA_LOAD_ARG}
+ --build-arg CURL_VERSION=${CURL_VERSION} --build-arg BASE_REGISTRY=${BASE_REGISTRY} --build-arg AWS_REGION=${AWS_REGION} "${SRC_DIR}" ${EXTRA_LOAD_ARG}
echo "Docker image has been successfully built"
From c5c8805eb847870f98325c6bc8469eb04d2f180f Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Fri, 14 Aug 2026 16:57:20 +0100
Subject: [PATCH 111/129] ci(ric): temporarily disable musl builds for testing
---
.../workflows/release-runtime-interface-client.yml | 4 ++--
aws-lambda-java-runtime-interface-client/pom.xml | 13 +++----------
.../src/main/jni/build-jni-lib.sh | 4 +++-
3 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
index b5122f31b..c0ba2d84d 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -55,10 +55,10 @@ jobs:
include:
- arch: x86_64
runner: codebuild-aws-lambda-java-libs-test-trigger-x86-${{ github.run_id }}-${{ github.run_attempt }}
- profiles: linux-x86_64 linux_musl-x86_64
+ profiles: linux-x86_64
- arch: aarch64
runner: codebuild-aws-lambda-java-libs-test-trigger-arm64-${{ github.run_id }}-${{ github.run_attempt }}
- profiles: linux-aarch64 linux_musl-aarch64
+ profiles: linux-aarch64
runs-on: ${{ matrix.runner }}
timeout-minutes: 45
steps:
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index 6db41aa36..c76f37610 100644
--- a/aws-lambda-java-runtime-interface-client/pom.xml
+++ b/aws-lambda-java-runtime-interface-client/pom.xml
@@ -442,16 +442,9 @@
jarlinux-aarch_64
-
- ${project.build.directory}/${project.build.finalName}-linux_musl-x86_64.jar
- jar
- linux_musl-x86_64
-
-
- ${project.build.directory}/${project.build.finalName}-linux_musl-aarch_64.jar
- jar
- linux_musl-aarch_64
-
+
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
index 44a290b6a..82e49d566 100755
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
@@ -116,7 +116,9 @@ if [ -n "$BUILD_OS" ] && [ -n "$BUILD_ARCH" ]; then
else
# build for all architectures and libc implementations
declare -a ARCHITECTURES=("x86_64" "aarch_64")
- declare -a LIBC_IMPLS=("glibc" "musl")
+ # musl (Alpine) temporarily disabled for testing: the egress-locked release
+ # runner can't reach the Alpine apk mirrors. Re-add "musl" once that's solved.
+ declare -a LIBC_IMPLS=("glibc")
for arch in "${ARCHITECTURES[@]}"; do
From 25a85f5a554b6a648ace6f6cfd711c86988c0bd9 Mon Sep 17 00:00:00 2001
From: Maxime David
Date: Fri, 14 Aug 2026 16:42:00 +0000
Subject: [PATCH 112/129] fix: fix egress test
---
.../com/amazonaws/services/lambda/crac/DNSCacheManagerTest.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/crac/DNSCacheManagerTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/crac/DNSCacheManagerTest.java
index 5eb6f749f..721b27059 100644
--- a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/crac/DNSCacheManagerTest.java
+++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/crac/DNSCacheManagerTest.java
@@ -69,7 +69,7 @@ public void positiveDnsCacheShouldBeEmpty() throws CheckpointException, RestoreE
StatefulResource resource = new StatefulResource();
Core.getGlobalContext().register(resource);
- String[] hosts = {"www.stackoverflow.com", "www.amazon.com", "www.yahoo.com"};
+ String[] hosts = {"github.com", "amazonaws.com"};
for(String singleHost : hosts) {
InetAddress address = InetAddress.getByName(singleHost);
}
From c6defea2abcfe8de07a49c63dc315718a8361471 Mon Sep 17 00:00:00 2001
From: Maxime David
Date: Fri, 14 Aug 2026 16:56:21 +0000
Subject: [PATCH 113/129] fix: remove breaking test (test only)
---
.../runtime/api/client/ClasspathLoaderTest.java | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/ClasspathLoaderTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/ClasspathLoaderTest.java
index 38147d219..49ffa59d2 100644
--- a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/ClasspathLoaderTest.java
+++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/ClasspathLoaderTest.java
@@ -35,20 +35,6 @@ void testLoadAllClassesWithNoClasspath() throws IOException {
}
}
- @Test
- void testLoadAllClassesWithEmptyClasspath() {
- String originalClasspath = System.getProperty("java.class.path");
- try {
- System.setProperty("java.class.path", "");
- assertThrows(FileNotFoundException.class, () ->
- ClasspathLoader.main(new String[]{}));
- } finally {
- if (originalClasspath != null) {
- System.setProperty("java.class.path", originalClasspath);
- }
- }
- }
-
@Test
void testLoadAllClassesWithInvalidPath() {
String originalClasspath = System.getProperty("java.class.path");
From c583fae2ec7f6aead477055c9bf84f68cac95fd2 Mon Sep 17 00:00:00 2001
From: Maxime David
Date: Fri, 14 Aug 2026 16:57:17 +0000
Subject: [PATCH 114/129] Revert "fix: remove breaking test (test only)"
This reverts commit c6defea2abcfe8de07a49c63dc315718a8361471.
---
.../runtime/api/client/ClasspathLoaderTest.java | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/ClasspathLoaderTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/ClasspathLoaderTest.java
index 49ffa59d2..38147d219 100644
--- a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/ClasspathLoaderTest.java
+++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/ClasspathLoaderTest.java
@@ -35,6 +35,20 @@ void testLoadAllClassesWithNoClasspath() throws IOException {
}
}
+ @Test
+ void testLoadAllClassesWithEmptyClasspath() {
+ String originalClasspath = System.getProperty("java.class.path");
+ try {
+ System.setProperty("java.class.path", "");
+ assertThrows(FileNotFoundException.class, () ->
+ ClasspathLoader.main(new String[]{}));
+ } finally {
+ if (originalClasspath != null) {
+ System.setProperty("java.class.path", originalClasspath);
+ }
+ }
+ }
+
@Test
void testLoadAllClassesWithInvalidPath() {
String originalClasspath = System.getProperty("java.class.path");
From a0a326b8503bfac928d23e6d743d5b4b8016c93b Mon Sep 17 00:00:00 2001
From: Maxime David
Date: Fri, 14 Aug 2026 17:02:46 +0000
Subject: [PATCH 115/129] fix: java8 home
---
.github/workflows/release-runtime-interface-client.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
index c0ba2d84d..eb48b7525 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -91,7 +91,7 @@ jobs:
jdk8
- $JAVA_HOME
+ $JAVA_8_HOME
EOF
@@ -180,7 +180,7 @@ jobs:
jdk8
- $JAVA_HOME
+ $JAVA_8_HOME
EOF
From d45cfe874e3e0616fa5a00054b253e85d149fec0 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Fri, 14 Aug 2026 18:20:16 +0100
Subject: [PATCH 116/129] ci(ric): blank Java 9+ argLine for JDK 8 test run
---
.github/workflows/release-runtime-interface-client.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
index eb48b7525..c003c79ae 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -243,7 +243,7 @@ jobs:
- name: Run tests
env:
IS_JAVA_8: true
- run: mvn test --file "$MODULE/pom.xml"
+ run: mvn test -DargLineForReflectionTestOnly="" --file "$MODULE/pom.xml"
# JARs to attach + .so files for the fat main JAR.
- name: Download native artifacts
From 306234c05bde2d3ecc9d1462ed7aaf64068792bd Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Fri, 14 Aug 2026 18:39:21 +0100
Subject: [PATCH 117/129] fix(ci): raise OIDC role duration to STS minimum 900s
---
.github/actions/configure-release-aws-credentials/action.yml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/.github/actions/configure-release-aws-credentials/action.yml b/.github/actions/configure-release-aws-credentials/action.yml
index a02a1e9a4..6a34f6480 100644
--- a/.github/actions/configure-release-aws-credentials/action.yml
+++ b/.github/actions/configure-release-aws-credentials/action.yml
@@ -23,5 +23,6 @@ runs:
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
+ # Kept short: the job only needs the role briefly to read two secrets.
+ # 900s is STS's minimum for assume-role; anything lower is rejected.
+ role-duration-seconds: 900
From 3a17a26251d770984fbf280a16f7051ab57006b5 Mon Sep 17 00:00:00 2001
From: Maxime David
Date: Fri, 14 Aug 2026 18:25:24 +0000
Subject: [PATCH 118/129] Revert "ci(ric): temporarily disable musl builds for
testing"
This reverts commit c5c8805eb847870f98325c6bc8469eb04d2f180f.
---
.../workflows/release-runtime-interface-client.yml | 4 ++--
aws-lambda-java-runtime-interface-client/pom.xml | 13 ++++++++++---
.../src/main/jni/build-jni-lib.sh | 4 +---
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
index c003c79ae..49c3f8d5a 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -55,10 +55,10 @@ jobs:
include:
- arch: x86_64
runner: codebuild-aws-lambda-java-libs-test-trigger-x86-${{ github.run_id }}-${{ github.run_attempt }}
- profiles: linux-x86_64
+ profiles: linux-x86_64 linux_musl-x86_64
- arch: aarch64
runner: codebuild-aws-lambda-java-libs-test-trigger-arm64-${{ github.run_id }}-${{ github.run_attempt }}
- profiles: linux-aarch64
+ profiles: linux-aarch64 linux_musl-aarch64
runs-on: ${{ matrix.runner }}
timeout-minutes: 45
steps:
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index c76f37610..6db41aa36 100644
--- a/aws-lambda-java-runtime-interface-client/pom.xml
+++ b/aws-lambda-java-runtime-interface-client/pom.xml
@@ -442,9 +442,16 @@
jarlinux-aarch_64
-
+
+ ${project.build.directory}/${project.build.finalName}-linux_musl-x86_64.jar
+ jar
+ linux_musl-x86_64
+
+
+ ${project.build.directory}/${project.build.finalName}-linux_musl-aarch_64.jar
+ jar
+ linux_musl-aarch_64
+
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
index 82e49d566..44a290b6a 100755
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
@@ -116,9 +116,7 @@ if [ -n "$BUILD_OS" ] && [ -n "$BUILD_ARCH" ]; then
else
# build for all architectures and libc implementations
declare -a ARCHITECTURES=("x86_64" "aarch_64")
- # musl (Alpine) temporarily disabled for testing: the egress-locked release
- # runner can't reach the Alpine apk mirrors. Re-add "musl" once that's solved.
- declare -a LIBC_IMPLS=("glibc")
+ declare -a LIBC_IMPLS=("glibc" "musl")
for arch in "${ARCHITECTURES[@]}"; do
From 69892c1005569a8fab4abf2d6bc82c1782617c34 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
Date: Fri, 14 Aug 2026 18:56:20 +0000
Subject: [PATCH 119/129] chore(ric): release 2.12.0-RC
---
aws-lambda-java-runtime-interface-client/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index 6db41aa36..da9209bbb 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.0com.amazonawsaws-lambda-java-runtime-interface-client
- 2.12.0-SNAPSHOT
+ 2.12.0-RCjarAWS Lambda Java Runtime Interface Client
From cbb4dd0ed547080d8ed77d7dcd30ed538871360d Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
Date: Fri, 14 Aug 2026 18:56:22 +0000
Subject: [PATCH 120/129] chore(ric): prepare next development 2.12.1-SNAPSHOT
---
aws-lambda-java-runtime-interface-client/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index da9209bbb..d84aa51d8 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.0com.amazonawsaws-lambda-java-runtime-interface-client
- 2.12.0-RC
+ 2.12.1-SNAPSHOTjarAWS Lambda Java Runtime Interface Client
From e4713720b62904687eef8a420867f5939caa5236 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Fri, 14 Aug 2026 20:02:02 +0100
Subject: [PATCH 121/129] ci: restore main-only release branch guard
---
.../release-runtime-interface-client.yml | 18 +++++++++---------
.github/workflows/release.yml | 12 ++++++------
2 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/.github/workflows/release-runtime-interface-client.yml b/.github/workflows/release-runtime-interface-client.yml
index 49c3f8d5a..e41dcfc61 100644
--- a/.github/workflows/release-runtime-interface-client.yml
+++ b/.github/workflows/release-runtime-interface-client.yml
@@ -62,15 +62,15 @@ jobs:
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
+ # 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
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index dc446f7f5..7ff834e56 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -74,12 +74,12 @@ jobs:
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
+ - 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:
From e6290f4ea8b8c9216f4b9d04a68b811ef506c729 Mon Sep 17 00:00:00 2001
From: Fabiana Severin
Date: Fri, 14 Aug 2026 20:07:58 +0100
Subject: [PATCH 122/129] chore(ric): revert version bump to 2.12.0-SNAPSHOT
---
aws-lambda-java-runtime-interface-client/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml
index d84aa51d8..6db41aa36 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.0com.amazonawsaws-lambda-java-runtime-interface-client
- 2.12.1-SNAPSHOT
+ 2.12.0-SNAPSHOTjarAWS Lambda Java Runtime Interface Client
From b6f57da1a1dda5547abe5d2a46f459e1262d39bd Mon Sep 17 00:00:00 2001
From: Rudraroop Ray
Date: Wed, 19 Aug 2026 16:42:02 +0000
Subject: [PATCH 123/129] Jackson version bump to 2.18.9 for CVE
---
aws-lambda-java-serialization/RELEASE.CHANGELOG.md | 4 ++++
aws-lambda-java-serialization/pom.xml | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/aws-lambda-java-serialization/RELEASE.CHANGELOG.md b/aws-lambda-java-serialization/RELEASE.CHANGELOG.md
index 3bb977937..2aaa8732a 100644
--- a/aws-lambda-java-serialization/RELEASE.CHANGELOG.md
+++ b/aws-lambda-java-serialization/RELEASE.CHANGELOG.md
@@ -1,3 +1,7 @@
+### Aug 20, 2026
+`1.4.2`:
+- Update `jackson-databind` dependency from 2.18.6 to 2.18.9
+
### May 20, 2026
`1.4.1`:
- Fix build issue
diff --git a/aws-lambda-java-serialization/pom.xml b/aws-lambda-java-serialization/pom.xml
index 8b2b754af..fbdb93d9a 100644
--- a/aws-lambda-java-serialization/pom.xml
+++ b/aws-lambda-java-serialization/pom.xml
@@ -35,7 +35,7 @@
1.81.8com.amazonaws.lambda.thirdparty
- 2.18.6
+ 2.18.92.10.1202310137.3.2
From c38b1b13e347ad2558c48912edf816f95c221aa2 Mon Sep 17 00:00:00 2001
From: Rudraroop Ray
Date: Wed, 19 Aug 2026 17:02:14 +0000
Subject: [PATCH 124/129] Adding next version of serialization post auto-bump
to the test package
---
aws-lambda-java-tests/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml
index bb0c7ab74..40d4d0c37 100644
--- a/aws-lambda-java-tests/pom.xml
+++ b/aws-lambda-java-tests/pom.xml
@@ -43,7 +43,7 @@
-->
5.9.20.8.7
- 1.4.1
+ 1.4.23.16.13.18.03.27.7
From 9bd304e308b2ed54899fde771730def99d022d30 Mon Sep 17 00:00:00 2001
From: Rudraroop Ray
Date: Thu, 20 Aug 2026 10:08:00 +0000
Subject: [PATCH 125/129] Revert "Adding next version of serialization post
auto-bump to the test package"
This reverts commit c38b1b13e347ad2558c48912edf816f95c221aa2.
---
aws-lambda-java-tests/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aws-lambda-java-tests/pom.xml b/aws-lambda-java-tests/pom.xml
index 40d4d0c37..bb0c7ab74 100644
--- a/aws-lambda-java-tests/pom.xml
+++ b/aws-lambda-java-tests/pom.xml
@@ -43,7 +43,7 @@
-->
5.9.20.8.7
- 1.4.2
+ 1.4.13.16.13.18.03.27.7
From a32b1e4ee21bf8e6284010eaca92eefb9f81a7dc Mon Sep 17 00:00:00 2001
From: Maxime David
Date: Thu, 20 Aug 2026 08:41:47 -0400
Subject: [PATCH 126/129] fix: speed up CI (#634)
* fix: speed up CI
* fix: build native JNI lib on aarch64 CI runners
The multiArch=false path skips architectures whose name doesn't match
the host arch, but ARCHITECTURES uses Maven's classifier spelling
'aarch_64' while `arch` reports 'aarch64'. On the ARM runner this
mismatch caused every arch to be skipped, so no .so was built and the
unit tests crashed loading the native library.
Normalize the host arch to 'aarch_64' before comparing.
* fix: speed up smoke tests
* fix: pr comments
---
.../workflows/runtime-interface-client_pr.yml | 66 ++++++++++++++-----
.../Makefile | 31 +++++++--
.../src/main/jni/build-jni-lib.sh | 11 +++-
.../codebuild/buildspec.os.alpine.yml | 2 +-
.../codebuild/buildspec.os.amazoncorretto.yml | 2 +-
5 files changed, 89 insertions(+), 23 deletions(-)
diff --git a/.github/workflows/runtime-interface-client_pr.yml b/.github/workflows/runtime-interface-client_pr.yml
index a0d8c6cc8..b8fb8cfbe 100644
--- a/.github/workflows/runtime-interface-client_pr.yml
+++ b/.github/workflows/runtime-interface-client_pr.yml
@@ -19,8 +19,17 @@ permissions:
jobs:
- smoke-test:
- runs-on: ubuntu-latest
+ smoke-test-arch:
+ strategy:
+ fail-fast: true
+ matrix:
+ include:
+ - arch: x86_64
+ runner: ubuntu-latest
+ - arch: aarch64
+ runner: ubuntu-24.04-arm
+ runs-on: ${{ matrix.runner }}
+ name: "smoke-test (${{ matrix.arch }})"
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
@@ -39,14 +48,23 @@ jobs:
working-directory: ./aws-lambda-java-serialization
run: mvn clean install
- - name: Runtime Interface Client smoke tests - Run 'pr' target
+ - name: Runtime Interface Client smoke tests - Run 'pr-${{ matrix.arch }}' target
working-directory: ./aws-lambda-java-runtime-interface-client
- run: make pr
+ run: make pr-${{ matrix.arch }}
env:
IS_JAVA_8: true
- build:
- runs-on: ubuntu-latest
+ build-arch:
+ strategy:
+ fail-fast: true
+ matrix:
+ include:
+ - arch: x86_64
+ runner: ubuntu-latest
+ - arch: aarch64
+ runner: ubuntu-24.04-arm
+ runs-on: ${{ matrix.runner }}
+ name: "build (${{ matrix.arch }})"
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
@@ -57,17 +75,11 @@ jobs:
distribution: corretto
cache: maven
- - name: Set up QEMU
- uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
-
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
with:
install: true
- - name: Available buildx platforms
- run: echo ${{ steps.buildx.outputs.platforms }}
-
- name: Build and install core dependency locally
working-directory: ./aws-lambda-java-core
run: mvn clean install
@@ -76,16 +88,16 @@ jobs:
working-directory: ./aws-lambda-java-serialization
run: mvn clean install
- - name: Test Runtime Interface Client xplatform build - Run 'build' target
+ - name: Test Runtime Interface Client build - Run 'build-${{ matrix.arch }}' target
working-directory: ./aws-lambda-java-runtime-interface-client
- run: make build
+ run: make build-${{ matrix.arch }}
env:
IS_JAVA_8: true
- name: Save the built jar
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
- name: aws-lambda-java-runtime-interface-client
+ name: aws-lambda-java-runtime-interface-client-${{ matrix.arch }}
path: ./aws-lambda-java-runtime-interface-client/target/aws-lambda-java-runtime-interface-client-*.jar
- name: Upload coverage to Codecov
@@ -93,3 +105,27 @@ jobs:
uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
+
+ smoke-test:
+ needs: smoke-test-arch
+ if: always()
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check smoke-test results
+ run: |
+ if [ "${{ needs.smoke-test-arch.result }}" != "success" ]; then
+ echo "Smoke tests failed on one or more architectures"
+ exit 1
+ fi
+
+ build:
+ needs: build-arch
+ if: always()
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check build results
+ run: |
+ if [ "${{ needs.build-arch.result }}" != "success" ]; then
+ echo "Build failed on one or more architectures"
+ exit 1
+ fi
diff --git a/aws-lambda-java-runtime-interface-client/Makefile b/aws-lambda-java-runtime-interface-client/Makefile
index 6c3a268fb..e651abc96 100644
--- a/aws-lambda-java-runtime-interface-client/Makefile
+++ b/aws-lambda-java-runtime-interface-client/Makefile
@@ -30,11 +30,20 @@ setup-codebuild-agent:
--build-arg ARCHITECTURE=$(ARCHITECTURE_ALIAS) \
- < test/integration/codebuild-local/Dockerfile.agent
+# Smoke tests are split per-architecture so CI can run each set on a native
+# runner. Running the linux/arm64/v8 combos under QEMU on an x86_64 host makes
+# `mvn install` recompile curl for aarch64 emulated, which takes ~30 minutes.
.PHONY: test-smoke
-test-smoke: setup-codebuild-agent
+test-smoke: test-smoke-x86_64 test-smoke-aarch64
+
+.PHONY: test-smoke-x86_64
+test-smoke-x86_64: setup-codebuild-agent
CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.alpine.yml alpine 3.15 corretto11 linux/amd64
- CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.alpine.yml alpine 3.15 corretto11 linux/arm64/v8
CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.amazoncorretto.yml amazoncorretto amazoncorretto 11 linux/amd64
+
+.PHONY: test-smoke-aarch64
+test-smoke-aarch64: setup-codebuild-agent
+ CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.alpine.yml alpine 3.15 corretto11 linux/arm64/v8
CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.amazoncorretto.yml amazoncorretto amazoncorretto 11 linux/arm64/v8
.PHONY: test-integ
@@ -49,11 +58,25 @@ dev: test
.PHONY: pr
pr: test test-smoke
+# Per-architecture PR checks so CI can run each on a native runner (no QEMU).
+.PHONY: pr-x86_64
+pr-x86_64: test test-smoke-x86_64
+
+.PHONY: pr-aarch64
+pr-aarch64: test test-smoke-aarch64
+
.PHONY: build
-build:
- mvn clean install $(EXTRA_LOAD_ARG)
+build: build-x86_64 build-aarch64
+
+.PHONY: build-x86_64
+build-x86_64:
+ mvn clean install -DmultiArch=false $(EXTRA_LOAD_ARG)
mvn install -P linux-x86_64 $(EXTRA_LOAD_ARG)
mvn install -P linux_musl-x86_64 $(EXTRA_LOAD_ARG)
+
+.PHONY: build-aarch64
+build-aarch64:
+ mvn clean install -DmultiArch=false $(EXTRA_LOAD_ARG)
mvn install -P linux-aarch64 $(EXTRA_LOAD_ARG)
mvn install -P linux_musl-aarch64 $(EXTRA_LOAD_ARG)
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
index 44a290b6a..5323030fa 100755
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
@@ -118,10 +118,17 @@ else
declare -a ARCHITECTURES=("x86_64" "aarch_64")
declare -a LIBC_IMPLS=("glibc" "musl")
+ # `arch` reports the host as `aarch64`, but we use Maven's classifier
+ # spelling `aarch_64` in ARCHITECTURES, so normalize before comparing.
+ host_arch=$(arch)
+ if [ "${host_arch}" == "aarch64" ]; then
+ host_arch="aarch_64"
+ fi
+
for arch in "${ARCHITECTURES[@]}"; do
- if [[ "${MULTI_ARCH}" != "true" ]] && [[ "$(arch)" != "${arch}" ]]; then
- echo "multi arch build not requested and host arch is $(arch), so skipping ${arch}..."
+ if [[ "${MULTI_ARCH}" != "true" ]] && [[ "${host_arch}" != "${arch}" ]]; then
+ echo "multi arch build not requested and host arch is ${host_arch}, so skipping ${arch}..."
continue
fi
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.alpine.yml b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.alpine.yml
index 2a71cb1b0..afc68fd76 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.alpine.yml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.alpine.yml
@@ -45,7 +45,7 @@ phases:
# Install serialization (dependency of RIC)
- (cd aws-lambda-java-core && mvn install)
- (cd aws-lambda-java-serialization && mvn install)
- - (cd aws-lambda-java-runtime-interface-client && mvn install -DargLineForReflectionTestOnly="")
+ - (cd aws-lambda-java-runtime-interface-client && mvn install -DmultiArch=false -DargLineForReflectionTestOnly="")
- (cd aws-lambda-java-runtime-interface-client/test/integration/test-handler && mvn install)
- export IMAGE_TAG="java-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}"
- echo "Extracting and including Runtime Interface Emulator"
diff --git a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazoncorretto.yml b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazoncorretto.yml
index db8bf2ba0..e5a586b91 100644
--- a/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazoncorretto.yml
+++ b/aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.amazoncorretto.yml
@@ -44,7 +44,7 @@ phases:
# Install serialization (dependency of RIC)
- (cd aws-lambda-java-core && mvn install)
- (cd aws-lambda-java-serialization && mvn install)
- - (cd aws-lambda-java-runtime-interface-client && mvn install -DargLineForReflectionTestOnly="")
+ - (cd aws-lambda-java-runtime-interface-client && mvn install -DmultiArch=false -DargLineForReflectionTestOnly="")
- (cd aws-lambda-java-runtime-interface-client/test/integration/test-handler && mvn install)
- export IMAGE_TAG="java-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}"
- echo "Extracting and including Runtime Interface Emulator"
From f4363f432dc62f5abc4a4dfd13d9ad36be1d5dde Mon Sep 17 00:00:00 2001
From: Maxime David
Date: Thu, 20 Aug 2026 11:26:08 -0400
Subject: [PATCH 127/129] feat: remove vendored aws-lambda-cpp dependency
(#633)
---
.../workflows/runtime-interface-client_pr.yml | 55 +
.../.gitignore | 3 +
.../Makefile | 11 +-
.../README.md | 2 +-
.../src/main/jni/Dockerfile.glibc | 19 +-
.../src/main/jni/Dockerfile.musl | 14 +-
.../src/main/jni/build-jni-lib.sh | 73 +-
.../deps/aws-lambda-cpp-0.2.7/.clang-format | 61 -
.../jni/deps/aws-lambda-cpp-0.2.7/.clang-tidy | 41 -
.../.github/PULL_REQUEST_TEMPLATE.md | 6 -
.../jni/deps/aws-lambda-cpp-0.2.7/.gitignore | 5 -
.../deps/aws-lambda-cpp-0.2.7/CMakeLists.txt | 132 -
.../aws-lambda-cpp-0.2.7/CODE_OF_CONDUCT.md | 4 -
.../deps/aws-lambda-cpp-0.2.7/CONTRIBUTING.md | 61 -
.../jni/deps/aws-lambda-cpp-0.2.7/LICENSE | 202 -
.../main/jni/deps/aws-lambda-cpp-0.2.7/NOTICE | 2 -
.../jni/deps/aws-lambda-cpp-0.2.7/README.md | 220 -
.../ci/codebuild/amazonlinux-2017.03.yml | 18 -
.../ci/codebuild/build-cpp-sdk.sh | 17 -
.../ci/codebuild/build.sh | 11 -
.../ci/codebuild/format-check.sh | 24 -
.../ci/codebuild/run-tests.sh | 11 -
.../ci/codebuild/ubuntu-18.04.yml | 17 -
.../ci/docker/alpine-linux-3.8 | 5 -
.../ci/docker/amazon-linux-2017.03 | 12 -
.../ci/docker/ubuntu-linux-18.04 | 15 -
.../cmake/aws-lambda-runtime-config.cmake | 20 -
.../aws-lambda-cpp-0.2.7/examples/Dockerfile | 3 -
.../examples/api-gateway/CMakeLists.txt | 12 -
.../examples/api-gateway/README.md | 81 -
.../examples/api-gateway/main.cpp | 61 -
.../examples/dynamodb/CMakeLists.txt | 24 -
.../examples/dynamodb/README.md | 52 -
.../examples/dynamodb/main.cpp | 229 -
.../examples/s3/CMakeLists.txt | 22 -
.../examples/s3/README.md | 51 -
.../aws-lambda-cpp-0.2.7/examples/s3/main.cpp | 128 -
.../include/aws/http/response.h | 174 -
.../include/aws/lambda-runtime/outcome.h | 96 -
.../include/aws/lambda-runtime/runtime.h | 197 -
.../include/aws/lambda-runtime/version.h | 41 -
.../include/aws/logging/logging.h | 67 -
.../aws-lambda-cpp-0.2.7/packaging/packager | 180 -
.../aws-lambda-cpp-0.2.7/src/backward.cpp | 32 -
.../deps/aws-lambda-cpp-0.2.7/src/backward.h | 4291 -----
.../deps/aws-lambda-cpp-0.2.7/src/logging.cpp | 70 -
.../deps/aws-lambda-cpp-0.2.7/src/runtime.cpp | 545 -
.../aws-lambda-cpp-0.2.7/src/version.cpp.in | 48 -
.../aws-lambda-cpp-0.2.7/tests/CMakeLists.txt | 16 -
.../tests/gtest/.clang-tidy | 3 -
.../tests/gtest/gtest-all.cc | 11763 ------------
.../aws-lambda-cpp-0.2.7/tests/gtest/gtest.h | 14916 ----------------
.../deps/aws-lambda-cpp-0.2.7/tests/main.cpp | 38 -
.../tests/resources/CMakeLists.txt | 14 -
.../tests/resources/lambda_function.cpp | 129 -
.../tests/runtime_tests.cpp | 194 -
.../tests/version_tests.cpp | 22 -
.../codebuild-local/Dockerfile.agent | 6 +-
.../codebuild-local/docker-retry.sh | 35 +
.../integration/codebuild-local/test_all.sh | 23 +-
.../integration/codebuild-local/test_one.sh | 6 +-
.../codebuild/buildspec.os.alpine.yml | 2 +-
.../codebuild/buildspec.os.amazoncorretto.yml | 2 +-
.../codebuild/buildspec.os.amazonlinux.1.yml | 2 +-
.../codebuild/buildspec.os.amazonlinux.2.yml | 2 +-
.../codebuild/buildspec.os.centos.yml | 81 -
.../codebuild/buildspec.os.debian.yml | 8 +-
.../codebuild/buildspec.os.ubuntu.yml | 8 +-
.../scripts/configure_multi_arch_env.sh | 2 +-
.../docker/Dockerfile.function.centos | 13 -
.../docker/Dockerfile.function.debian | 6 +-
71 files changed, 217 insertions(+), 34539 deletions(-)
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.clang-format
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.clang-tidy
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.github/PULL_REQUEST_TEMPLATE.md
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.gitignore
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/CMakeLists.txt
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/CODE_OF_CONDUCT.md
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/CONTRIBUTING.md
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/LICENSE
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/NOTICE
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/README.md
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/amazonlinux-2017.03.yml
delete mode 100755 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/build-cpp-sdk.sh
delete mode 100755 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/build.sh
delete mode 100755 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/format-check.sh
delete mode 100755 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/run-tests.sh
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/ubuntu-18.04.yml
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/docker/alpine-linux-3.8
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/docker/amazon-linux-2017.03
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/docker/ubuntu-linux-18.04
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/cmake/aws-lambda-runtime-config.cmake
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/Dockerfile
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/api-gateway/CMakeLists.txt
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/api-gateway/README.md
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/api-gateway/main.cpp
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/dynamodb/CMakeLists.txt
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/dynamodb/README.md
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/dynamodb/main.cpp
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/s3/CMakeLists.txt
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/s3/README.md
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/s3/main.cpp
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/http/response.h
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/outcome.h
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/runtime.h
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/version.h
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/logging/logging.h
delete mode 100755 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/packaging/packager
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/backward.cpp
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/backward.h
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/logging.cpp
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/runtime.cpp
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/version.cpp.in
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/tests/CMakeLists.txt
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/tests/gtest/.clang-tidy
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/tests/gtest/gtest-all.cc
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/tests/gtest/gtest.h
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/tests/main.cpp
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/tests/resources/CMakeLists.txt
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/tests/resources/lambda_function.cpp
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/tests/runtime_tests.cpp
delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/tests/version_tests.cpp
create mode 100755 aws-lambda-java-runtime-interface-client/test/integration/codebuild-local/docker-retry.sh
delete mode 100644 aws-lambda-java-runtime-interface-client/test/integration/codebuild/buildspec.os.centos.yml
delete mode 100644 aws-lambda-java-runtime-interface-client/test/integration/docker/Dockerfile.function.centos
diff --git a/.github/workflows/runtime-interface-client_pr.yml b/.github/workflows/runtime-interface-client_pr.yml
index b8fb8cfbe..bc9e3f3eb 100644
--- a/.github/workflows/runtime-interface-client_pr.yml
+++ b/.github/workflows/runtime-interface-client_pr.yml
@@ -106,6 +106,61 @@ jobs:
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
+ integration-test-matrix:
+ runs-on: ${{ matrix.arch.runner }}
+ strategy:
+ # Run every OS/arch combination to completion so one failure doesn't mask the others.
+ fail-fast: false
+ matrix:
+ buildspec:
+ - buildspec.os.alpine.yml
+ - buildspec.os.amazoncorretto.yml
+ - buildspec.os.amazonlinux.1.yml
+ - buildspec.os.amazonlinux.2.yml
+ - buildspec.os.debian.yml
+ - buildspec.os.ubuntu.yml
+ arch:
+ - label: x64
+ runner: ubuntu-latest
+ platform: linux/amd64
+ - label: arm64
+ runner: ubuntu-24.04-arm
+ platform: linux/arm64/v8
+ exclude:
+ # Amazon Linux 1 was never published for ARM64 (x86_64 only), so
+ # public.ecr.aws/amazonlinux/amazonlinux:1 has no arm64 manifest.
+ - buildspec: buildspec.os.amazonlinux.1.yml
+ arch:
+ label: arm64
+ runner: ubuntu-24.04-arm
+ platform: linux/arm64/v8
+ name: "integration-test (${{ matrix.buildspec }} / ${{ matrix.arch.label }})"
+ steps:
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
+ with:
+ install: true
+
+ - name: Run OS integration test - 'test-integ' target
+ working-directory: ./aws-lambda-java-runtime-interface-client
+ run: make test-integ BUILDSPEC=test/integration/codebuild/${{ matrix.buildspec }}
+ env:
+ PLATFORM_FILTER: ${{ matrix.arch.platform }}
+
+ integration-test:
+ needs: integration-test-matrix
+ if: always()
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check integration-test results
+ run: |
+ if [ "${{ needs.integration-test-matrix.result }}" != "success" ]; then
+ echo "Integration tests failed on one or more OS/arch combinations"
+ exit 1
+ fi
+
smoke-test:
needs: smoke-test-arch
if: always()
diff --git a/aws-lambda-java-runtime-interface-client/.gitignore b/aws-lambda-java-runtime-interface-client/.gitignore
index b1e77deb4..f6064106d 100644
--- a/aws-lambda-java-runtime-interface-client/.gitignore
+++ b/aws-lambda-java-runtime-interface-client/.gitignore
@@ -1,2 +1,5 @@
compile-flags.txt
ric-dev-environment/codeartifact-properties.mk
+
+# aws-lambda-cpp prebuilt lib + headers, fetched and staged at build time
+src/main/jni/deps/aws-lambda-cpp/
diff --git a/aws-lambda-java-runtime-interface-client/Makefile b/aws-lambda-java-runtime-interface-client/Makefile
index e651abc96..770671c07 100644
--- a/aws-lambda-java-runtime-interface-client/Makefile
+++ b/aws-lambda-java-runtime-interface-client/Makefile
@@ -26,9 +26,10 @@ test:
.PHONY: setup-codebuild-agent
setup-codebuild-agent:
- docker build -t codebuild-agent \
+ test/integration/codebuild-local/docker-retry.sh docker build --load -t codebuild-agent \
--build-arg ARCHITECTURE=$(ARCHITECTURE_ALIAS) \
- - < test/integration/codebuild-local/Dockerfile.agent
+ -f test/integration/codebuild-local/Dockerfile.agent \
+ test/integration/codebuild-local
# Smoke tests are split per-architecture so CI can run each set on a native
# runner. Running the linux/arm64/v8 combos under QEMU on an x86_64 host makes
@@ -46,9 +47,13 @@ test-smoke-aarch64: setup-codebuild-agent
CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.alpine.yml alpine 3.15 corretto11 linux/arm64/v8
CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.amazoncorretto.yml amazoncorretto amazoncorretto 11 linux/arm64/v8
+# BUILDSPEC can point to the buildspec directory (default, runs every OS) or to a
+# single buildspec file, which is how CI parallelizes the run across OSes.
+BUILDSPEC ?= test/integration/codebuild
+
.PHONY: test-integ
test-integ: setup-codebuild-agent
- CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_all.sh test/integration/codebuild
+ CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_all.sh $(BUILDSPEC)
# Command to run everytime you make changes to verify everything works
.PHONY: dev
diff --git a/aws-lambda-java-runtime-interface-client/README.md b/aws-lambda-java-runtime-interface-client/README.md
index b72a6238c..a49bf87b4 100644
--- a/aws-lambda-java-runtime-interface-client/README.md
+++ b/aws-lambda-java-runtime-interface-client/README.md
@@ -11,7 +11,7 @@ You can include this package in your preferred base image to make that base imag
### Creating a Docker Image for Lambda with the Runtime Interface Client
-Choose a preferred base image. The Runtime Interface Client is tested on Amazon Linux, Alpine, Ubuntu, Debian, and CentOS. The requirements are that the image is:
+Choose a preferred base image. The Runtime Interface Client is tested on Amazon Linux, Alpine, Ubuntu, and Debian. The requirements are that the image is:
* built for x86_64 and ARM64
* contains Java >= 8
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc
index 7ad20122c..ab6f83b69 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.glibc
@@ -7,7 +7,6 @@ ARG AWS_REGION
RUN if [ -n "${AWS_REGION}" ]; then echo "${AWS_REGION}" > /etc/yum/vars/awsregion; fi
RUN yum install -y \
- cmake3 \
tar \
gzip \
make \
@@ -33,18 +32,12 @@ RUN ./configure \
make && \
make install
-# Install aws-lambda-cpp dependency
-ADD ./deps/aws-lambda-cpp-* /src/deps/aws-lambda-cpp
-RUN mkdir -p /src/deps/aws-lambda-cpp/build
-WORKDIR /src/deps/aws-lambda-cpp/build
-RUN cmake3 .. \
- -DENABLE_LTO=OFF \
- -DCMAKE_CXX_FLAGS="-fPIC -DBACKWARD_SYSTEM_UNKNOWN" \
- -DCMAKE_CXX_STANDARD=11 \
- -DCMAKE_INSTALL_PREFIX=$(pwd)/../../artifacts \
- -DCMAKE_MODULE_PATH=$(pwd)/../../artifacts/lib/pkgconfig && \
- make && \
- make install
+# Install prebuilt aws-lambda-cpp dependency. The static library and headers
+# were fetched and GPG-verified on the host by build-jni-lib.sh; here we only
+# COPY them into the artifacts tree the native client links against (the build
+# container never reaches the network).
+COPY ./deps/aws-lambda-cpp/include /src/deps/artifacts/include
+COPY ./deps/aws-lambda-cpp/lib/libaws-lambda-runtime.a /src/deps/artifacts/lib/
# Build native client
ADD *.cpp *.h /src/
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.musl b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.musl
index 5fd7f4882..fa5b98173 100644
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.musl
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/Dockerfile.musl
@@ -6,7 +6,6 @@ ARG CURL_VERSION
RUN apk update && \
apk add \
openjdk11 \
- cmake \
file \
g++ \
gcc \
@@ -31,17 +30,8 @@ RUN ./configure \
make && \
make install
-# Install aws-lambda-cpp dependency
-ADD ./deps/aws-lambda-cpp-* /src/deps/aws-lambda-cpp
-RUN mkdir -p /src/deps/aws-lambda-cpp/build
-WORKDIR /src/deps/aws-lambda-cpp/build
-RUN cmake .. \
- -DCMAKE_CXX_FLAGS="-fPIC -DBACKWARD_SYSTEM_UNKNOWN" \
- -DCMAKE_CXX_STANDARD=11 \
- -DCMAKE_INSTALL_PREFIX=$(pwd)/../../artifacts\
- -DCMAKE_MODULE_PATH=$(pwd)/../../artifacts/lib/pkgconfig && \
- make && \
- make install
+COPY ./deps/aws-lambda-cpp/include /src/deps/artifacts/include
+COPY ./deps/aws-lambda-cpp/lib/libaws-lambda-runtime.a /src/deps/artifacts/lib/
# Build native client
ADD *.cpp *.h /src/
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
index 5323030fa..28263531b 100755
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
+++ b/aws-lambda-java-runtime-interface-client/src/main/jni/build-jni-lib.sh
@@ -9,12 +9,67 @@ MULTI_ARCH=${2}
BUILD_OS=${3}
BUILD_ARCH=${4}
CURL_VERSION=7.83.1
-# Registry hosting the base images. Defaults to public.ecr.aws for local and
-# GitHub-hosted builds; the release workflow overrides it with the ECR
-# pull-through cache so egress-locked runners don't hit public.ecr.aws.
+
BASE_REGISTRY="${BASE_REGISTRY:-public.ecr.aws}"
AWS_REGION="${AWS_REGION:-${AWS_DEFAULT_REGION:-}}"
+# aws-lambda-cpp is consumed as the prebuilt static library published on the
+# upstream GitHub release rather than being compiled from a vendored source
+# tree. We fetch and GPG-verify it
+ALC_VERSION="1.0.1"
+ALC_TAG="v${ALC_VERSION}"
+ALC_REPO_URL="https://github.com/awslabs/aws-lambda-cpp"
+ALC_RELEASE_URL="${ALC_REPO_URL}/releases/download/${ALC_TAG}"
+ALC_SIGNING_KEY_URL="https://raw.githubusercontent.com/awslabs/aws-lambda-cpp/${ALC_TAG}/signing-public-key.asc"
+ALC_STAGE_DIR="${SRC_DIR}/deps/aws-lambda-cpp"
+
+function fetch_aws_lambda_cpp() {
+ arch=$1
+
+ release_arch="${arch/aarch_64/aarch64}"
+
+ if [ -f "${ALC_STAGE_DIR}/.staged-arch" ] && \
+ [ "$(cat "${ALC_STAGE_DIR}/.staged-arch")" == "${release_arch}" ]; then
+ echo "aws-lambda-cpp ${ALC_VERSION} (${release_arch}) already staged, skipping fetch"
+ return
+ fi
+
+ echo "Fetching prebuilt aws-lambda-cpp ${ALC_VERSION} for ${release_arch}"
+ rm -rf "${ALC_STAGE_DIR}"
+ mkdir -p "${ALC_STAGE_DIR}/lib" "${ALC_STAGE_DIR}/include"
+
+ local workdir
+ workdir=$(mktemp -d)
+ local lib_asset="libaws-lambda-runtime-${release_arch}.a"
+
+ curl -fsSL -o "${workdir}/${lib_asset}" "${ALC_RELEASE_URL}/${lib_asset}"
+ curl -fsSL -o "${workdir}/${lib_asset}.asc" "${ALC_RELEASE_URL}/${lib_asset}.asc"
+ curl -fsSL -o "${workdir}/SHA256SUMS" "${ALC_RELEASE_URL}/SHA256SUMS"
+ curl -fsSL -o "${workdir}/SHA256SUMS.asc" "${ALC_RELEASE_URL}/SHA256SUMS.asc"
+ curl -fsSL -o "${workdir}/signing-key.asc" "${ALC_SIGNING_KEY_URL}"
+
+ local gnupghome
+ gnupghome=$(mktemp -d)
+ gpg --homedir "${gnupghome}" --batch --quiet --import "${workdir}/signing-key.asc"
+ gpg --homedir "${gnupghome}" --batch --verify "${workdir}/${lib_asset}.asc" "${workdir}/${lib_asset}"
+ gpg --homedir "${gnupghome}" --batch --verify "${workdir}/SHA256SUMS.asc" "${workdir}/SHA256SUMS"
+ rm -rf "${gnupghome}"
+
+ # Cross-check the checksum too (defence in depth; SHA256SUMS is itself signed).
+ ( cd "${workdir}" && grep "${lib_asset}\$" SHA256SUMS | sha256sum -c - )
+
+ cp "${workdir}/${lib_asset}" "${ALC_STAGE_DIR}/lib/libaws-lambda-runtime.a"
+
+ # Headers aren't a release asset, so take them from the source at the same
+ # tag. They are declarations only -- every symbol lives in the prebuilt lib.
+ curl -fsSL -o "${workdir}/src.tar.gz" "${ALC_REPO_URL}/archive/refs/tags/${ALC_TAG}.tar.gz"
+ tar -xzf "${workdir}/src.tar.gz" -C "${workdir}" "aws-lambda-cpp-${ALC_VERSION}/include"
+ cp -R "${workdir}/aws-lambda-cpp-${ALC_VERSION}/include/." "${ALC_STAGE_DIR}/include/"
+
+ echo "${release_arch}" > "${ALC_STAGE_DIR}/.staged-arch"
+ rm -rf "${workdir}"
+}
+
function get_docker_platform() {
arch=$1
@@ -44,6 +99,8 @@ function build_for_libc_arch() {
arch=$2
artifact=$3
+ fetch_aws_lambda_cpp "${arch}"
+
docker_platform=$(get_docker_platform ${arch})
echo "Compiling the native library with libc implementation \`${libc_impl}\` on architecture \`${arch}\` using Docker platform \`${docker_platform}\`"
@@ -118,12 +175,10 @@ else
declare -a ARCHITECTURES=("x86_64" "aarch_64")
declare -a LIBC_IMPLS=("glibc" "musl")
- # `arch` reports the host as `aarch64`, but we use Maven's classifier
- # spelling `aarch_64` in ARCHITECTURES, so normalize before comparing.
- host_arch=$(arch)
- if [ "${host_arch}" == "aarch64" ]; then
- host_arch="aarch_64"
- fi
+ host_arch="$(arch)"
+ case "${host_arch}" in
+ aarch64|arm64) host_arch="aarch_64" ;;
+ esac
for arch in "${ARCHITECTURES[@]}"; do
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.clang-format b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.clang-format
deleted file mode 100644
index ec8bb67d4..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.clang-format
+++ /dev/null
@@ -1,61 +0,0 @@
----
-Language: Cpp
-# BasedOnStyle: Mozilla
-AlignAfterOpenBracket: AlwaysBreak
-AlignConsecutiveAssignments: false
-AlignConsecutiveDeclarations: false
-AlignEscapedNewlines: Right
-AlignOperands: true
-AlignTrailingComments: true
-AllowAllParametersOfDeclarationOnNextLine: false
-AllowShortBlocksOnASingleLine: false
-AllowShortCaseLabelsOnASingleLine: false
-AllowShortFunctionsOnASingleLine: Inline
-AllowShortIfStatementsOnASingleLine: false
-AllowShortLoopsOnASingleLine: false
-AlwaysBreakAfterReturnType: None
-AlwaysBreakBeforeMultilineStrings: false
-AlwaysBreakTemplateDeclarations: true
-BinPackArguments: false
-BinPackParameters: false
-BreakBeforeBinaryOperators: None
-BreakBeforeTernaryOperators: true
-BreakStringLiterals: true
-ColumnLimit: 120
-ContinuationIndentWidth: 4
-DerivePointerAlignment: false
-IncludeBlocks: Preserve
-IndentCaseLabels: true
-IndentPPDirectives: AfterHash
-IndentWidth: 4
-IndentWrappedFunctionNames: true
-KeepEmptyLinesAtTheStartOfBlocks: true
-MacroBlockBegin: ''
-MacroBlockEnd: ''
-MaxEmptyLinesToKeep: 1
-PenaltyBreakComment: 10
-PenaltyBreakAssignment: 20
-PenaltyBreakString: 30
-PenaltyBreakBeforeFirstCallParameter: 35
-PenaltyBreakFirstLessLess: 40
-PenaltyExcessCharacter: 1000000
-PenaltyReturnTypeOnItsOwnLine: 100000
-PointerAlignment: Left
-ReflowComments: true
-SortIncludes: false
-SpaceAfterCStyleCast: false
-SpaceBeforeAssignmentOperators: true
-SpaceBeforeParens: ControlStatements
-SpaceInEmptyParentheses: false
-SpacesInContainerLiterals: true
-SpacesInCStyleCastParentheses: false
-SpacesInParentheses: false
-SpacesInSquareBrackets: false
-Standard: Cpp11
-TabWidth: 4
-UseTab: Never
-NamespaceIndentation: None
-BreakBeforeBraces: Stroustrup
-AccessModifierOffset: -4
-...
-
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.clang-tidy b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.clang-tidy
deleted file mode 100644
index 7d343ead8..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.clang-tidy
+++ /dev/null
@@ -1,41 +0,0 @@
----
-Checks:
-'clang-diagnostic-*,clang-analyzer-*,performance-*,readability-*,modernize-*,bugprone-*,misc-*,-modernize-use-trailing-return-type'
-WarningsAsErrors: '*'
-HeaderFilterRegex: 'include/aws/.*\.h$'
-FormatStyle: 'none'
-CheckOptions:
- - key: modernize-pass-by-value.ValuesOnly
- value: '1'
- - key: readability-implicit-bool-conversion.AllowPointerConditions
- value: '1'
- - key: readability-implicit-bool-conversion.AllowIntegerConditions
- value: '1'
- - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
- value: '1'
- - key: readability-identifier-naming.ClassCase
- value: 'lower_case'
- - key: readability-identifier-naming.StructCase
- value: 'lower_case'
- - key: readability-identifier-naming.StructCase
- value: 'lower_case'
- - key: readability-identifier-naming.ParameterCase
- value: 'lower_case'
- - key: readability-identifier-naming.PrivateMemberCase
- value: 'lower_case'
- - key: readability-identifier-naming.LocalVariableCase
- value: 'lower_case'
- - key: readability-identifier-naming.TypeAliasCase
- value: 'lower_case'
- - key: readability-identifier-naming.UnionCase
- value: 'lower_case'
- - key: readability-identifier-naming.FunctionCase
- value: 'lower_case'
- - key: readability-identifier-naming.NamespaceCase
- value: 'lower_case'
- - key: readability-identifier-naming.GlobalConstantCase
- value: 'UPPER_CASE'
- - key: readability-identifier-naming.PrivateMemberPrefix
- value: 'm_'
-
-...
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.github/PULL_REQUEST_TEMPLATE.md b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.github/PULL_REQUEST_TEMPLATE.md
deleted file mode 100644
index ab40d21d7..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.github/PULL_REQUEST_TEMPLATE.md
+++ /dev/null
@@ -1,6 +0,0 @@
-*Issue #, if available:*
-
-*Description of changes:*
-
-
-By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.gitignore b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.gitignore
deleted file mode 100644
index 647f44937..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-build
-tags
-TODO
-compile_commands.json
-.clangd
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/CMakeLists.txt b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/CMakeLists.txt
deleted file mode 100644
index 1765caf06..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/CMakeLists.txt
+++ /dev/null
@@ -1,132 +0,0 @@
-cmake_minimum_required(VERSION 3.9)
-set(CMAKE_CXX_STANDARD 11)
-project(aws-lambda-runtime
- VERSION 0.2.7
- LANGUAGES CXX)
-
-option(ENABLE_LTO "Enables link-time optimization, requires compiler support." ON)
-option(ENABLE_TESTS "Enables building the test project, requires AWS C++ SDK." OFF)
-
-add_library(${PROJECT_NAME}
- "src/logging.cpp"
- "src/runtime.cpp"
- "src/backward.cpp"
- "${CMAKE_CURRENT_BINARY_DIR}/version.cpp"
- )
-
-set_target_properties(${PROJECT_NAME} PROPERTIES
- SOVERSION 0
- VERSION ${PROJECT_VERSION})
-
-target_include_directories(${PROJECT_NAME} PUBLIC
- $
- $)
-
-if (ENABLE_LTO)
- include(CheckIPOSupported)
- check_ipo_supported(RESULT has_lto OUTPUT lto_check_output)
- if(has_lto)
- set_property(TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
- else()
- message(WARNING "Link-time optimization (LTO) is not supported: ${lto_check_output}")
- endif()
-endif()
-
-find_package(CURL REQUIRED)
-if (CMAKE_VERSION VERSION_LESS 3.12)
- target_link_libraries(${PROJECT_NAME} PRIVATE ${CURL_LIBRARIES})
-else()
- target_link_libraries(${PROJECT_NAME} PRIVATE CURL::libcurl)
-endif()
-
-target_include_directories(${PROJECT_NAME} PRIVATE ${CURL_INCLUDE_DIRS})
-
-target_compile_options(${PROJECT_NAME} PRIVATE
- "-fno-exceptions"
- "-fno-rtti"
- "-fvisibility=hidden"
- "-fvisibility-inlines-hidden"
- "-Wall"
- "-Wextra"
- "-Werror"
- "-Wconversion"
- "-Wno-sign-conversion")
-
-find_library(DW_LIB NAMES dw)
-if (NOT DW_LIB STREQUAL DW_LIB-NOTFOUND)
- message("-- Enhanced stack-traces are enabled via libdw: ${DW_LIB}")
- target_compile_definitions(${PROJECT_NAME} PRIVATE "BACKWARD_HAS_DW=1")
- target_link_libraries(${PROJECT_NAME} PUBLIC "${DW_LIB}")
-else()
- find_library(BFD_LIB NAMES bfd)
- if (NOT BFD_LIB STREQUAL BFD_LIB-NOTFOUND)
- message("-- Enhanced stack-traces are enabled via libbfd: ${BFD_LIB}")
- target_compile_definitions(${PROJECT_NAME} PRIVATE "BACKWARD_HAS_BFD=1")
- target_link_libraries(${PROJECT_NAME} PRIVATE "${BFD_LIB}")
- endif()
-endif()
-
-if (LOG_VERBOSITY)
- target_compile_definitions(${PROJECT_NAME} PRIVATE "AWS_LAMBDA_LOG=${LOG_VERBOSITY}")
-elseif(CMAKE_BUILD_TYPE STREQUAL Debug)
- target_compile_definitions(${PROJECT_NAME} PRIVATE "AWS_LAMBDA_LOG=3")
-else ()
- target_compile_definitions(${PROJECT_NAME} PRIVATE "AWS_LAMBDA_LOG=0")
-endif()
-
-#tests
-if (ENABLE_TESTS)
- enable_testing()
- add_subdirectory(tests)
-endif()
-
-#versioning
-configure_file(
- "${CMAKE_CURRENT_SOURCE_DIR}/src/version.cpp.in"
- "${CMAKE_CURRENT_BINARY_DIR}/version.cpp"
- NEWLINE_STYLE LF)
-
-include (CMakePackageConfigHelpers)
-
-write_basic_package_version_file("${PROJECT_NAME}-config-version.cmake"
- VERSION ${PROJECT_VERSION}
- COMPATIBILITY SameMajorVersion)
-
-# installation
-install(FILES "include/aws/http/response.h"
- DESTINATION "include/aws/http")
-
-install(FILES
- "include/aws/lambda-runtime/runtime.h"
- "include/aws/lambda-runtime/version.h"
- "include/aws/lambda-runtime/outcome.h"
- DESTINATION "include/aws/lambda-runtime")
-
-install(FILES "include/aws/logging/logging.h"
- DESTINATION "include/aws/logging")
-
-include(GNUInstallDirs)
-install(TARGETS ${PROJECT_NAME}
- EXPORT ${PROJECT_NAME}-targets
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
- )
-
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/${PROJECT_NAME}-config.cmake"
- "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
- @ONLY)
-
-export(EXPORT "${PROJECT_NAME}-targets" NAMESPACE AWS::)
-
-install(EXPORT "${PROJECT_NAME}-targets"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}/cmake/"
- NAMESPACE AWS::)
-
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
- "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}/cmake/")
-
-install(PROGRAMS "${CMAKE_CURRENT_SOURCE_DIR}/packaging/packager"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}/cmake/")
-
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/CODE_OF_CONDUCT.md b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/CODE_OF_CONDUCT.md
deleted file mode 100644
index 3b6446687..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/CODE_OF_CONDUCT.md
+++ /dev/null
@@ -1,4 +0,0 @@
-## Code of Conduct
-This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
-For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
-opensource-codeofconduct@amazon.com with any additional questions or comments.
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/CONTRIBUTING.md b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/CONTRIBUTING.md
deleted file mode 100644
index e8c3aa58e..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/CONTRIBUTING.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# Contributing Guidelines
-
-Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
-documentation, we greatly value feedback and contributions from our community.
-
-Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
-information to effectively respond to your bug report or contribution.
-
-
-## Reporting Bugs/Feature Requests
-
-We welcome you to use the GitHub issue tracker to report bugs or suggest features.
-
-When filing an issue, please check [existing open](https://github.com/awslabs/aws-lambda-cpp-runtime/issues), or [recently closed](https://github.com/awslabs/aws-lambda-cpp-runtime/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already
-reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
-
-* A reproducible test case or series of steps
-* The version of our code being used
-* Any modifications you've made relevant to the bug
-* Anything unusual about your environment or deployment
-
-
-## Contributing via Pull Requests
-Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
-
-1. You are working against the latest source on the *master* branch.
-2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
-3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
-
-To send us a pull request, please:
-
-1. Fork the repository.
-2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
-3. Ensure local tests pass.
-4. Commit to your fork using clear commit messages.
-5. Send us a pull request, answering any default questions in the pull request interface.
-6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
-
-GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
-[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
-
-
-## Finding contributions to work on
-Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/awslabs/aws-lambda-cpp-runtime/labels/help%20wanted) issues is a great place to start.
-
-
-## Code of Conduct
-This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
-For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
-opensource-codeofconduct@amazon.com with any additional questions or comments.
-
-
-## Security issue notifications
-If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
-
-
-## Licensing
-
-See the [LICENSE](https://github.com/awslabs/aws-lambda-cpp-runtime/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
-
-We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/LICENSE b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/LICENSE
deleted file mode 100644
index d64569567..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/NOTICE b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/NOTICE
deleted file mode 100644
index 34e186a0d..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/NOTICE
+++ /dev/null
@@ -1,2 +0,0 @@
-AWS Lambda Cpp Runtime
-Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/README.md b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/README.md
deleted file mode 100644
index 0812476a0..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/README.md
+++ /dev/null
@@ -1,220 +0,0 @@
-[](https://github.com/awslabs/aws-lambda-cpp/blob/master/LICENSE)
-
-[](https://lgtm.com/projects/g/awslabs/aws-lambda-cpp/context:cpp)
-## AWS Lambda C++ Runtime
-
-C++ implementation of the lambda runtime API
-
-## Design Goals
-1. Negligible cold-start overhead (single digit millisecond).
-2. Freedom of choice in compilers, build platforms and C standard library versions.
-
-## Building and Installing the Runtime
-Since AWS Lambda runs on GNU/Linux, you should build this runtime library and your logic on GNU/Linux as well.
-
-### Prerequisites
-Make sure you have the following packages installed first:
-1. CMake (version 3.9 or later)
-1. git
-1. Make or Ninja
-1. zip
-1. libcurl-devel (on Debian-basded distros it's libcurl4-openssl-dev)
-
-In a terminal, run the following commands:
-```bash
-$ git clone https://github.com/awslabs/aws-lambda-cpp.git
-$ cd aws-lambda-cpp
-$ mkdir build
-$ cd build
-$ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=~/lambda-install
-$ make && make install
-```
-
-To consume this library in a project that is also using CMake, you would do:
-
-```cmake
-cmake_minimum_required(VERSION 3.9)
-set(CMAKE_CXX_STANDARD 11)
-project(demo LANGUAGES CXX)
-find_package(aws-lambda-runtime)
-add_executable(${PROJECT_NAME} "main.cpp")
-target_link_libraries(${PROJECT_NAME} PRIVATE AWS::aws-lambda-runtime)
-target_compile_features(${PROJECT_NAME} PRIVATE "cxx_std_11")
-target_compile_options(${PROJECT_NAME} PRIVATE "-Wall" "-Wextra")
-
-# this line creates a target that packages your binary and zips it up
-aws_lambda_package_target(${PROJECT_NAME})
-```
-
-And here is how a sample `main.cpp` would look like:
-```cpp
-#include
-
-using namespace aws::lambda_runtime;
-
-static invocation_response my_handler(invocation_request const& req)
-{
- if (req.payload.length() > 42) {
- return invocation_response::failure("error message here"/*error_message*/,
- "error type here" /*error_type*/);
- }
-
- return invocation_response::success("json payload here" /*payload*/,
- "application/json" /*MIME type*/);
-}
-
-int main()
-{
- run_handler(my_handler);
- return 0;
-}
-```
-
-And finally, here's how you would package it all. Run the following commands from your application's root directory:
-
-```bash
-$ mkdir build
-$ cd build
-$ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=~/lambda-install
-$ make
-$ make aws-lambda-package-demo
-```
-The last command above `make aws-lambda-package-demo` will create a zip file called `demo.zip` in the current directory.
-
-Now, create an IAM role and the Lambda function via the AWS CLI.
-
-First create the following trust policy JSON file
-
-```
-$ cat trust-policy.json
-{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Principal": {
- "Service": ["lambda.amazonaws.com"]
- },
- "Action": "sts:AssumeRole"
- }
- ]
-}
-
-```
-Then create the IAM role:
-
-```bash
-$ aws iam create-role --role-name lambda-demo --assume-role-policy-document file://trust-policy.json
-```
-
-Note down the role Arn returned to you after running that command. We'll need it in the next steps:
-
-Attach the following policy to allow Lambda to write logs in CloudWatch:
-```bash
-$ aws iam attach-role-policy --role-name lambda-demo --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
-```
-
-Make sure you attach the appropriate policies and/or permissions for any other AWS services that you plan on using.
-
-And finally, create the Lambda function:
-
-```
-$ aws lambda create-function --function-name demo \
---role \
---runtime provided --timeout 15 --memory-size 128 \
---handler demo --zip-file fileb://demo.zip
-```
-
-And to invoke the function:
-```bash
-$ aws lambda invoke --function-name demo --payload '{"answer":42}' output.txt
-```
-
-## Using the C++ SDK for AWS with this runtime
-This library is completely independent from the AWS C++ SDK. You should treat the AWS C++ SDK as just another dependency in your application.
-See [the examples section](https://github.com/awslabs/aws-lambda-cpp/tree/master/examples/) for a demo utilizing the AWS C++ SDK with this Lambda runtime.
-
-## Supported Compilers
-Any *fully* compliant C++11 compiler targeting GNU/Linux x86-64 should work. Please avoid compiler versions that provide half-baked C++11 support.
-
-- Use GCC v5.x or above
-- Use Clang v3.3 or above
-
-## Packaging, ABI, GNU C Library, Oh My!
-Lambda runs your code on some version of Amazon Linux. It would be a less than ideal customer experience if you are forced to build your application on that platform and that platform only.
-
-However, the freedom to build on any linux distro brings a challenge. The GNU C Library ABI. There is no guarantee the platform used to build the Lambda function has the same GLIBC version as the one used by AWS Lambda. In fact, you might not even be using GNU's implementation. For example you could build a C++ Lambda function using musl libc.
-
-To ensure that your application will run correctly on Lambda, we must package the entire C runtime library with your function.
-If you choose to build on the same [Amazon Linux version used by lambda](https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html), you can avoid packaging the C runtime in your zip file.
-This can be done by passing the `NO_LIBC` flag in CMake as follows:
-
-```cmake
-aws_lambda_package_target(${PROJECT_NAME} NO_LIBC)
-```
-### Common Pitfalls with Packaging
-
-* Any library dependency your Lambda function has that is dynamically loaded via `dlopen` will NOT be automatically packaged. You **must** add those dependencies manually to the zip file.
-This applies to any configuration or resource files that your code depends on.
-
-* If you are making HTTP calls over TLS (https), keep in mind that the CA bundle location is different between distros.
-For example, if you are using the AWS C++ SDK, it's best to set the following configuration options:
-
-```cpp
-Aws::Client::ClientConfiguration config;
-config.caFile = "/etc/pki/tls/certs/ca-bundle.crt";
-```
-If you are not using the AWS C++ SDK, but happen to be using libcurl directly, you can set the CA bundle location by doing:
-```c
-curl_easy_setopt(curl_handle, CURLOPT_CAINFO, "/etc/pki/tls/certs/ca-bundle.crt");
-```
-
-## FAQ & Troubleshooting
-1. **Why is the zip file so large? what are all those files?**
- Typically, the zip file is large because we have to package the entire C standard library.
- You can reduce the size by doing some or all of the following:
- - Ensure you're building in release mode `-DCMAKE_BUILD_TYPE=Release`
- - If possible, build your function using musl libc, it's tiny. The easiest way to do this, assuming your code is portable, is to build on Alpine linux, which uses musl libc by default.
-1. **How to upload a zip file that's bigger than 50MB via the CLI?**
- Upload your zip file to S3 first:
- ```bash
- $ aws s3 cp demo.zip s3://mys3bucket/demo.zip
- ```
- NOTE: you must use the same region for your S3 bucket as the lambda.
-
- Then you can create the Lambda function this way:
-
- ```bash
- $ aws lambda create-function --function-name demo \
- --role \
- --runtime provided --timeout 15 --memory-size 128 \
- --handler demo
- --code "S3Bucket=mys3bucket,S3Key=demo.zip"
- ```
-1. **My code is crashing, how can I debug it?**
-
- - Starting with [v0.2.0](https://github.com/awslabs/aws-lambda-cpp/releases/tag/v0.2.0) you should see a stack-trace of the crash site in the logs (which are typically stored in CloudWatch).
- - To get a more detailed stack-trace with source-code information such as line numbers, file names, etc. you need to install one of the following packages:
- - On Debian-based systems - `sudo apt install libdw-dev` or `sudo apt install binutils-dev`
- - On RHEL based systems - `sudo yum install elfutils-devel` or `sudo yum install binutils-devel`
- If you have either of those packages installed, CMake will detect them and automatically link to them. No other
- steps are required.
- - Turn up the logging verbosity to the maximum.
- - Build the runtime in Debug mode. `-DCMAKE_BUILD_TYPE=Debug`. Verbose logs are enabled by default in Debug builds.
- - To enable verbose logs in Release builds, build the runtime with the following CMake flag `-DLOG_VERBOSITY=3`
- - If you are using the AWS C++ SDK, see [this FAQ](https://github.com/aws/aws-sdk-cpp/wiki#how-do-i-turn-on-logging) on how to adjust its logging verbosity
- - Run your code locally on an Amazon Linux AMI or Docker container to reproduce the problem
- - If you go the AMI route, [use the official one](https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html) recommended by AWS Lambda
- - If you go the Docker route, use the following command to launch a container running AL2017.03
- `$ docker run -v /tmp:/tmp -it --security-opt seccomp=unconfined amazonlinux:2017.03`
- The `security-opt` argument is necessary to run `gdb`, `strace`, etc.
-1. **CURL problem with the SSL CA cert**
- - Make sure you are using a `libcurl` version built with OpenSSL, or one of its flavors (BoringSSL, LibreSSL)
- - Make sure you tell `libcurl` where to find the CA bundle file.
- - You can try hitting the non-TLS version of the endpoint if available. (Not Recommended).
-1. **No known conversion between `std::string` and `Aws::String`**
- - Either turn off custom memory management in the AWS C++ SDK or build it as a static library (`-DBUILD_SHARED_LIBS=OFF`)
-
-## License
-
-This library is licensed under the Apache 2.0 License.
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/amazonlinux-2017.03.yml b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/amazonlinux-2017.03.yml
deleted file mode 100644
index eab1bafb5..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/amazonlinux-2017.03.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-version: 0.1
-# This uses the docker image specified in ci/docker/amazon-linux-2017.03
-phases:
- pre_build:
- commands:
- - alias cmake=cmake3
- - pip install awscli
- - ci/codebuild/build-cpp-sdk.sh
- build:
- commands:
- - echo Build started on `date`
- - ci/codebuild/build.sh -DENABLE_TESTS=ON -DTEST_RESOURCE_PREFIX=amzn201703
- - ci/codebuild/run-tests.sh aws-lambda-package-lambda-test-fun amzn201703
- - ci/codebuild/run-tests.sh aws-lambda-package-lambda-test-fun-no-glibc amzn201703
- post_build:
- commands:
- - echo Build completed on `date`
-
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/build-cpp-sdk.sh b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/build-cpp-sdk.sh
deleted file mode 100755
index 93ae7ebec..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/build-cpp-sdk.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-set -euo pipefail
-
-# build the AWS C++ SDK
-cd /aws-sdk-cpp
-git pull
-mkdir build
-cd build
-cmake .. -GNinja -DBUILD_ONLY="lambda" \
- -DCMAKE_BUILD_TYPE=Release \
- -DENABLE_UNITY_BUILD=ON \
- -DBUILD_SHARED_LIBS=ON \
- -DENABLE_TESTING=OFF \
- -DCMAKE_INSTALL_PREFIX=/install $@
-ninja
-ninja install
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/build.sh b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/build.sh
deleted file mode 100755
index 53a9544e2..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/build.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-set -euo pipefail
-
-# build the lambda-runtime
-cd $CODEBUILD_SRC_DIR
-mkdir build
-cd build
-cmake .. -GNinja -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/install $@
-ninja
-ninja install
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/format-check.sh b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/format-check.sh
deleted file mode 100755
index 3afb80230..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/ci/codebuild/format-check.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-
-set -euo pipefail
-
-CLANG_FORMAT=clang-format
-
-if NOT type $CLANG_FORMAT > /dev/null 2>&1; then
- echo "No appropriate clang-format found."
- exit 1
-fi
-
-FAIL=0
-SOURCE_FILES=$(find src include tests -type f -name "*.h" -o -name "*.cpp")
-for i in $SOURCE_FILES
-do
- if [ $($CLANG_FORMAT -output-replacements-xml $i | grep -c "
- DEPENDS ${target})
-endfunction()
-
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/Dockerfile b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/Dockerfile
deleted file mode 100644
index aabb4dd42..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/Dockerfile
+++ /dev/null
@@ -1,3 +0,0 @@
-FROM alpine:latest
-
-RUN apk update && apk add cmake make git g++ bash curl-dev zlib-dev
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/api-gateway/CMakeLists.txt b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/api-gateway/CMakeLists.txt
deleted file mode 100644
index 02da6ccf6..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/api-gateway/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-cmake_minimum_required(VERSION 3.5)
-set(CMAKE_CXX_STANDARD 11)
-
-project(api LANGUAGES CXX)
-
-find_package(aws-lambda-runtime REQUIRED)
-find_package(AWSSDK COMPONENTS core)
-
-add_executable(${PROJECT_NAME} "main.cpp")
-target_link_libraries(${PROJECT_NAME} PUBLIC AWS::aws-lambda-runtime ${AWSSDK_LINK_LIBRARIES})
-
-aws_lambda_package_target(${PROJECT_NAME})
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/api-gateway/README.md b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/api-gateway/README.md
deleted file mode 100644
index d184165b6..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/api-gateway/README.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# Example using the AWS C++ Lambda runtime and Amazon API Gateway
-
-In this example, we'll build a simple "Hello, World" lambda function that can be invoked using an api endpoint created using Amazon API gateway. This example can be viewed as the C++ counterpart to the NodeJS "Hello, World" API example as viewed [here](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html). At the end of this example, you should be able to invoke your lambda via an api endpoint and receive a raw JSON response. This example employs the use of the AWS C++ SDK to parse the request and write the necessary response.
-
-## Build the AWS C++ SDK
-Start by building the SDK from source.
-
-```bash
-$ mkdir ~/install
-$ git clone https://github.com/aws/aws-sdk-cpp.git
-$ cd aws-sdk-cpp
-$ mkdir build
-$ cd build
-$ cmake .. -DBUILD_ONLY="core" \
- -DCMAKE_BUILD_TYPE=Release \
- -DBUILD_SHARED_LIBS=OFF \
- -DENABLE_UNITY_BUILD=ON \
- -DCUSTOM_MEMORY_MANAGEMENT=OFF \
- -DCMAKE_INSTALL_PREFIX=~/install \
- -DENABLE_UNITY_BUILD=ON
-$ make
-$ make install
-```
-
-## Build the Runtime
-We need to build the C++ Lambda runtime as outlined in the other examples.
-
-```bash
-$ git clone https://github.com/awslabs/aws-lambda-cpp-runtime.git
-$ cd aws-lambda-cpp-runtime
-$ mkdir build
-$ cd build
-$ cmake .. -DCMAKE_BUILD_TYPE=Release \
- -DBUILD_SHARED_LIBS=OFF \
- -DCMAKE_INSTALL_PREFIX=~/install \
-$ make
-$ make install
-```
-
-## Build the application
-The next step is to build the Lambda function in `main.cpp` and run the packaging command as follows:
-
-```bash
-$ mkdir build
-$ cd build
-$ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=~/install
-$ make
-$ make aws-lambda-package-api
-```
-
-You should now have a zip file called `api.zip`. Follow the instructions in the main README to upload it and return here once complete.
-
-## Using Amazon API Gateway
-For the rest of this example, we will use the AWS Management Console to create the API endpoint using Amazon API Gateway.
-
-1. Navigate to AWS Lambda within the console [here](https://console.aws.amazon.com/lambda/home)
-1. Select the newly created function. Within the specific function, the "Designer" window should appear.
-1. Simply click "Add trigger" -> "API Gateway" -> "Create an API". Please view the settings below.
- * API Type: HTTP API
- * Security: Open
- * API name: Hello-World-API (or desired name)
- * Deployment stage: default
-1. Once you have added the API gateway, locate the newly created endpoint. View how to test the endpoint below.
-
-## Test the endpoint
-Feel free to test the endpoint any way you desire. Below is a way to test using cURL:
-
-```
-curl -v -X POST \
- '?name=Bradley&city=Chicago' \
- -H 'content-type: application/json' \
- -H 'day: Sunday' \
- -d '{ "time": "evening" }'
-```
-
-With the expected response being:
-```
-{
- "message": "Good evening, Bradley of Chicago. Happy Sunday!"
-}
-```
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/api-gateway/main.cpp b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/api-gateway/main.cpp
deleted file mode 100644
index 90f103551..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/api-gateway/main.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-#include
-#include
-#include
-
-using namespace aws::lambda_runtime;
-
-invocation_response my_handler(invocation_request const& request)
-{
-
- using namespace Aws::Utils::Json;
-
- JsonValue json(request.payload);
- if (!json.WasParseSuccessful()) {
- return invocation_response::failure("Failed to parse input JSON", "InvalidJSON");
- }
-
- auto v = json.View();
- Aws::SimpleStringStream ss;
- ss << "Good ";
-
- if (v.ValueExists("body") && v.GetObject("body").IsString()) {
- auto body = v.GetString("body");
- JsonValue body_json(body);
-
- if (body_json.WasParseSuccessful()) {
- auto body_v = body_json.View();
- ss << (body_v.ValueExists("time") && body_v.GetObject("time").IsString() ? body_v.GetString("time") : "");
- }
- }
- ss << ", ";
-
- if (v.ValueExists("queryStringParameters")) {
- auto query_params = v.GetObject("queryStringParameters");
- ss << (query_params.ValueExists("name") && query_params.GetObject("name").IsString()
- ? query_params.GetString("name")
- : "")
- << " of ";
- ss << (query_params.ValueExists("city") && query_params.GetObject("city").IsString()
- ? query_params.GetString("city")
- : "")
- << ". ";
- }
-
- if (v.ValueExists("headers")) {
- auto headers = v.GetObject("headers");
- ss << "Happy "
- << (headers.ValueExists("day") && headers.GetObject("day").IsString() ? headers.GetString("day") : "")
- << "!";
- }
-
- JsonValue resp;
- resp.WithString("message", ss.str());
-
- return invocation_response::success(resp.View().WriteCompact(), "application/json");
-}
-
-int main()
-{
- run_handler(my_handler);
- return 0;
-}
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/dynamodb/CMakeLists.txt b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/dynamodb/CMakeLists.txt
deleted file mode 100644
index 8447e0197..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/dynamodb/CMakeLists.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-cmake_minimum_required(VERSION 3.5)
-set(CMAKE_CXX_STANDARD 11)
-project(ddb-demo LANGUAGES CXX)
-
-find_package(aws-lambda-runtime)
-find_package(AWSSDK COMPONENTS dynamodb)
-
-add_executable(${PROJECT_NAME} "main.cpp")
-
-target_link_libraries(${PROJECT_NAME} PUBLIC AWS::aws-lambda-runtime ${AWSSDK_LINK_LIBRARIES})
-
-target_compile_options(${PROJECT_NAME} PRIVATE
- "-fno-exceptions"
- "-fno-rtti"
- "-Wall"
- "-Wextra"
- "-Werror"
- "-Wconversion"
- "-Wno-sign-conversion")
-
-target_compile_features(${PROJECT_NAME} PRIVATE "cxx_std_11")
-
-aws_lambda_package_target(${PROJECT_NAME})
-
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/dynamodb/README.md b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/dynamodb/README.md
deleted file mode 100644
index db84fd87e..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/dynamodb/README.md
+++ /dev/null
@@ -1,52 +0,0 @@
-# Example using the AWS C++ SDK with Lambda & DynamoDB
-
-We'll build a Lambda function that can be used as an API Gateway proxy to fetch records from a DynamoDB table.
-To also show case how this can be done on a Linux distro other than Amazon Linux, you can use the Dockerfile in this directory to create an Alpine Linux environment in which you can run the following instructions.
-
-That being said, the instructions below should work on any Linux distribution.
-
-## Build the AWS C++ SDK
-Start by building the SDK from source.
-```bash
-$ mkdir ~/install
-$ git clone https://github.com/aws/aws-sdk-cpp.git
-$ cd aws-sdk-cpp
-$ mkdir build
-$ cd build
-$ cmake .. -DBUILD_ONLY="dynamodb" \
- -DCMAKE_BUILD_TYPE=Release \
- -DBUILD_SHARED_LIBS=OFF \
- -DENABLE_UNITY_BUILD=ON \
- -DCUSTOM_MEMORY_MANAGEMENT=OFF \
- -DCMAKE_INSTALL_PREFIX=~/install \
- -DENABLE_UNITY_BUILD=ON
-
-$ make -j 4
-$ make install
-```
-
-## Build the Runtime
-Now let's build the C++ Lambda runtime, so in a separate directory clone this repository and follow these steps:
-
-```bash
-$ git clone https://github.com/awslabs/aws-lambda-cpp-runtime.git
-$ cd aws-lambda-cpp-runtime
-$ mkdir build
-$ cd build
-$ cmake .. -DCMAKE_BUILD_TYPE=Release \
- -DBUILD_SHARED_LIBS=OFF \
- -DCMAKE_INSTALL_PREFIX=~/install \
-$ make
-$ make install
-```
-
-## Build the application
-The last step is to build the Lambda function in `main.cpp` and run the packaging command as follows:
-
-```bash
-$ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=~/install
-$ make
-$ make aws-lambda-package-ddb-demo
-```
-
-You should now have a zip file called `ddb-demo.zip`. Follow the instructions in the main README to upload it and invoke the lambda.
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/dynamodb/main.cpp b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/dynamodb/main.cpp
deleted file mode 100644
index a8b86621a..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/dynamodb/main.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-// API Gateway Input format
-// {
-// "resource": "Resource path",
-// "path": "Path parameter",
-// "httpMethod": "Incoming request's method name"
-// "headers": {String containing incoming request headers}
-// "multiValueHeaders": {List of strings containing incoming request headers}
-// "queryStringParameters": {query string parameters }
-// "multiValueQueryStringParameters": {List of query string parameters}
-// "pathParameters": {path parameters}
-// "stageVariables": {Applicable stage variables}
-// "requestContext": {Request context, including authorizer-returned key-value pairs}
-// "body": "A JSON string of the request payload."
-// "isBase64Encoded": "A boolean flag to indicate if the applicable request payload is Base64-encode"
-// }
-
-static char const TAG[] = "lambda";
-
-struct criteria {
- criteria(Aws::Utils::Json::JsonView data) : error_msg(nullptr)
- {
- using namespace Aws::Utils;
- auto path_params = data.GetObject("pathParameters");
- if (!path_params.ValueExists("productId")) {
- error_msg = "Missing URL parameter {productId}.";
- return;
- }
-
- product_id = path_params.GetString("productId");
- auto qs = data.GetObject("queryStringParameters");
-
- if (!qs.ValueExists("startDate")) {
- error_msg = "Missing query string parameter 'startDate'.";
- return;
- }
- start_date = DateTime(qs.GetString("startDate"), DateFormat::ISO_8601);
- if (!start_date.WasParseSuccessful()) {
- error_msg = "Invalid input format. startDate must be in ISO 8601 format.";
- return;
- }
-
- if (!qs.ValueExists("endDate")) {
- error_msg = "Missing query string parameter 'endDate'.";
- return;
- }
- end_date = DateTime(qs.GetString("endDate"), DateFormat::ISO_8601);
- if (!end_date.WasParseSuccessful()) {
- error_msg = "Invalid input format. endDate must be in ISO 8601 format.";
- return;
- }
- }
-
- std::string product_id;
- Aws::Utils::DateTime start_date;
- Aws::Utils::DateTime end_date;
- char const* error_msg;
-};
-
-Aws::Utils::Json::JsonValue query(criteria const cr, Aws::DynamoDB::DynamoDBClient const& client)
-{
- using namespace Aws::DynamoDB;
- using namespace Aws::DynamoDB::Model;
- using namespace Aws::Utils::Json;
-
- AWS_LOGSTREAM_DEBUG(
- TAG,
- "criteria is: product_id: " << cr.product_id << " start_date epoch: " << cr.start_date.Millis()
- << " end_date epoch: " << cr.end_date.Millis());
-
- QueryRequest query;
-
- auto const& table_name = Aws::Environment::GetEnv("TABLE_NAME");
- query.SetTableName(table_name);
- query.SetKeyConditionExpression("#H = :h AND #R BETWEEN :s AND :e");
- query.AddExpressionAttributeNames("#H", "product_id");
- query.AddExpressionAttributeNames("#R", "date_time");
-
- query.AddExpressionAttributeValues(":h", AttributeValue(cr.product_id));
- AttributeValue date;
- date.SetN(std::to_string(cr.start_date.Millis() / 1000));
- query.AddExpressionAttributeValues(":s", date);
-
- date.SetN(std::to_string(cr.end_date.Millis() / 1000));
- query.AddExpressionAttributeValues(":e", date);
-
- auto outcome = client.Query(query);
- if (outcome.IsSuccess()) {
- auto const& maps = outcome.GetResult().GetItems(); // returns vector of map
- if (maps.empty()) {
- AWS_LOGSTREAM_DEBUG(TAG, "No data returned from query");
- return {};
- }
-
- // Schema
- // string_attr :product_id, hash_key: true
- // epoch_time_attr :date_time, range_key: true
- // string_attr :product_title
- // string_attr :marketplace
- // string_attr :product_category
- // date_attr :review_date
- // integer_attr :star_rating
- // float_attr :postive
- // float_attr :mixed
- // float_attr :neutral
- // float_attr :negative
-
- JsonValue output;
- output.WithString("product", maps[0].find("product_title")->second.GetS());
- output.WithString("category", maps[0].find("product_category")->second.GetS());
- Aws::Utils::Array sentiments(maps.size());
- for (size_t i = 0; i < maps.size(); i++) {
- JsonValue review;
- auto&& m = maps[i];
-
- auto it = m.find("review_date");
- if (it != m.end()) {
- review.WithString("date", it->second.GetS());
- }
-
- it = m.find("positive");
- if (it != m.end()) {
- review.WithString("positive", it->second.GetN());
- }
-
- it = m.find("negative");
- if (it != m.end()) {
- review.WithString("negative", it->second.GetN());
- }
-
- it = m.find("mixed");
- if (it != m.end()) {
- review.WithString("mixed", it->second.GetN());
- }
-
- it = m.find("neutral");
- if (it != m.end()) {
- review.WithString("neutral", it->second.GetN());
- }
-
- sentiments[i] = std::move(review);
- }
- output.WithArray("sentiment", sentiments);
- return output;
- }
-
- AWS_LOGSTREAM_ERROR(TAG, "database query failed: " << outcome.GetError());
- return {};
-}
-
-
-aws::lambda_runtime::invocation_response my_handler(
- aws::lambda_runtime::invocation_request const& req,
- Aws::DynamoDB::DynamoDBClient const& client)
-{
- using namespace Aws::Utils::Json;
- AWS_LOGSTREAM_DEBUG(TAG, "received payload: " << req.payload);
- JsonValue eventJson(req.payload);
- assert(eventJson.WasParseSuccessful());
- const criteria cr(eventJson);
- if (cr.error_msg) {
- JsonValue response;
- response.WithString("body", cr.error_msg).WithInteger("statusCode", 400);
- auto const apig_response = response.View().WriteCompact();
- AWS_LOGSTREAM_ERROR(TAG, "Validation failed. " << apig_response);
- return aws::lambda_runtime::invocation_response::success(apig_response, "application/json");
- }
-
- auto result = query(cr, client);
- auto const query_response = result.View().WriteCompact();
- AWS_LOGSTREAM_DEBUG(TAG, "query response: " << query_response);
-
- JsonValue response;
- if (result.View().ValueExists("product")) {
- response.WithString("body", query_response).WithInteger("statusCode", 200);
- }
- else {
- response.WithString("body", "No data found for this product.").WithInteger("statusCode", 400);
- }
-
- auto const apig_response = response.View().WriteCompact();
- AWS_LOGSTREAM_DEBUG(TAG, "api gateway response: " << apig_response);
-
- return aws::lambda_runtime::invocation_response::success(apig_response, "application/json");
-}
-
-std::function()> GetConsoleLoggerFactory()
-{
- return [] {
- return Aws::MakeShared(
- "console_logger", Aws::Utils::Logging::LogLevel::Trace);
- };
-}
-
-int main()
-{
- using namespace Aws;
- SDKOptions options;
- options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Trace;
- options.loggingOptions.logger_create_fn = GetConsoleLoggerFactory();
- InitAPI(options);
- {
- Aws::Client::ClientConfiguration config;
- config.region = Aws::Environment::GetEnv("AWS_REGION");
- config.caFile = "/etc/pki/tls/certs/ca-bundle.crt";
- config.disableExpectHeader = true;
-
- auto credentialsProvider = Aws::MakeShared(TAG);
- Aws::DynamoDB::DynamoDBClient client(credentialsProvider, config);
- auto handler_fn = [&client](aws::lambda_runtime::invocation_request const& req) {
- return my_handler(req, client);
- };
- aws::lambda_runtime::run_handler(handler_fn);
- }
- ShutdownAPI(options);
- return 0;
-}
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/s3/CMakeLists.txt b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/s3/CMakeLists.txt
deleted file mode 100644
index b398a4e2d..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/s3/CMakeLists.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-cmake_minimum_required(VERSION 3.5)
-set(CMAKE_CXX_STANDARD 11)
-project(encoder LANGUAGES CXX)
-
-find_package(aws-lambda-runtime)
-find_package(AWSSDK COMPONENTS s3)
-
-add_executable(${PROJECT_NAME} "main.cpp")
-
-target_link_libraries(${PROJECT_NAME} PRIVATE AWS::aws-lambda-runtime ${AWSSDK_LINK_LIBRARIES})
-
-target_compile_options(${PROJECT_NAME} PRIVATE
- "-Wall"
- "-Wextra"
- "-Wconversion"
- "-Wshadow"
- "-Wno-sign-conversion")
-
-target_compile_features(${PROJECT_NAME} PRIVATE "cxx_std_11")
-
-aws_lambda_package_target(${PROJECT_NAME})
-
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/s3/README.md b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/s3/README.md
deleted file mode 100644
index 8bc3255a4..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/s3/README.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# Example using the AWS C++ SDK with Lambda
-
-We'll build a lambda that downloads an image file from S3 and sends it back in the response as Base64 encoded that can be displayed in a web page for example.
-To also show case how this can be done on a Linux distro other than Amazon Linux, you can use the Dockerfile in this directory to create an Alpine Linux environment in which you can run the following instructions.
-
-That being said, the instructions below should work on any Linux distribution.
-
-## Build the AWS C++ SDK
-Start by building the SDK from source.
-```bash
-$ mkdir ~/install
-$ git clone https://github.com/aws/aws-sdk-cpp.git
-$ cd aws-sdk-cpp
-$ mkdir build
-$ cd build
-$ cmake .. -DBUILD_ONLY="s3" \
- -DCMAKE_BUILD_TYPE=Release \
- -DBUILD_SHARED_LIBS=OFF \
- -DCUSTOM_MEMORY_MANAGEMENT=OFF \
- -DCMAKE_INSTALL_PREFIX=~/install \
- -DENABLE_UNITY_BUILD=ON
-
-$ make
-$ make install
-```
-
-## Build the Runtime
-Now let's build the C++ Lambda runtime, so in a separate directory clone this repository and follow these steps:
-
-```bash
-$ git clone https://github.com/awslabs/aws-lambda-cpp-runtime.git
-$ cd aws-lambda-cpp-runtime
-$ mkdir build
-$ cd build
-$ cmake .. -DCMAKE_BUILD_TYPE=Release \
- -DBUILD_SHARED_LIBS=OFF \
- -DCMAKE_INSTALL_PREFIX=~/install \
-$ make
-$ make install
-```
-
-## Build the application
-The last step is to build the Lambda function in `main.cpp` and run the packaging command as follows:
-
-```bash
-$ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=~/install
-$ make
-$ make aws-lambda-package-encoder
-```
-
-You should now have a zip file called `encoder.zip`. Follow the instructions in the main README to upload it and invoke the lambda.
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/s3/main.cpp b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/s3/main.cpp
deleted file mode 100644
index 45b935bf3..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/examples/s3/main.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-using namespace aws::lambda_runtime;
-
-std::string download_and_encode_file(
- Aws::S3::S3Client const& client,
- Aws::String const& bucket,
- Aws::String const& key,
- Aws::String& encoded_output);
-
-std::string encode(Aws::String const& filename, Aws::String& output);
-char const TAG[] = "LAMBDA_ALLOC";
-
-static invocation_response my_handler(invocation_request const& req, Aws::S3::S3Client const& client)
-{
- using namespace Aws::Utils::Json;
- JsonValue json(req.payload);
- if (!json.WasParseSuccessful()) {
- return invocation_response::failure("Failed to parse input JSON", "InvalidJSON");
- }
-
- auto v = json.View();
-
- if (!v.ValueExists("s3bucket") || !v.ValueExists("s3key") || !v.GetObject("s3bucket").IsString() ||
- !v.GetObject("s3key").IsString()) {
- return invocation_response::failure("Missing input value s3bucket or s3key", "InvalidJSON");
- }
-
- auto bucket = v.GetString("s3bucket");
- auto key = v.GetString("s3key");
-
- AWS_LOGSTREAM_INFO(TAG, "Attempting to download file from s3://" << bucket << "/" << key);
-
- Aws::String base64_encoded_file;
- auto err = download_and_encode_file(client, bucket, key, base64_encoded_file);
- if (!err.empty()) {
- return invocation_response::failure(err, "DownloadFailure");
- }
-
- return invocation_response::success(base64_encoded_file, "application/base64");
-}
-
-std::function()> GetConsoleLoggerFactory()
-{
- return [] {
- return Aws::MakeShared(
- "console_logger", Aws::Utils::Logging::LogLevel::Trace);
- };
-}
-
-int main()
-{
- using namespace Aws;
- SDKOptions options;
- options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Trace;
- options.loggingOptions.logger_create_fn = GetConsoleLoggerFactory();
- InitAPI(options);
- {
- Client::ClientConfiguration config;
- config.region = Aws::Environment::GetEnv("AWS_REGION");
- config.caFile = "/etc/pki/tls/certs/ca-bundle.crt";
-
- auto credentialsProvider = Aws::MakeShared(TAG);
- S3::S3Client client(credentialsProvider, config);
- auto handler_fn = [&client](aws::lambda_runtime::invocation_request const& req) {
- return my_handler(req, client);
- };
- run_handler(handler_fn);
- }
- ShutdownAPI(options);
- return 0;
-}
-
-std::string encode(Aws::IOStream& stream, Aws::String& output)
-{
- Aws::Vector bits;
- bits.reserve(stream.tellp());
- stream.seekg(0, stream.beg);
-
- char streamBuffer[1024 * 4];
- while (stream.good()) {
- stream.read(streamBuffer, sizeof(streamBuffer));
- auto bytesRead = stream.gcount();
-
- if (bytesRead > 0) {
- bits.insert(bits.end(), (unsigned char*)streamBuffer, (unsigned char*)streamBuffer + bytesRead);
- }
- }
- Aws::Utils::ByteBuffer bb(bits.data(), bits.size());
- output = Aws::Utils::HashingUtils::Base64Encode(bb);
- return {};
-}
-
-std::string download_and_encode_file(
- Aws::S3::S3Client const& client,
- Aws::String const& bucket,
- Aws::String const& key,
- Aws::String& encoded_output)
-{
- using namespace Aws;
-
- S3::Model::GetObjectRequest request;
- request.WithBucket(bucket).WithKey(key);
-
- auto outcome = client.GetObject(request);
- if (outcome.IsSuccess()) {
- AWS_LOGSTREAM_INFO(TAG, "Download completed!");
- auto& s = outcome.GetResult().GetBody();
- return encode(s, encoded_output);
- }
- else {
- AWS_LOGSTREAM_ERROR(TAG, "Failed with error: " << outcome.GetError());
- return outcome.GetError().GetMessage();
- }
-}
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/http/response.h b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/http/response.h
deleted file mode 100644
index 9b8cbda1f..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/http/response.h
+++ /dev/null
@@ -1,174 +0,0 @@
-#pragma once
-/*
- * Copyright 2018-present Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License").
- * You may not use this file except in compliance with the License.
- * A copy of the License is located at
- *
- * http://aws.amazon.com/apache2.0
- *
- * or in the "license" file accompanying this file. This file is distributed
- * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-#include
-#include
-#include
-#include // tolower
-#include
-
-namespace aws {
-namespace http {
-enum class response_code;
-class response {
-public:
- /**
- * lower-case the name but store the value as is
- */
- inline void add_header(std::string name, std::string const& value);
- inline void append_body(const char* p, size_t sz);
- inline bool has_header(char const* header) const;
- inline std::string const& get_header(char const* header) const;
- inline response_code get_response_code() const { return m_response_code; }
- inline void set_response_code(aws::http::response_code c);
- inline void set_content_type(char const* ct);
- inline std::string const& get_body() const;
-
-private:
- response_code m_response_code;
- using key_value_collection = std::vector>;
- key_value_collection m_headers;
- std::string m_body;
- std::string m_content_type;
-};
-
-enum class response_code {
- REQUEST_NOT_MADE = -1,
- CONTINUE = 100,
- SWITCHING_PROTOCOLS = 101,
- PROCESSING = 102,
- OK = 200,
- CREATED = 201,
- ACCEPTED = 202,
- NON_AUTHORITATIVE_INFORMATION = 203,
- NO_CONTENT = 204,
- RESET_CONTENT = 205,
- PARTIAL_CONTENT = 206,
- MULTI_STATUS = 207,
- ALREADY_REPORTED = 208,
- IM_USED = 226,
- MULTIPLE_CHOICES = 300,
- MOVED_PERMANENTLY = 301,
- FOUND = 302,
- SEE_OTHER = 303,
- NOT_MODIFIED = 304,
- USE_PROXY = 305,
- SWITCH_PROXY = 306,
- TEMPORARY_REDIRECT = 307,
- PERMANENT_REDIRECT = 308,
- BAD_REQUEST = 400,
- UNAUTHORIZED = 401,
- PAYMENT_REQUIRED = 402,
- FORBIDDEN = 403,
- NOT_FOUND = 404,
- METHOD_NOT_ALLOWED = 405,
- NOT_ACCEPTABLE = 406,
- PROXY_AUTHENTICATION_REQUIRED = 407,
- REQUEST_TIMEOUT = 408,
- CONFLICT = 409,
- GONE = 410,
- LENGTH_REQUIRED = 411,
- PRECONDITION_FAILED = 412,
- REQUEST_ENTITY_TOO_LARGE = 413,
- REQUEST_URI_TOO_LONG = 414,
- UNSUPPORTED_MEDIA_TYPE = 415,
- REQUESTED_RANGE_NOT_SATISFIABLE = 416,
- EXPECTATION_FAILED = 417,
- IM_A_TEAPOT = 418,
- AUTHENTICATION_TIMEOUT = 419,
- METHOD_FAILURE = 420,
- UNPROC_ENTITY = 422,
- LOCKED = 423,
- FAILED_DEPENDENCY = 424,
- UPGRADE_REQUIRED = 426,
- PRECONDITION_REQUIRED = 427,
- TOO_MANY_REQUESTS = 429,
- REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
- LOGIN_TIMEOUT = 440,
- NO_RESPONSE = 444,
- RETRY_WITH = 449,
- BLOCKED = 450,
- REDIRECT = 451,
- REQUEST_HEADER_TOO_LARGE = 494,
- CERT_ERROR = 495,
- NO_CERT = 496,
- HTTP_TO_HTTPS = 497,
- CLIENT_CLOSED_TO_REQUEST = 499,
- INTERNAL_SERVER_ERROR = 500,
- NOT_IMPLEMENTED = 501,
- BAD_GATEWAY = 502,
- SERVICE_UNAVAILABLE = 503,
- GATEWAY_TIMEOUT = 504,
- HTTP_VERSION_NOT_SUPPORTED = 505,
- VARIANT_ALSO_NEGOTIATES = 506,
- INSUFFICIENT_STORAGE = 506,
- LOOP_DETECTED = 508,
- BANDWIDTH_LIMIT_EXCEEDED = 509,
- NOT_EXTENDED = 510,
- NETWORK_AUTHENTICATION_REQUIRED = 511,
- NETWORK_READ_TIMEOUT = 598,
- NETWORK_CONNECT_TIMEOUT = 599
-};
-
-inline void response::set_response_code(http::response_code c)
-{
- m_response_code = c;
-}
-
-inline void response::set_content_type(char const* ct)
-{
- m_content_type = ct;
-}
-
-inline std::string const& response::get_body() const
-{
- return m_body;
-}
-inline void response::add_header(std::string name, std::string const& value)
-{
- std::transform(name.begin(), name.end(), name.begin(), ::tolower);
- m_headers.emplace_back(name, value);
-}
-
-inline void response::append_body(const char* p, size_t sz)
-{
- // simple and generates significantly less code than std::stringstream
- constexpr size_t min_capacity = 512;
- if (m_body.capacity() < min_capacity) {
- m_body.reserve(min_capacity);
- }
-
- m_body.append(p, sz);
-}
-
-inline bool response::has_header(char const* header) const
-{
- return std::any_of(m_headers.begin(), m_headers.end(), [header](std::pair const& p) {
- return p.first == header;
- });
-}
-
-inline std::string const& response::get_header(char const* header) const
-{
- auto it = std::find_if(m_headers.begin(), m_headers.end(), [header](std::pair const& p) {
- return p.first == header;
- });
- assert(it != m_headers.end());
- return it->second;
-}
-
-} // namespace http
-} // namespace aws
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/outcome.h b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/outcome.h
deleted file mode 100644
index b5d0b8b0a..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/outcome.h
+++ /dev/null
@@ -1,96 +0,0 @@
-#pragma once
-/*
- * Copyright 2018-present Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License").
- * You may not use this file except in compliance with the License.
- * A copy of the License is located at
- *
- * http://aws.amazon.com/apache2.0
- *
- * or in the "license" file accompanying this file. This file is distributed
- * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-#include
-#include
-
-namespace aws {
-namespace lambda_runtime {
-
-template
-class outcome {
-public:
- outcome(TResult const& s) : m_s(s), m_success(true) {}
- outcome(TResult&& s) : m_s(std::move(s)), m_success(true) {}
-
- outcome(TFailure const& f) : m_f(f), m_success(false) {}
- outcome(TFailure&& f) : m_f(std::move(f)), m_success(false) {}
-
- outcome(outcome const& other) : m_success(other.m_success)
- {
- if (m_success) {
- new (&m_s) TResult(other.m_s);
- }
- else {
- new (&m_f) TFailure(other.m_f);
- }
- }
-
- outcome(outcome&& other) noexcept : m_success(other.m_success)
- {
- if (m_success) {
- new (&m_s) TResult(std::move(other.m_s));
- }
- else {
- new (&m_f) TFailure(std::move(other.m_f));
- }
- }
-
- ~outcome()
- {
- if (m_success) {
- m_s.~TResult();
- }
- else {
- m_f.~TFailure();
- }
- }
-
- TResult const& get_result() const&
- {
- assert(m_success);
- return m_s;
- }
-
- TResult&& get_result() &&
- {
- assert(m_success);
- return std::move(m_s);
- }
-
- TFailure const& get_failure() const&
- {
- assert(!m_success);
- return m_f;
- }
-
- TFailure&& get_failure() &&
- {
- assert(!m_success);
- return std::move(m_f);
- }
-
- bool is_success() const { return m_success; }
-
-private:
- union {
- TResult m_s;
- TFailure m_f;
- };
- bool m_success;
-};
-} // namespace lambda_runtime
-} // namespace aws
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/runtime.h b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/runtime.h
deleted file mode 100644
index 96f90eaa2..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/runtime.h
+++ /dev/null
@@ -1,197 +0,0 @@
-#pragma once
-/*
- * Copyright 2018-present Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License").
- * You may not use this file except in compliance with the License.
- * A copy of the License is located at
- *
- * http://aws.amazon.com/apache2.0
- *
- * or in the "license" file accompanying this file. This file is distributed
- * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include "aws/lambda-runtime/outcome.h"
-#include "aws/http/response.h"
-
-namespace aws {
-namespace lambda_runtime {
-
-struct invocation_request {
- /**
- * The user's payload represented as a UTF-8 string.
- */
- std::string payload;
-
- /**
- * An identifier unique to the current invocation.
- */
- std::string request_id;
-
- /**
- * X-Ray tracing ID of the current invocation.
- */
- std::string xray_trace_id;
-
- /**
- * Information about the client application and device when invoked through the AWS Mobile SDK.
- */
- std::string client_context;
-
- /**
- * Information about the Amazon Cognito identity provider when invoked through the AWS Mobile SDK.
- */
- std::string cognito_identity;
-
- /**
- * The ARN requested. This can be different in each invoke that executes the same version.
- */
- std::string function_arn;
-
- /**
- * Function execution deadline counted in milliseconds since the Unix epoch.
- */
- std::chrono::time_point deadline;
-
- /**
- * Tenant ID of the current invocation.
- */
- std::string tenant_id;
-
- /**
- * Invocation ID for cross-wiring protection.
- */
- std::string invocation_id;
-
- /**
- * The number of milliseconds left before lambda terminates the current execution.
- */
- inline std::chrono::milliseconds get_time_remaining() const;
-};
-
-class invocation_response {
-private:
- /**
- * The output of the function which is sent to the lambda caller.
- */
- std::string m_payload;
-
- /**
- * The MIME type of the payload.
- * This is always set to 'application/json' in unsuccessful invocations.
- */
- std::string m_content_type;
-
- /**
- * Flag to distinguish if the contents are for successful or unsuccessful invocations.
- */
- bool m_success;
-
- /**
- * Instantiate an empty response. Used by the static functions 'success' and 'failure' to create a populated
- * invocation_response
- */
- invocation_response() = default;
-
-public:
- // Create a success or failure response. Typically, you should use the static functions invocation_response::success
- // and invocation_response::failure, however, invocation_response::failure doesn't allow for arbitrary payloads.
- // To support clients that need to control the entire error response body (e.g. adding a stack trace), this
- // constructor should be used instead.
- // Note: adding an overload to invocation_response::failure is not feasible since the parameter types are the same.
- invocation_response(std::string const& payload, std::string const& content_type, bool success)
- : m_payload(payload), m_content_type(content_type), m_success(success)
- {
- }
-
- /**
- * Create a successful invocation response with the given payload and content-type.
- */
- static invocation_response success(std::string const& payload, std::string const& content_type);
-
- /**
- * Create a failure response with the given error message and error type.
- * The content-type is always set to application/json in this case.
- */
- static invocation_response failure(std::string const& error_message, std::string const& error_type);
-
- /**
- * Get the MIME type of the payload.
- */
- std::string const& get_content_type() const { return m_content_type; }
-
- /**
- * Get the payload string. The string is assumed to be UTF-8 encoded.
- */
- std::string const& get_payload() const { return m_payload; }
-
- /**
- * Returns true if the payload and content-type are set. Returns false if the error message and error types are set.
- */
- bool is_success() const { return m_success; }
-};
-
-struct no_result {
-};
-
-class runtime {
-public:
- using next_outcome = aws::lambda_runtime::outcome;
- using post_outcome = aws::lambda_runtime::outcome;
-
- runtime(std::string const& endpoint, std::string const& user_agent);
- runtime(std::string const& endpoint);
- ~runtime();
-
- /**
- * Ask lambda for an invocation.
- */
- next_outcome get_next();
-
- /**
- * Tells lambda that the function has succeeded.
- */
- post_outcome post_success(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id);
-
- post_outcome post_success(std::string const& request_id, invocation_response const& handler_response);
-
- /**
- * Tells lambda that the function has failed.
- */
- post_outcome post_failure(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id);
-
- post_outcome post_failure(std::string const& request_id, invocation_response const& handler_response);
-
-private:
- void set_curl_next_options();
- void set_curl_post_result_options();
- post_outcome do_post(
- std::string const& url,
- std::string const& request_id,
- invocation_response const& handler_response,
- std::string const& invocation_id);
-
-private:
- std::string const m_user_agent_header;
- std::array const m_endpoints;
-};
-
-inline std::chrono::milliseconds invocation_request::get_time_remaining() const
-{
- using namespace std::chrono;
- return duration_cast(deadline - system_clock::now());
-}
-
-// Entry method
-void run_handler(std::function const& handler);
-
-} // namespace lambda_runtime
-} // namespace aws
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/version.h b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/version.h
deleted file mode 100644
index eafcbde76..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/version.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#pragma once
-/*
- * Copyright 2018-present Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License").
- * You may not use this file except in compliance with the License.
- * A copy of the License is located at
- *
- * http://aws.amazon.com/apache2.0
- *
- * or in the "license" file accompanying this file. This file is distributed
- * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-namespace aws {
-namespace lambda_runtime {
-
-/**
- * Returns the major component of the library version.
- */
-unsigned get_version_major();
-
-/**
- * Returns the minor component of the library version.
- */
-unsigned get_version_minor();
-
-/**
- * Returns the patch component of the library version.
- */
-unsigned get_version_patch();
-
-/**
- * Returns the semantic version of the library in the form Major.Minor.Patch
- */
-char const* get_version();
-
-} // namespace lambda_runtime
-} // namespace aws
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/logging/logging.h b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/logging/logging.h
deleted file mode 100644
index 0b5d0ef96..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/logging/logging.h
+++ /dev/null
@@ -1,67 +0,0 @@
-#pragma once
-/*
- * Copyright 2018-present Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License").
- * You may not use this file except in compliance with the License.
- * A copy of the License is located at
- *
- * http://aws.amazon.com/apache2.0
- *
- * or in the "license" file accompanying this file. This file is distributed
- * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-#include
-
-namespace aws {
-namespace logging {
-
-enum class verbosity {
- error,
- info,
- debug,
-};
-
-void log(verbosity v, char const* tag, char const* msg, va_list args);
-
-[[gnu::format(printf, 2, 3)]] inline void log_error(char const* tag, char const* msg, ...)
-{
- va_list args;
- va_start(args, msg);
- log(verbosity::error, tag, msg, args);
- va_end(args);
- (void)tag;
- (void)msg;
-}
-
-[[gnu::format(printf, 2, 3)]] inline void log_info(char const* tag, char const* msg, ...)
-{
-#if AWS_LAMBDA_LOG >= 1
- va_list args;
- va_start(args, msg);
- log(verbosity::info, tag, msg, args);
- va_end(args);
-#else
- (void)tag;
- (void)msg;
-#endif
-}
-
-[[gnu::format(printf, 2, 3)]] inline void log_debug(char const* tag, char const* msg, ...)
-{
-#if AWS_LAMBDA_LOG >= 2
- va_list args;
- va_start(args, msg);
- log(verbosity::debug, tag, msg, args);
- va_end(args);
-#else
- (void)tag;
- (void)msg;
-#endif
-}
-
-} // namespace logging
-} // namespace aws
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/packaging/packager b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/packaging/packager
deleted file mode 100755
index d33389166..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/packaging/packager
+++ /dev/null
@@ -1,180 +0,0 @@
-#!/bin/bash
-# Copyright 2018-present Amazon.com, Inc. or its affiliates. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License").
-# You may not use this file except in compliance with the License.
-# A copy of the License is located at
-#
-# http://aws.amazon.com/apache2.0
-#
-# or in the "license" file accompanying this file. This file is distributed
-# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
-# express or implied. See the License for the specific language governing
-# permissions and limitations under the License.
-
-set -euo pipefail
-
-print_help() {
- echo -e "Usage: packager [OPTIONS] \n"
- echo -e "OPTIONS\n"
- echo -e "\t-d,--default-libc\t Use the target host libc libraries. This will not package the C library files.\n"
-}
-
-if [ $# -lt 1 ]; then
- echo -e "Error: missing arguments\n"
- print_help
- exit 1
-fi
-
-POSITIONAL=()
-INCLUDE_LIBC=true
-while [[ $# -gt 0 ]]
-do
- key="$1"
- case $key in
- -d|--default-libc)
- INCLUDE_LIBC=false
- shift # past argument
- ;;
- *) # unknown option
- POSITIONAL+=("$1") # save it in an array for later
- shift # past argument
- ;;
- esac
-done
-set -- "${POSITIONAL[@]}" # restore positional parameters
-
-PKG_BIN_PATH=$1
-
-if [ ! -f "$PKG_BIN_PATH" ]; then
- echo "$PKG_BIN_PATH" - No such file.;
- exit 1;
-fi
-
-if ! type zip > /dev/null 2>&1; then
- echo "zip utility is not found. Please install it and re-run this script"
- exit 1
-fi
-function package_libc_via_pacman {
- if grep --extended-regexp "Arch Linux|Manjaro Linux" < /etc/os-release > /dev/null 2>&1; then
- if type pacman > /dev/null 2>&1; then
- pacman --query --list --quiet glibc | sed -E '/\.so$|\.so\.[0-9]+$/!d'
- fi
- fi
-}
-
-function package_libc_via_dpkg() {
- if type dpkg-query > /dev/null 2>&1; then
- if [[ $(dpkg-query --listfiles libc6 | wc -l) -gt 0 ]]; then
- dpkg-query --listfiles libc6 | sed -E '/\.so$|\.so\.[0-9]+$/!d'
- fi
- fi
-}
-
-function package_libc_via_rpm() {
- if type rpm > /dev/null 2>&1; then
- if [[ $(rpm --query --list glibc.x86_64 | wc -l) -gt 1 ]]; then
- rpm --query --list glibc.x86_64 | sed -E '/\.so$|\.so\.[0-9]+$/!d'
- fi
- fi
-}
-
-# hasElement expects an element and an array parameter
-# it's equivalent to array.contains(element)
-# e.g. hasElement "needle" ${haystack[@]}
-function hasElement() {
- local el key=$1
- shift
- for el in "$@"
- do
- [[ "$el" == "$key" ]] && return 0
- done
- return 1
-}
-
-PKG_BIN_FILENAME=$(basename "$PKG_BIN_PATH")
-PKG_DIR=tmp
-PKG_LD=""
-
-list=$(ldd "$PKG_BIN_PATH" | awk '{print $(NF-1)}')
-libc_libs=()
-libc_libs+=($(package_libc_via_dpkg))
-libc_libs+=($(package_libc_via_rpm))
-libc_libs+=($(package_libc_via_pacman))
-
-mkdir -p "$PKG_DIR/bin" "$PKG_DIR/lib"
-
-for i in $list
-do
- if [[ ! -f $i ]]; then # ignore linux-vdso.so.1
- continue
- fi
-
- # Do not copy libc files which are directly linked unless it's the dynamic loader
- if hasElement "$i" "${libc_libs[@]}"; then
- filename=$(basename "$i")
- if [[ -z "${filename##ld-*}" ]]; then
- PKG_LD=$filename # Use this file as the loader
- cp "$i" "$PKG_DIR/lib"
- fi
- continue
- fi
-
- cp "$i" $PKG_DIR/lib
-done
-
-if [[ $INCLUDE_LIBC == true ]]; then
- for i in "${libc_libs[@]}"
- do
- filename=$(basename "$i")
- if [[ -z "${filename##ld-*}" ]]; then
- # if the loader is empty, then the binary is probably linked to a symlink of the loader. The symlink will
- # not show up when quering the package manager for libc files. So, in this case, we want to copy the loader
- if [[ -z "$PKG_LD" ]]; then
- PKG_LD=$filename
- cp "$i" "$PKG_DIR/lib" # we want to follow the symlink (default behavior)
- fi
- continue # We don't want the dynamic loader's symlink because its target is an absolute path (/lib/ld-*).
- fi
- cp --no-dereference "$i" "$PKG_DIR/lib"
- done
-fi
-
-if [[ -z "$PKG_LD" ]]; then
- echo "Failed to identify, locate or package the loader. Please file an issue on Github!" 1>&2
- exit 1
-fi
-
-bootstrap_script=$(cat < "$PKG_DIR/bootstrap"
-else
- echo -e "$bootstrap_script_no_libc" > "$PKG_DIR/bootstrap"
-fi
-chmod +x "$PKG_DIR/bootstrap"
-# some shenanigans to create the right layout in the zip file without extraneous directories
-pushd "$PKG_DIR" > /dev/null
-zip --symlinks --recurse-paths "$PKG_BIN_FILENAME".zip -- *
-ORIGIN_DIR=$(dirs -l +1)
-mv "$PKG_BIN_FILENAME".zip "$ORIGIN_DIR"
-popd > /dev/null
-rm -r "$PKG_DIR"
-echo Created "$ORIGIN_DIR/$PKG_BIN_FILENAME".zip
-
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/backward.cpp b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/backward.cpp
deleted file mode 100644
index cc64abdbc..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/backward.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-// Pick your poison.
-//
-// On GNU/Linux, you have few choices to get the most out of your stack trace.
-//
-// By default you get:
-// - object filename
-// - function name
-//
-// In order to add:
-// - source filename
-// - line and column numbers
-// - source code snippet (assuming the file is accessible)
-
-// Install one of the following library then uncomment one of the macro (or
-// better, add the detection of the lib and the macro definition in your build
-// system)
-
-// - apt-get install libdw-dev ...
-// - g++/clang++ -ldw ...
-// #define BACKWARD_HAS_DW 1
-
-// - apt-get install binutils-dev ...
-// - g++/clang++ -lbfd ...
-// #define BACKWARD_HAS_BFD 1
-
-#include "backward.h"
-
-namespace backward {
-
-backward::SignalHandling sh;
-
-} // namespace backward
diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/backward.h b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/backward.h
deleted file mode 100644
index e9e56c798..000000000
--- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/backward.h
+++ /dev/null
@@ -1,4291 +0,0 @@
-// clang-format off
-/*
- * backward.hpp
- * Copyright 2013 Google Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef H_6B9572DA_A64B_49E6_B234_051480991C89
-#define H_6B9572DA_A64B_49E6_B234_051480991C89
-
-#ifndef __cplusplus
-# error "It's not going to compile without a C++ compiler..."
-#endif
-
-#if defined(BACKWARD_CXX11)
-#elif defined(BACKWARD_CXX98)
-#else
-# if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
-# define BACKWARD_CXX11
-# define BACKWARD_ATLEAST_CXX11
-# define BACKWARD_ATLEAST_CXX98
-# else
-# define BACKWARD_CXX98
-# define BACKWARD_ATLEAST_CXX98
-# endif
-#endif
-
-// You can define one of the following (or leave it to the auto-detection):
-//
-// #define BACKWARD_SYSTEM_LINUX
-// - specialization for linux
-//
-// #define BACKWARD_SYSTEM_DARWIN
-// - specialization for Mac OS X 10.5 and later.
-//
-// #define BACKWARD_SYSTEM_UNKNOWN
-// - placebo implementation, does nothing.
-//
-#if defined(BACKWARD_SYSTEM_LINUX)
-#elif defined(BACKWARD_SYSTEM_DARWIN)
-#elif defined(BACKWARD_SYSTEM_UNKNOWN)
-#elif defined(BACKWARD_SYSTEM_WINDOWS)
-#else
-# if defined(__linux) || defined(__linux__)
-# define BACKWARD_SYSTEM_LINUX
-# elif defined(__APPLE__)
-# define BACKWARD_SYSTEM_DARWIN
-# elif defined(_WIN32)
-# define BACKWARD_SYSTEM_WINDOWS
-# else
-# define BACKWARD_SYSTEM_UNKNOWN
-# endif
-#endif
-
-#define NOINLINE __attribute__((noinline))
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#if defined(BACKWARD_SYSTEM_LINUX)
-
-// On linux, backtrace can back-trace or "walk" the stack using the following
-// libraries:
-//
-// #define BACKWARD_HAS_UNWIND 1
-// - unwind comes from libgcc, but I saw an equivalent inside clang itself.
-// - with unwind, the stacktrace is as accurate as it can possibly be, since
-// this is used by the C++ runtine in gcc/clang for stack unwinding on
-// exception.
-// - normally libgcc is already linked to your program by default.
-//
-// #define BACKWARD_HAS_BACKTRACE == 1
-// - backtrace seems to be a little bit more portable than libunwind, but on
-// linux, it uses unwind anyway, but abstract away a tiny information that is
-// sadly really important in order to get perfectly accurate stack traces.
-// - backtrace is part of the (e)glib library.
-//
-// The default is:
-// #define BACKWARD_HAS_UNWIND == 1
-//
-// Note that only one of the define should be set to 1 at a time.
-//
-# if BACKWARD_HAS_UNWIND == 1
-# elif BACKWARD_HAS_BACKTRACE == 1
-# else
-# undef BACKWARD_HAS_UNWIND
-# define BACKWARD_HAS_UNWIND 1
-# undef BACKWARD_HAS_BACKTRACE
-# define BACKWARD_HAS_BACKTRACE 0
-# endif
-
-// On linux, backward can extract detailed information about a stack trace
-// using one of the following libraries:
-//
-// #define BACKWARD_HAS_DW 1
-// - libdw gives you the most juicy details out of your stack traces:
-// - object filename
-// - function name
-// - source filename
-// - line and column numbers
-// - source code snippet (assuming the file is accessible)
-// - variables name and values (if not optimized out)
-// - You need to link with the lib "dw":
-// - apt-get install libdw-dev
-// - g++/clang++ -ldw ...
-//
-// #define BACKWARD_HAS_BFD 1
-// - With libbfd, you get a fair amount of details:
-// - object filename
-// - function name
-// - source filename
-// - line numbers
-// - source code snippet (assuming the file is accessible)
-// - You need to link with the lib "bfd":
-// - apt-get install binutils-dev
-// - g++/clang++ -lbfd ...
-//
-// #define BACKWARD_HAS_DWARF 1
-// - libdwarf gives you the most juicy details out of your stack traces:
-// - object filename
-// - function name
-// - source filename
-// - line and column numbers
-// - source code snippet (assuming the file is accessible)
-// - variables name and values (if not optimized out)
-// - You need to link with the lib "dwarf":
-// - apt-get install libdwarf-dev
-// - g++/clang++ -ldwarf ...
-//
-// #define BACKWARD_HAS_BACKTRACE_SYMBOL 1
-// - backtrace provides minimal details for a stack trace:
-// - object filename
-// - function name
-// - backtrace is part of the (e)glib library.
-//
-// The default is:
-// #define BACKWARD_HAS_BACKTRACE_SYMBOL == 1
-//
-// Note that only one of the define should be set to 1 at a time.
-//
-# if BACKWARD_HAS_DW == 1
-# elif BACKWARD_HAS_BFD == 1
-# elif BACKWARD_HAS_DWARF == 1
-# elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1
-# else
-# undef BACKWARD_HAS_DW
-# define BACKWARD_HAS_DW 0
-# undef BACKWARD_HAS_BFD
-# define BACKWARD_HAS_BFD 0
-# undef BACKWARD_HAS_DWARF
-# define BACKWARD_HAS_DWARF 0
-# undef BACKWARD_HAS_BACKTRACE_SYMBOL
-# define BACKWARD_HAS_BACKTRACE_SYMBOL 1
-# endif
-
-# include
-# include
-# ifdef __ANDROID__
-// Old Android API levels define _Unwind_Ptr in both link.h and
-// unwind.h Rename the one in link.h as we are not going to be using
-// it
-# define _Unwind_Ptr _Unwind_Ptr_Custom
-# include
-# undef _Unwind_Ptr
-# else
-# include
-# endif
-# include
-# include
-# include
-# include
-
-# if BACKWARD_HAS_BFD == 1
-// NOTE: defining PACKAGE{,_VERSION} is required before including
-// bfd.h on some platforms, see also:
-// https://sourceware.org/bugzilla/show_bug.cgi?id=14243
-# ifndef PACKAGE
-# define PACKAGE
-# endif
-# ifndef PACKAGE_VERSION
-# define PACKAGE_VERSION
-# endif
-# include
-# ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-# include
-# undef _GNU_SOURCE
-# else
-# include
-# endif
-# endif
-
-# if BACKWARD_HAS_DW == 1
-# include
-# include
-# include
-# endif
-
-# if BACKWARD_HAS_DWARF == 1
-# include
-# include
-# include
-# include
-# include
-# ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-# include
-# undef _GNU_SOURCE
-# else
-# include
-# endif
-# endif
-
-# if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1)
-// then we shall rely on backtrace
-# include
-# endif
-
-#endif // defined(BACKWARD_SYSTEM_LINUX)
-
-#if defined(BACKWARD_SYSTEM_DARWIN)
-// On Darwin, backtrace can back-trace or "walk" the stack using the following
-// libraries:
-//
-// #define BACKWARD_HAS_UNWIND 1
-// - unwind comes from libgcc, but I saw an equivalent inside clang itself.
-// - with unwind, the stacktrace is as accurate as it can possibly be, since
-// this is used by the C++ runtine in gcc/clang for stack unwinding on
-// exception.
-// - normally libgcc is already linked to your program by default.
-//
-// #define BACKWARD_HAS_BACKTRACE == 1
-// - backtrace is available by default, though it does not produce as much
-// information as another library might.
-//
-// The default is:
-// #define BACKWARD_HAS_UNWIND == 1
-//
-// Note that only one of the define should be set to 1 at a time.
-//
-# if BACKWARD_HAS_UNWIND == 1
-# elif BACKWARD_HAS_BACKTRACE == 1
-# else
-# undef BACKWARD_HAS_UNWIND
-# define BACKWARD_HAS_UNWIND 1
-# undef BACKWARD_HAS_BACKTRACE
-# define BACKWARD_HAS_BACKTRACE 0
-# endif
-
-// On Darwin, backward can extract detailed information about a stack trace
-// using one of the following libraries:
-//
-// #define BACKWARD_HAS_BACKTRACE_SYMBOL 1
-// - backtrace provides minimal details for a stack trace:
-// - object filename
-// - function name
-//
-// The default is:
-// #define BACKWARD_HAS_BACKTRACE_SYMBOL == 1
-//
-# if BACKWARD_HAS_BACKTRACE_SYMBOL == 1
-# else
-# undef BACKWARD_HAS_BACKTRACE_SYMBOL
-# define BACKWARD_HAS_BACKTRACE_SYMBOL 1
-# endif
-
-# include
-# include
-# include
-# include
-# include
-# include
-
-# if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1)
-# include
-# endif
-#endif // defined(BACKWARD_SYSTEM_DARWIN)
-
-#if defined(BACKWARD_SYSTEM_WINDOWS)
-
-# include
-# include
-# include
-
-# include
-typedef SSIZE_T ssize_t;
-
-# define NOMINMAX
-# include
-# include
-
-# include
-# include
-
-# ifndef __clang__
-# undef NOINLINE
-# define NOINLINE __declspec(noinline)
-# endif
-
-# pragma comment(lib, "psapi.lib")
-# pragma comment(lib, "dbghelp.lib")
-
-// Comment / packing is from stackoverflow:
-// https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app/28276227#28276227
-// Some versions of imagehlp.dll lack the proper packing directives themselves
-// so we need to do it.
-# pragma pack(push, before_imagehlp, 8)
-# include
-# pragma pack(pop, before_imagehlp)
-
-// TODO maybe these should be undefined somewhere else?
-# undef BACKWARD_HAS_UNWIND
-# undef BACKWARD_HAS_BACKTRACE
-# if BACKWARD_HAS_PDB_SYMBOL == 1
-# else
-# undef BACKWARD_HAS_PDB_SYMBOL
-# define BACKWARD_HAS_PDB_SYMBOL 1
-# endif
-
-#endif
-
-#if BACKWARD_HAS_UNWIND == 1
-
-# include
-// while gcc's unwind.h defines something like that:
-// extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *);
-// extern _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
-//
-// clang's unwind.h defines something like this:
-// uintptr_t _Unwind_GetIP(struct _Unwind_Context* __context);
-//
-// Even if the _Unwind_GetIPInfo can be linked to, it is not declared, worse we
-// cannot just redeclare it because clang's unwind.h doesn't define _Unwind_Ptr
-// anyway.
-//
-// Luckily we can play on the fact that the guard macros have a different name:
-# ifdef __CLANG_UNWIND_H
-// In fact, this function still comes from libgcc (on my different linux boxes,
-// clang links against libgcc).
-# include
-extern "C" uintptr_t _Unwind_GetIPInfo(_Unwind_Context*, int*);
-# endif
-
-#endif // BACKWARD_HAS_UNWIND == 1
-
-#ifdef BACKWARD_ATLEAST_CXX11
-# include
-# include // for std::swap
-namespace backward {
-namespace details {
-template
-struct hashtable {
- typedef std::unordered_map type;
-};
-using std::move;
-} // namespace details
-} // namespace backward
-#else // NOT BACKWARD_ATLEAST_CXX11
-# define nullptr NULL
-# define override
-# include
-namespace backward {
-namespace details {
-template
-struct hashtable {
- typedef std::map type;
-};
-template
-const T& move(const T& v)
-{
- return v;
-}
-template
-T& move(T& v)
-{
- return v;
-}
-} // namespace details
-} // namespace backward
-#endif // BACKWARD_ATLEAST_CXX11
-
-namespace backward {
-namespace details {
-#if defined(BACKWARD_SYSTEM_WINDOWS)
-const char kBackwardPathDelimiter[] = ";";
-#else
-const char kBackwardPathDelimiter[] = ":";
-#endif
-} // namespace details
-} // namespace backward
-
-namespace backward {
-
-namespace system_tag {
-struct linux_tag; // seems that I cannot call that "linux" because the name
-// is already defined... so I am adding _tag everywhere.
-struct darwin_tag;
-struct windows_tag;
-struct unknown_tag;
-
-#if defined(BACKWARD_SYSTEM_LINUX)
-typedef linux_tag current_tag;
-#elif defined(BACKWARD_SYSTEM_DARWIN)
-typedef darwin_tag current_tag;
-#elif defined(BACKWARD_SYSTEM_WINDOWS)
-typedef windows_tag current_tag;
-#elif defined(BACKWARD_SYSTEM_UNKNOWN)
-typedef unknown_tag current_tag;
-#else
-# error "May I please get my system defines?"
-#endif
-} // namespace system_tag
-
-namespace trace_resolver_tag {
-#if defined(BACKWARD_SYSTEM_LINUX)
-struct libdw;
-struct libbfd;
-struct libdwarf;
-struct backtrace_symbol;
-
-# if BACKWARD_HAS_DW == 1
-typedef libdw current;
-# elif BACKWARD_HAS_BFD == 1
-typedef libbfd current;
-# elif BACKWARD_HAS_DWARF == 1
-typedef libdwarf current;
-# elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1
-typedef backtrace_symbol current;
-# else
-# error "You shall not pass, until you know what you want."
-# endif
-#elif defined(BACKWARD_SYSTEM_DARWIN)
-struct backtrace_symbol;
-
-# if BACKWARD_HAS_BACKTRACE_SYMBOL == 1
-typedef backtrace_symbol current;
-# else
-# error "You shall not pass, until you know what you want."
-# endif
-#elif defined(BACKWARD_SYSTEM_WINDOWS)
-struct pdb_symbol;
-# if BACKWARD_HAS_PDB_SYMBOL == 1
-typedef pdb_symbol current;
-# else
-# error "You shall not pass, until you know what you want."
-# endif
-#endif
-} // namespace trace_resolver_tag
-
-namespace details {
-
-template
-struct rm_ptr {
- typedef T type;
-};
-
-template
-struct rm_ptr {
- typedef T type;
-};
-
-template
-struct rm_ptr {
- typedef const T type;
-};
-
-template
-struct deleter {
- template
- void operator()(U& ptr) const
- {
- (*F)(ptr);
- }
-};
-
-template
-struct default_delete {
- void operator()(T& ptr) const { delete ptr; }
-};
-
-template >
-class handle {
- struct dummy;
- T _val;
- bool _empty;
-
-#ifdef BACKWARD_ATLEAST_CXX11
- handle(const handle&) = delete;
- handle& operator=(const handle&) = delete;
-#endif
-
-public:
- ~handle()
- {
- if (!_empty) {
- Deleter()(_val);
- }
- }
-
- explicit handle() : _val(), _empty(true) {}
- explicit handle(T val) : _val(val), _empty(false)
- {
- if (!_val)
- _empty = true;
- }
-
-#ifdef BACKWARD_ATLEAST_CXX11
- handle(handle&& from) : _empty(true) { swap(from); }
- handle& operator=(handle&& from)
- {
- swap(from);
- return *this;
- }
-#else
- explicit handle(const handle& from) : _empty(true)
- {
- // some sort of poor man's move semantic.
- swap(const_cast(from));
- }
- handle& operator=(const handle& from)
- {
- // some sort of poor man's move semantic.
- swap(const_cast(from));
- return *this;
- }
-#endif
-
- void reset(T new_val)
- {
- handle tmp(new_val);
- swap(tmp);
- }
-
- void update(T new_val)
- {
- _val = new_val;
- _empty = static_cast(new_val);
- }
-
- operator const dummy*() const
- {
- if (_empty) {
- return nullptr;
- }
- return reinterpret_cast(_val);
- }
- T get() { return _val; }
- T release()
- {
- _empty = true;
- return _val;
- }
- void swap(handle& b)
- {
- using std::swap;
- swap(b._val, _val); // can throw, we are safe here.
- swap(b._empty, _empty); // should not throw: if you cannot swap two
- // bools without throwing... It's a lost cause anyway!
- }
-
- T& operator->() { return _val; }
- const T& operator->() const { return _val; }
-
- typedef typename rm_ptr::type& ref_t;
- typedef const typename rm_ptr::type& const_ref_t;
- ref_t operator*() { return *_val; }
- const_ref_t operator*() const { return *_val; }
- ref_t operator[](size_t idx) { return _val[idx]; }
-
- // Watch out, we've got a badass over here
- T* operator&()
- {
- _empty = false;
- return &_val;
- }
-};
-
-// Default demangler implementation (do nothing).
-template
-struct demangler_impl {
- static std::string demangle(const char* funcname) { return funcname; }
-};
-
-#if defined(BACKWARD_SYSTEM_LINUX) || defined(BACKWARD_SYSTEM_DARWIN)
-
-template <>
-struct demangler_impl {
- demangler_impl() : _demangle_buffer_length(0) {}
-
- std::string demangle(const char* funcname)
- {
- using namespace details;
- char* result = abi::__cxa_demangle(funcname, _demangle_buffer.get(), &_demangle_buffer_length, nullptr);
- if (result) {
- _demangle_buffer.update(result);
- return result;
- }
- return funcname;
- }
-
-private:
- details::handle _demangle_buffer;
- size_t _demangle_buffer_length;
-};
-
-#endif // BACKWARD_SYSTEM_LINUX || BACKWARD_SYSTEM_DARWIN
-
-struct demangler : public demangler_impl {
-};
-
-// Split a string on the platform's PATH delimiter. Example: if delimiter
-// is ":" then:
-// "" --> []
-// ":" --> ["",""]
-// "::" --> ["","",""]
-// "/a/b/c" --> ["/a/b/c"]
-// "/a/b/c:/d/e/f" --> ["/a/b/c","/d/e/f"]
-// etc.
-inline std::vector split_source_prefixes(const std::string& s)
-{
- std::vector out;
- size_t last = 0;
- size_t next = 0;
- size_t delimiter_size = sizeof(kBackwardPathDelimiter) - 1;
- while ((next = s.find(kBackwardPathDelimiter, last)) != std::string::npos) {
- out.push_back(s.substr(last, next - last));
- last = next + delimiter_size;
- }
- if (last <= s.length()) {
- out.push_back(s.substr(last));
- }
- return out;
-}
-
-} // namespace details
-
-/*************** A TRACE ***************/
-
-struct Trace {
- void* addr;
- size_t idx;
-
- Trace() : addr(nullptr), idx(0) {}
-
- explicit Trace(void* _addr, size_t _idx) : addr(_addr), idx(_idx) {}
-};
-
-struct ResolvedTrace : public Trace {
-
- struct SourceLoc {
- std::string function;
- std::string filename;
- unsigned line;
- unsigned col;
-
- SourceLoc() : line(0), col(0) {}
-
- bool operator==(const SourceLoc& b) const
- {
- return function == b.function && filename == b.filename && line == b.line && col == b.col;
- }
-
- bool operator!=(const SourceLoc& b) const { return !(*this == b); }
- };
-
- // In which binary object this trace is located.
- std::string object_filename;
-
- // The function in the object that contain the trace. This is not the same
- // as source.function which can be an function inlined in object_function.
- std::string object_function;
-
- // The source location of this trace. It is possible for filename to be
- // empty and for line/col to be invalid (value 0) if this information
- // couldn't be deduced, for example if there is no debug information in the
- // binary object.
- SourceLoc source;
-
- // An optionals list of "inliners". All the successive sources location
- // from where the source location of the trace (the attribute right above)
- // is inlined. It is especially useful when you compiled with optimization.
- typedef std::vector source_locs_t;
- source_locs_t inliners;
-
- ResolvedTrace() : Trace() {}
- ResolvedTrace(const Trace& mini_trace) : Trace(mini_trace) {}
-};
-
-/*************** STACK TRACE ***************/
-
-// default implemention.
-template
-class StackTraceImpl {
-public:
- size_t size() const { return 0; }
- Trace operator[](size_t) const { return Trace(); }
- size_t load_here(size_t = 0) { return 0; }
- size_t load_from(void*, size_t = 0) { return 0; }
- size_t thread_id() const { return 0; }
- void skip_n_firsts(size_t) {}
-};
-
-class StackTraceImplBase {
-public:
- StackTraceImplBase() : _thread_id(0), _skip(0) {}
-
- size_t thread_id() const { return _thread_id; }
-
- void skip_n_firsts(size_t n) { _skip = n; }
-
-protected:
- void load_thread_info()
- {
-#ifdef BACKWARD_SYSTEM_LINUX
-# ifndef __ANDROID__
- _thread_id = static_cast(syscall(SYS_gettid));
-# else
- _thread_id = static_cast(gettid());
-# endif
- if (_thread_id == static_cast(getpid())) {
- // If the thread is the main one, let's hide that.
- // I like to keep little secret sometimes.
- _thread_id = 0;
- }
-#elif defined(BACKWARD_SYSTEM_DARWIN)
- _thread_id = reinterpret_cast(pthread_self());
- if (pthread_main_np() == 1) {
- // If the thread is the main one, let's hide that.
- _thread_id = 0;
- }
-#endif
- }
-
- size_t skip_n_firsts() const { return _skip; }
-
-private:
- size_t _thread_id;
- size_t _skip;
-};
-
-class StackTraceImplHolder : public StackTraceImplBase {
-public:
- size_t size() const { return _stacktrace.size() ? _stacktrace.size() - skip_n_firsts() : 0; }
- Trace operator[](size_t idx) const
- {
- if (idx >= size()) {
- return Trace();
- }
- return Trace(_stacktrace[idx + skip_n_firsts()], idx);
- }
- void* const* begin() const
- {
- if (size()) {
- return &_stacktrace[skip_n_firsts()];
- }
- return nullptr;
- }
-
-protected:
- std::vector _stacktrace;
-};
-
-#if BACKWARD_HAS_UNWIND == 1
-
-namespace details {
-
-template
-class Unwinder {
-public:
- size_t operator()(F& f, size_t depth)
- {
- _f = &f;
- _index = -1;
- _depth = depth;
- _Unwind_Backtrace(&this->backtrace_trampoline, this);
- return static_cast(_index);
- }
-
-private:
- F* _f;
- ssize_t _index;
- size_t _depth;
-
- static _Unwind_Reason_Code backtrace_trampoline(_Unwind_Context* ctx, void* self)
- {
- return (static_cast(self))->backtrace(ctx);
- }
-
- _Unwind_Reason_Code backtrace(_Unwind_Context* ctx)
- {
- if (_index >= 0 && static_cast(_index) >= _depth)
- return _URC_END_OF_STACK;
-
- int ip_before_instruction = 0;
- uintptr_t ip = _Unwind_GetIPInfo(ctx, &ip_before_instruction);
-
- if (!ip_before_instruction) {
- // calculating 0-1 for unsigned, looks like a possible bug to sanitiziers,
- // so let's do it explicitly:
- if (ip == 0) {
- ip = std::numeric_limits::max(); // set it to 0xffff... (as
- // from casting 0-1)
- }
- else {
- ip -= 1; // else just normally decrement it (no overflow/underflow will
- // happen)
- }
- }
-
- if (_index >= 0) { // ignore first frame.
- (*_f)(static_cast(_index), reinterpret_cast(ip));
- }
- _index += 1;
- return _URC_NO_REASON;
- }
-};
-
-template
-size_t unwind(F f, size_t depth)
-{
- Unwinder unwinder;
- return unwinder(f, depth);
-}
-
-} // namespace details
-
-template <>
-class StackTraceImpl : public StackTraceImplHolder {
-public:
- NOINLINE
- size_t load_here(size_t depth = 32)
- {
- load_thread_info();
- if (depth == 0) {
- return 0;
- }
- _stacktrace.resize(depth);
- size_t trace_cnt = details::unwind(callback(*this), depth);
- _stacktrace.resize(trace_cnt);
- skip_n_firsts(0);
- return size();
- }
- size_t load_from(void* addr, size_t depth = 32)
- {
- load_here(depth + 8);
-
- for (size_t i = 0; i < _stacktrace.size(); ++i) {
- if (_stacktrace[i] == addr) {
- skip_n_firsts(i);
- break;
- }
- }
-
- _stacktrace.resize(std::min(_stacktrace.size(), skip_n_firsts() + depth));
- return size();
- }
-
-private:
- struct callback {
- StackTraceImpl& self;
- callback(StackTraceImpl& _self) : self(_self) {}
-
- void operator()(size_t idx, void* addr) { self._stacktrace[idx] = addr; }
- };
-};
-
-#elif defined(BACKWARD_HAS_BACKTRACE)
-
-template <>
-class StackTraceImpl : public StackTraceImplHolder {
-public:
- NOINLINE
- size_t load_here(size_t depth = 32)
- {
- load_thread_info();
- if (depth == 0) {
- return 0;
- }
- _stacktrace.resize(depth + 1);
- size_t trace_cnt = backtrace(&_stacktrace[0], _stacktrace.size());
- _stacktrace.resize(trace_cnt);
- skip_n_firsts(1);
- return size();
- }
-
- size_t load_from(void* addr, size_t depth = 32)
- {
- load_here(depth + 8);
-
- for (size_t i = 0; i < _stacktrace.size(); ++i) {
- if (_stacktrace[i] == addr) {
- skip_n_firsts(i);
- _stacktrace[i] = (void*)((uintptr_t)_stacktrace[i] + 1);
- break;
- }
- }
-
- _stacktrace.resize(std::min(_stacktrace.size(), skip_n_firsts() + depth));
- return size();
- }
-};
-
-#elif defined(BACKWARD_SYSTEM_WINDOWS)
-
-template <>
-class StackTraceImpl : public StackTraceImplHolder {
-public:
- // We have to load the machine type from the image info
- // So we first initialize the resolver, and it tells us this info
- void set_machine_type(DWORD machine_type) { machine_type_ = machine_type; }
- void set_context(CONTEXT* ctx) { ctx_ = ctx; }
- void set_thread_handle(HANDLE handle) { thd_ = handle; }
-
- NOINLINE
- size_t load_here(size_t depth = 32)
- {
-
- CONTEXT localCtx; // used when no context is provided
-
- if (depth == 0) {
- return 0;
- }
-
- if (!ctx_) {
- ctx_ = &localCtx;
- RtlCaptureContext(ctx_);
- }
-
- if (!thd_) {
- thd_ = GetCurrentThread();
- }
-
- HANDLE process = GetCurrentProcess();
-
- STACKFRAME64 s;
- memset(&s, 0, sizeof(STACKFRAME64));
-
- // TODO: 32 bit context capture
- s.AddrStack.Mode = AddrModeFlat;
- s.AddrFrame.Mode = AddrModeFlat;
- s.AddrPC.Mode = AddrModeFlat;
-# ifdef _M_X64
- s.AddrPC.Offset = ctx_->Rip;
- s.AddrStack.Offset = ctx_->Rsp;
- s.AddrFrame.Offset = ctx_->Rbp;
-# else
- s.AddrPC.Offset = ctx_->Eip;
- s.AddrStack.Offset = ctx_->Esp;
- s.AddrFrame.Offset = ctx_->Ebp;
-# endif
-
- if (!machine_type_) {
-# ifdef _M_X64
- machine_type_ = IMAGE_FILE_MACHINE_AMD64;
-# else
- machine_type_ = IMAGE_FILE_MACHINE_I386;
-# endif
- }
-
- for (;;) {
- // NOTE: this only works if PDBs are already loaded!
- SetLastError(0);
- if (!StackWalk64(
- machine_type_, process, thd_, &s, ctx_, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
- break;
-
- if (s.AddrReturn.Offset == 0)
- break;
-
- _stacktrace.push_back(reinterpret_cast(s.AddrPC.Offset));
-
- if (size() >= depth)
- break;
- }
-
- return size();
- }
-
- size_t load_from(void* addr, size_t depth = 32)
- {
- load_here(depth + 8);
-
- for (size_t i = 0; i < _stacktrace.size(); ++i) {
- if (_stacktrace[i] == addr) {
- skip_n_firsts(i);
- break;
- }
- }
-
- _stacktrace.resize(std::min(_stacktrace.size(), skip_n_firsts() + depth));
- return size();
- }
-
-private:
- DWORD machine_type_ = 0;
- HANDLE thd_ = 0;
- CONTEXT* ctx_ = nullptr;
-};
-
-#endif
-
-class StackTrace : public StackTraceImpl {
-};
-
-/*************** TRACE RESOLVER ***************/
-
-template
-class TraceResolverImpl;
-
-#ifdef BACKWARD_SYSTEM_UNKNOWN
-
-template <>
-class TraceResolverImpl {
-public:
- template
- void load_stacktrace(ST&)
- {
- }
- ResolvedTrace resolve(ResolvedTrace t) { return t; }
-};
-
-#endif
-
-class TraceResolverImplBase {
-protected:
- std::string demangle(const char* funcname) { return _demangler.demangle(funcname); }
-
-private:
- details::demangler _demangler;
-};
-
-#ifdef BACKWARD_SYSTEM_LINUX
-
-class TraceResolverLinuxBase : public TraceResolverImplBase {
-public:
- TraceResolverLinuxBase() : argv0_(get_argv0()), exec_path_(read_symlink("/proc/self/exe")) {}
- std::string resolve_exec_path(Dl_info& symbol_info) const
- {
- // mutates symbol_info.dli_fname to be filename to open and returns filename
- // to display
- if (symbol_info.dli_fname == argv0_) {
- // dladdr returns argv[0] in dli_fname for symbols contained in
- // the main executable, which is not a valid path if the
- // executable was found by a search of the PATH environment
- // variable; In that case, we actually open /proc/self/exe, which
- // is always the actual executable (even if it was deleted/replaced!)
- // but display the path that /proc/self/exe links to.
- symbol_info.dli_fname = "/proc/self/exe";
- return exec_path_;
- }
- else {
- return symbol_info.dli_fname;
- }
- }
-
-private:
- std::string argv0_;
- std::string exec_path_;
-
- static std::string get_argv0()
- {
- std::string argv0;
- std::ifstream ifs("/proc/self/cmdline");
- std::getline(ifs, argv0, '\0');
- return argv0;
- }
-
- static std::string read_symlink(std::string const& symlink_path)
- {
- std::string path;
- path.resize(100);
-
- while (true) {
- ssize_t len = ::readlink(symlink_path.c_str(), &*path.begin(), path.size());
- if (len < 0) {
- return "";
- }
- if (static_cast(len) == path.size()) {
- path.resize(path.size() * 2);
- }
- else {
- path.resize(static_cast(len));
- break;
- }
- }
-
- return path;
- }
-};
-
-template
-class TraceResolverLinuxImpl;
-
-# if BACKWARD_HAS_BACKTRACE_SYMBOL == 1
-
-template <>
-class TraceResolverLinuxImpl : public TraceResolverLinuxBase {
-public:
- template
- void load_stacktrace(ST& st)
- {
- using namespace details;
- if (st.size() == 0) {
- return;
- }
- _symbols.reset(backtrace_symbols(st.begin(), (int)st.size()));
- }
-
- ResolvedTrace resolve(ResolvedTrace trace)
- {
- char* filename = _symbols[trace.idx];
- char* funcname = filename;
- while (*funcname && *funcname != '(') {
- funcname += 1;
- }
- trace.object_filename.assign(
- filename,
- funcname); // ok even if funcname is the ending
- // \0 (then we assign entire string)
-
- if (*funcname) { // if it's not end of string (e.g. from last frame ip==0)
- funcname += 1;
- char* funcname_end = funcname;
- while (*funcname_end && *funcname_end != ')' && *funcname_end != '+') {
- funcname_end += 1;
- }
- *funcname_end = '\0';
- trace.object_function = this->demangle(funcname);
- trace.source.function = trace.object_function; // we cannot do better.
- }
- return trace;
- }
-
-private:
- details::handle _symbols;
-};
-
-# endif // BACKWARD_HAS_BACKTRACE_SYMBOL == 1
-
-# if BACKWARD_HAS_BFD == 1
-
-template <>
-class TraceResolverLinuxImpl : public TraceResolverLinuxBase {
-public:
- TraceResolverLinuxImpl() : _bfd_loaded(false) {}
-
- template
- void load_stacktrace(ST&)
- {
- }
-
- ResolvedTrace resolve(ResolvedTrace trace)
- {
- Dl_info symbol_info;
-
- // trace.addr is a virtual address in memory pointing to some code.
- // Let's try to find from which loaded object it comes from.
- // The loaded object can be yourself btw.
- if (!dladdr(trace.addr, &symbol_info)) {
- return trace; // dat broken trace...
- }
-
- // Now we get in symbol_info:
- // .dli_fname:
- // pathname of the shared object that contains the address.
- // .dli_fbase:
- // where the object is loaded in memory.
- // .dli_sname:
- // the name of the nearest symbol to trace.addr, we expect a
- // function name.
- // .dli_saddr:
- // the exact address corresponding to .dli_sname.
-
- if (symbol_info.dli_sname) {
- trace.object_function = demangle(symbol_info.dli_sname);
- }
-
- if (!symbol_info.dli_fname) {
- return trace;
- }
-
- trace.object_filename = resolve_exec_path(symbol_info);
- bfd_fileobject& fobj = load_object_with_bfd(symbol_info.dli_fname);
- if (!fobj.handle) {
- return trace; // sad, we couldn't load the object :(
- }
-
- find_sym_result* details_selected; // to be filled.
-
- // trace.addr is the next instruction to be executed after returning
- // from the nested stack frame. In C++ this usually relate to the next
- // statement right after the function call that leaded to a new stack
- // frame. This is not usually what you want to see when printing out a
- // stacktrace...
- find_sym_result details_call_site = find_symbol_details(fobj, trace.addr, symbol_info.dli_fbase);
- details_selected = &details_call_site;
-
-# if BACKWARD_HAS_UNWIND == 0
- // ...this is why we also try to resolve the symbol that is right
- // before the return address. If we are lucky enough, we will get the
- // line of the function that was called. But if the code is optimized,
- // we might get something absolutely not related since the compiler
- // can reschedule the return address with inline functions and
- // tail-call optimisation (among other things that I don't even know
- // or cannot even dream about with my tiny limited brain).
- find_sym_result details_adjusted_call_site =
- find_symbol_details(fobj, (void*)(uintptr_t(trace.addr) - 1), symbol_info.dli_fbase);
-
- // In debug mode, we should always get the right thing(TM).
- if (details_call_site.found && details_adjusted_call_site.found) {
- // Ok, we assume that details_adjusted_call_site is a better estimation.
- details_selected = &details_adjusted_call_site;
- trace.addr = (void*)(uintptr_t(trace.addr) - 1);
- }
-
- if (details_selected == &details_call_site && details_call_site.found) {
- // we have to re-resolve the symbol in order to reset some
- // internal state in BFD... so we can call backtrace_inliners
- // thereafter...
- details_call_site = find_symbol_details(fobj, trace.addr, symbol_info.dli_fbase);
- }
-# endif // BACKWARD_HAS_UNWIND
-
- if (details_selected->found) {
- if (details_selected->filename) {
- trace.source.filename = details_selected->filename;
- }
- trace.source.line = details_selected->line;
-
- if (details_selected->funcname) {
- // this time we get the name of the function where the code is
- // located, instead of the function were the address is
- // located. In short, if the code was inlined, we get the
- // function correspoding to the code. Else we already got in
- // trace.function.
- trace.source.function = demangle(details_selected->funcname);
-
- if (!symbol_info.dli_sname) {
- // for the case dladdr failed to find the symbol name of
- // the function, we might as well try to put something
- // here.
- trace.object_function = trace.source.function;
- }
- }
-
- // Maybe the source of the trace got inlined inside the function
- // (trace.source.function). Let's see if we can get all the inlined
- // calls along the way up to the initial call site.
- trace.inliners = backtrace_inliners(fobj, *details_selected);
-
-# if 0
- if (trace.inliners.size() == 0) {
- // Maybe the trace was not inlined... or maybe it was and we
- // are lacking the debug information. Let's try to make the
- // world better and see if we can get the line number of the
- // function (trace.source.function) now.
- //
- // We will get the location of where the function start (to be
- // exact: the first instruction that really start the
- // function), not where the name of the function is defined.
- // This can be quite far away from the name of the function
- // btw.
- //
- // If the source of the function is the same as the source of
- // the trace, we cannot say if the trace was really inlined or
- // not. However, if the filename of the source is different
- // between the function and the trace... we can declare it as
- // an inliner. This is not 100% accurate, but better than
- // nothing.
-
- if (symbol_info.dli_saddr) {
- find_sym_result details = find_symbol_details(fobj,
- symbol_info.dli_saddr,
- symbol_info.dli_fbase);
-
- if (details.found) {
- ResolvedTrace::SourceLoc diy_inliner;
- diy_inliner.line = details.line;
- if (details.filename) {
- diy_inliner.filename = details.filename;
- }
- if (details.funcname) {
- diy_inliner.function = demangle(details.funcname);
- } else {
- diy_inliner.function = trace.source.function;
- }
- if (diy_inliner != trace.source) {
- trace.inliners.push_back(diy_inliner);
- }
- }
- }
- }
-# endif
- }
-
- return trace;
- }
-
-private:
- bool _bfd_loaded;
-
- typedef details::handle> bfd_handle_t;
-
- typedef details::handle bfd_symtab_t;
-
- struct bfd_fileobject {
- bfd_handle_t handle;
- bfd_vma base_addr;
- bfd_symtab_t symtab;
- bfd_symtab_t dynamic_symtab;
- };
-
- typedef details::hashtable::type fobj_bfd_map_t;
- fobj_bfd_map_t _fobj_bfd_map;
-
- bfd_fileobject& load_object_with_bfd(const std::string& filename_object)
- {
- using namespace details;
-
- if (!_bfd_loaded) {
- using namespace details;
- bfd_init();
- _bfd_loaded = true;
- }
-
- fobj_bfd_map_t::iterator it = _fobj_bfd_map.find(filename_object);
- if (it != _fobj_bfd_map.end()) {
- return it->second;
- }
-
- // this new object is empty for now.
- bfd_fileobject& r = _fobj_bfd_map[filename_object];
-
- // we do the work temporary in this one;
- bfd_handle_t bfd_handle;
-
- int fd = open(filename_object.c_str(), O_RDONLY);
- bfd_handle.reset(bfd_fdopenr(filename_object.c_str(), "default", fd));
- if (!bfd_handle) {
- close(fd);
- return r;
- }
-
- if (!bfd_check_format(bfd_handle.get(), bfd_object)) {
- return r; // not an object? You lose.
- }
-
- if ((bfd_get_file_flags(bfd_handle.get()) & HAS_SYMS) == 0) {
- return r; // that's what happen when you forget to compile in debug.
- }
-
- ssize_t symtab_storage_size = bfd_get_symtab_upper_bound(bfd_handle.get());
-
- ssize_t dyn_symtab_storage_size = bfd_get_dynamic_symtab_upper_bound(bfd_handle.get());
-
- if (symtab_storage_size <= 0 && dyn_symtab_storage_size <= 0) {
- return r; // weird, is the file is corrupted?
- }
-
- bfd_symtab_t symtab, dynamic_symtab;
- ssize_t symcount = 0, dyn_symcount = 0;
-
- if (symtab_storage_size > 0) {
- symtab.reset(static_cast(malloc(static_cast(symtab_storage_size))));
- symcount = bfd_canonicalize_symtab(bfd_handle.get(), symtab.get());
- }
-
- if (dyn_symtab_storage_size > 0) {
- dynamic_symtab.reset(static_cast(malloc(static_cast(dyn_symtab_storage_size))));
- dyn_symcount = bfd_canonicalize_dynamic_symtab(bfd_handle.get(), dynamic_symtab.get());
- }
-
- if (symcount <= 0 && dyn_symcount <= 0) {
- return r; // damned, that's a stripped file that you got there!
- }
-
- r.handle = move(bfd_handle);
- r.symtab = move(symtab);
- r.dynamic_symtab = move(dynamic_symtab);
- return r;
- }
-
- struct find_sym_result {
- bool found;
- const char* filename;
- const char* funcname;
- unsigned int line;
- };
-
- struct find_sym_context {
- TraceResolverLinuxImpl* self;
- bfd_fileobject* fobj;
- void* addr;
- void* base_addr;
- find_sym_result result;
- };
-
- find_sym_result find_symbol_details(bfd_fileobject& fobj, void* addr, void* base_addr)
- {
- find_sym_context context;
- context.self = this;
- context.fobj = &fobj;
- context.addr = addr;
- context.base_addr = base_addr;
- context.result.found = false;
- bfd_map_over_sections(fobj.handle.get(), &find_in_section_trampoline, static_cast(&context));
- return context.result;
- }
-
- static void find_in_section_trampoline(bfd*, asection* section, void* data)
- {
- find_sym_context* context = static_cast(data);
- context->self->find_in_section(
- reinterpret_cast(context->addr),
- reinterpret_cast(context->base_addr),
- *context->fobj,
- section,
- context->result);
- }
-
- void find_in_section(
- bfd_vma addr,
- bfd_vma base_addr,
- bfd_fileobject& fobj,
- asection* section,
- find_sym_result& result)
- {
- if (result.found)
- return;
-
-# ifdef bfd_get_section_flags
- if ((bfd_get_section_flags(fobj.handle.get(), section) & SEC_ALLOC) == 0)
-# else
- if ((bfd_section_flags(section) & SEC_ALLOC) == 0)
-# endif
- return; // a debug section is never loaded automatically.
-
-# ifdef bfd_get_section_vma
- bfd_vma sec_addr = bfd_get_section_vma(fobj.handle.get(), section);
-# else
- bfd_vma sec_addr = bfd_section_vma(section);
-# endif
-# ifdef bfd_get_section_size
- bfd_size_type size = bfd_get_section_size(section);
-# else
- bfd_size_type size = bfd_section_size(section);
-# endif
-
- // are we in the boundaries of the section?
- if (addr < sec_addr || addr >= sec_addr + size) {
- addr -= base_addr; // oups, a relocated object, lets try again...
- if (addr < sec_addr || addr >= sec_addr + size) {
- return;
- }
- }
-
-# if defined(__clang__)
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
-# endif
- if (!result.found && fobj.symtab) {
- result.found = bfd_find_nearest_line(
- fobj.handle.get(),
- section,
- fobj.symtab.get(),
- addr - sec_addr,
- &result.filename,
- &result.funcname,
- &result.line);
- }
-
- if (!result.found && fobj.dynamic_symtab) {
- result.found = bfd_find_nearest_line(
- fobj.handle.get(),
- section,
- fobj.dynamic_symtab.get(),
- addr - sec_addr,
- &result.filename,
- &result.funcname,
- &result.line);
- }
-# if defined(__clang__)
-# pragma clang diagnostic pop
-# endif
- }
-
- ResolvedTrace::source_locs_t backtrace_inliners(bfd_fileobject& fobj, find_sym_result previous_result)
- {
- // This function can be called ONLY after a SUCCESSFUL call to
- // find_symbol_details. The state is global to the bfd_handle.
- ResolvedTrace::source_locs_t results;
- while (previous_result.found) {
- find_sym_result result;
- result.found = bfd_find_inliner_info(fobj.handle.get(), &result.filename, &result.funcname, &result.line);
-
- if (result.found) /* and not (
- cstrings_eq(previous_result.filename,
- result.filename) and
- cstrings_eq(previous_result.funcname, result.funcname)
- and result.line == previous_result.line
- )) */
- {
- ResolvedTrace::SourceLoc src_loc;
- src_loc.line = result.line;
- if (result.filename) {
- src_loc.filename = result.filename;
- }
- if (result.funcname) {
- src_loc.function = demangle(result.funcname);
- }
- results.push_back(src_loc);
- }
- previous_result = result;
- }
- return results;
- }
-
- bool cstrings_eq(const char* a, const char* b)
- {
- if (!a || !b) {
- return false;
- }
- return strcmp(a, b) == 0;
- }
-};
-# endif // BACKWARD_HAS_BFD == 1
-
-# if BACKWARD_HAS_DW == 1
-
-template <>
-class TraceResolverLinuxImpl : public TraceResolverLinuxBase {
-public:
- TraceResolverLinuxImpl() : _dwfl_handle_initialized(false) {}
-
- template
- void load_stacktrace(ST&)
- {
- }
-
- ResolvedTrace resolve(ResolvedTrace trace)
- {
- using namespace details;
-
- Dwarf_Addr trace_addr = (Dwarf_Addr)trace.addr;
-
- if (!_dwfl_handle_initialized) {
- // initialize dwfl...
- _dwfl_cb.reset(new Dwfl_Callbacks);
- _dwfl_cb->find_elf = &dwfl_linux_proc_find_elf;
- _dwfl_cb->find_debuginfo = &dwfl_standard_find_debuginfo;
- _dwfl_cb->debuginfo_path = 0;
-
- _dwfl_handle.reset(dwfl_begin(_dwfl_cb.get()));
- _dwfl_handle_initialized = true;
-
- if (!_dwfl_handle) {
- return trace;
- }
-
- // ...from the current process.
- dwfl_report_begin(_dwfl_handle.get());
- int r = dwfl_linux_proc_report(_dwfl_handle.get(), getpid());
- dwfl_report_end(_dwfl_handle.get(), NULL, NULL);
- if (r < 0) {
- return trace;
- }
- }
-
- if (!_dwfl_handle) {
- return trace;
- }
-
- // find the module (binary object) that contains the trace's address.
- // This is not using any debug information, but the addresses ranges of
- // all the currently loaded binary object.
- Dwfl_Module* mod = dwfl_addrmodule(_dwfl_handle.get(), trace_addr);
- if (mod) {
- // now that we found it, lets get the name of it, this will be the
- // full path to the running binary or one of the loaded library.
- const char* module_name = dwfl_module_info(mod, 0, 0, 0, 0, 0, 0, 0);
- if (module_name) {
- trace.object_filename = module_name;
- }
- // We also look after the name of the symbol, equal or before this
- // address. This is found by walking the symtab. We should get the
- // symbol corresponding to the function (mangled) containing the
- // address. If the code corresponding to the address was inlined,
- // this is the name of the out-most inliner function.
- const char* sym_name = dwfl_module_addrname(mod, trace_addr);
- if (sym_name) {
- trace.object_function = demangle(sym_name);
- }
- }
-
- // now let's get serious, and find out the source location (file and
- // line number) of the address.
-
- // This function will look in .debug_aranges for the address and map it
- // to the location of the compilation unit DIE in .debug_info and
- // return it.
- Dwarf_Addr mod_bias = 0;
- Dwarf_Die* cudie = dwfl_module_addrdie(mod, trace_addr, &mod_bias);
-
-# if 1
- if (!cudie) {
- // Sadly clang does not generate the section .debug_aranges, thus
- // dwfl_module_addrdie will fail early. Clang doesn't either set
- // the lowpc/highpc/range info for every compilation unit.
- //
- // So in order to save the world:
- // for every compilation unit, we will iterate over every single
- // DIEs. Normally functions should have a lowpc/highpc/range, which
- // we will use to infer the compilation unit.
-
- // note that this is probably badly inefficient.
- while ((cudie = dwfl_module_nextcu(mod, cudie, &mod_bias))) {
- Dwarf_Die die_mem;
- Dwarf_Die* fundie = find_fundie_by_pc(cudie, trace_addr - mod_bias, &die_mem);
- if (fundie) {
- break;
- }
- }
- }
-# endif
-
-//#define BACKWARD_I_DO_NOT_RECOMMEND_TO_ENABLE_THIS_HORRIBLE_PIECE_OF_CODE
-# ifdef BACKWARD_I_DO_NOT_RECOMMEND_TO_ENABLE_THIS_HORRIBLE_PIECE_OF_CODE
- if (!cudie) {
- // If it's still not enough, lets dive deeper in the shit, and try
- // to save the world again: for every compilation unit, we will
- // load the corresponding .debug_line section, and see if we can
- // find our address in it.
-
- Dwarf_Addr cfi_bias;
- Dwarf_CFI* cfi_cache = dwfl_module_eh_cfi(mod, &cfi_bias);
-
- Dwarf_Addr bias;
- while ((cudie = dwfl_module_nextcu(mod, cudie, &bias))) {
- if (dwarf_getsrc_die(cudie, trace_addr - bias)) {
-
- // ...but if we get a match, it might be a false positive
- // because our (address - bias) might as well be valid in a
- // different compilation unit. So we throw our last card on
- // the table and lookup for the address into the .eh_frame
- // section.
-
- handle frame;
- dwarf_cfi_addrframe(cfi_cache, trace_addr - cfi_bias, &frame);
- if (frame) {
- break;
- }
- }
- }
- }
-# endif
-
- if (!cudie) {
- return trace; // this time we lost the game :/
- }
-
- // Now that we have a compilation unit DIE, this function will be able
- // to load the corresponding section in .debug_line (if not already
- // loaded) and hopefully find the source location mapped to our
- // address.
- Dwarf_Line* srcloc = dwarf_getsrc_die(cudie, trace_addr - mod_bias);
-
- if (srcloc) {
- const char* srcfile = dwarf_linesrc(srcloc, 0, 0);
- if (srcfile) {
- trace.source.filename = srcfile;
- }
- int line = 0, col = 0;
- dwarf_lineno(srcloc, &line);
- dwarf_linecol(srcloc, &col);
- trace.source.line = line;
- trace.source.col = col;
- }
-
- deep_first_search_by_pc(cudie, trace_addr - mod_bias, inliners_search_cb(trace));
- if (trace.source.function.size() == 0) {
- // fallback.
- trace.source.function = trace.object_function;
- }
-
- return trace;
- }
-
-private:
- typedef details::handle> dwfl_handle_t;
- details::handle> _dwfl_cb;
- dwfl_handle_t _dwfl_handle;
- bool _dwfl_handle_initialized;
-
- // defined here because in C++98, template function cannot take locally
- // defined types... grrr.
- struct inliners_search_cb {
- void operator()(Dwarf_Die* die)
- {
- switch (dwarf_tag(die)) {
- const char* name;
- case DW_TAG_subprogram:
- if ((name = dwarf_diename(die))) {
- trace.source.function = name;
- }
- break;
-
- case DW_TAG_inlined_subroutine:
- ResolvedTrace::SourceLoc sloc;
- Dwarf_Attribute attr_mem;
-
- if ((name = dwarf_diename(die))) {
- sloc.function = name;
- }
- if ((name = die_call_file(die))) {
- sloc.filename = name;
- }
-
- Dwarf_Word line = 0, col = 0;
- dwarf_formudata(dwarf_attr(die, DW_AT_call_line, &attr_mem), &line);
- dwarf_formudata(dwarf_attr(die, DW_AT_call_column, &attr_mem), &col);
- sloc.line = (unsigned)line;
- sloc.col = (unsigned)col;
-
- trace.inliners.push_back(sloc);
- break;
- };
- }
- ResolvedTrace& trace;
- inliners_search_cb(ResolvedTrace& t) : trace(t) {}
- };
-
- static bool die_has_pc(Dwarf_Die* die, Dwarf_Addr pc)
- {
- Dwarf_Addr low, high;
-
- // continuous range
- if (dwarf_hasattr(die, DW_AT_low_pc) && dwarf_hasattr(die, DW_AT_high_pc)) {
- if (dwarf_lowpc(die, &low) != 0) {
- return false;
- }
- if (dwarf_highpc(die, &high) != 0) {
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute* attr = dwarf_attr(die, DW_AT_high_pc, &attr_mem);
- Dwarf_Word value;
- if (dwarf_formudata(attr, &value) != 0) {
- return false;
- }
- high = low + value;
- }
- return pc >= low && pc < high;
- }
-
- // non-continuous range.
- Dwarf_Addr base;
- ptrdiff_t offset = 0;
- while ((offset = dwarf_ranges(die, offset, &base, &low, &high)) > 0) {
- if (pc >= low && pc < high) {
- return true;
- }
- }
- return false;
- }
-
- static Dwarf_Die* find_fundie_by_pc(Dwarf_Die* parent_die, Dwarf_Addr pc, Dwarf_Die* result)
- {
- if (dwarf_child(parent_die, result) != 0) {
- return 0;
- }
-
- Dwarf_Die* die = result;
- do {
- switch (dwarf_tag(die)) {
- case DW_TAG_subprogram:
- case DW_TAG_inlined_subroutine:
- if (die_has_pc(die, pc)) {
- return result;
- }
- };
- bool declaration = false;
- Dwarf_Attribute attr_mem;
- dwarf_formflag(dwarf_attr(die, DW_AT_declaration, &attr_mem), &declaration);
- if (!declaration) {
- // let's be curious and look deeper in the tree,
- // function are not necessarily at the first level, but
- // might be nested inside a namespace, structure etc.
- Dwarf_Die die_mem;
- Dwarf_Die* indie = find_fundie_by_pc(die, pc, &die_mem);
- if (indie) {
- *result = die_mem;
- return result;
- }
- }
- } while (dwarf_siblingof(die, result) == 0);
- return 0;
- }
-
- template
- static bool deep_first_search_by_pc(Dwarf_Die* parent_die, Dwarf_Addr pc, CB cb)
- {
- Dwarf_Die die_mem;
- if (dwarf_child(parent_die, &die_mem) != 0) {
- return false;
- }
-
- bool branch_has_pc = false;
- Dwarf_Die* die = &die_mem;
- do {
- bool declaration = false;
- Dwarf_Attribute attr_mem;
- dwarf_formflag(dwarf_attr(die, DW_AT_declaration, &attr_mem), &declaration);
- if (!declaration) {
- // let's be curious and look deeper in the tree, function are
- // not necessarily at the first level, but might be nested
- // inside a namespace, structure, a function, an inlined
- // function etc.
- branch_has_pc = deep_first_search_by_pc(die, pc, cb);
- }
- if (!branch_has_pc) {
- branch_has_pc = die_has_pc(die, pc);
- }
- if (branch_has_pc) {
- cb(die);
- }
- } while (dwarf_siblingof(die, &die_mem) == 0);
- return branch_has_pc;
- }
-
- static const char* die_call_file(Dwarf_Die* die)
- {
- Dwarf_Attribute attr_mem;
- Dwarf_Sword file_idx = 0;
-
- dwarf_formsdata(dwarf_attr(die, DW_AT_call_file, &attr_mem), &file_idx);
-
- if (file_idx == 0) {
- return 0;
- }
-
- Dwarf_Die die_mem;
- Dwarf_Die* cudie = dwarf_diecu(die, &die_mem, 0, 0);
- if (!cudie) {
- return 0;
- }
-
- Dwarf_Files* files = 0;
- size_t nfiles;
- dwarf_getsrcfiles(cudie, &files, &nfiles);
- if (!files) {
- return 0;
- }
-
- return dwarf_filesrc(files, file_idx, 0, 0);
- }
-};
-# endif // BACKWARD_HAS_DW == 1
-
-# if BACKWARD_HAS_DWARF == 1
-
-template <>
-class TraceResolverLinuxImpl : public TraceResolverLinuxBase {
-public:
- TraceResolverLinuxImpl() : _dwarf_loaded(false) {}
-
- template
- void load_stacktrace(ST&)
- {
- }
-
- ResolvedTrace resolve(ResolvedTrace trace)
- {
- // trace.addr is a virtual address in memory pointing to some code.
- // Let's try to find from which loaded object it comes from.
- // The loaded object can be yourself btw.
-
- Dl_info symbol_info;
- int dladdr_result = 0;
-# if defined(__GLIBC__)
- link_map* link_map;
- // We request the link map so we can get information about offsets
- dladdr_result = dladdr1(trace.addr, &symbol_info, reinterpret_cast(&link_map), RTLD_DL_LINKMAP);
-# else
- // Android doesn't have dladdr1. Don't use the linker map.
- dladdr_result = dladdr(trace.addr, &symbol_info);
-# endif
- if (!dladdr_result) {
- return trace; // dat broken trace...
- }
-
- // Now we get in symbol_info:
- // .dli_fname:
- // pathname of the shared object that contains the address.
- // .dli_fbase:
- // where the object is loaded in memory.
- // .dli_sname:
- // the name of the nearest symbol to trace.addr, we expect a
- // function name.
- // .dli_saddr:
- // the exact address corresponding to .dli_sname.
- //
- // And in link_map:
- // .l_addr:
- // difference between the address in the ELF file and the address
- // in memory
- // l_name:
- // absolute pathname where the object was found
-
- if (symbol_info.dli_sname) {
- trace.object_function = demangle(symbol_info.dli_sname);
- }
-
- if (!symbol_info.dli_fname) {
- return trace;
- }
-
- trace.object_filename = resolve_exec_path(symbol_info);
- dwarf_fileobject& fobj = load_object_with_dwarf(symbol_info.dli_fname);
- if (!fobj.dwarf_handle) {
- return trace; // sad, we couldn't load the object :(
- }
-
-# if defined(__GLIBC__)
- // Convert the address to a module relative one by looking at
- // the module's loading address in the link map
- Dwarf_Addr address = reinterpret_cast(trace.addr) - reinterpret_cast(link_map->l_addr);
-# else
- Dwarf_Addr address = reinterpret_cast(trace.addr);
-# endif
-
- if (trace.object_function.empty()) {
- symbol_cache_t::iterator it = fobj.symbol_cache.lower_bound(address);
-
- if (it != fobj.symbol_cache.end()) {
- if (it->first != address) {
- if (it != fobj.symbol_cache.begin()) {
- --it;
- }
- }
- trace.object_function = demangle(it->second.c_str());
- }
- }
-
- // Get the Compilation Unit DIE for the address
- Dwarf_Die die = find_die(fobj, address);
-
- if (!die) {
- return trace; // this time we lost the game :/
- }
-
- // libdwarf doesn't give us direct access to its objects, it always
- // allocates a copy for the caller. We keep that copy alive in a cache
- // and we deallocate it later when it's no longer required.
- die_cache_entry& die_object = get_die_cache(fobj, die);
- if (die_object.isEmpty())
- return trace; // We have no line section for this DIE
-
- die_linemap_t::iterator it = die_object.line_section.lower_bound(address);
-
- if (it != die_object.line_section.end()) {
- if (it->first != address) {
- if (it == die_object.line_section.begin()) {
- // If we are on the first item of the line section
- // but the address does not match it means that
- // the address is below the range of the DIE. Give up.
- return trace;
- }
- else {
- --it;
- }
- }
- }
- else {
- return trace; // We didn't find the address.
- }
-
- // Get the Dwarf_Line that the address points to and call libdwarf
- // to get source file, line and column info.
- Dwarf_Line line = die_object.line_buffer[it->second];
- Dwarf_Error error = DW_DLE_NE;
-
- char* filename;
- if (dwarf_linesrc(line, &filename, &error) == DW_DLV_OK) {
- trace.source.filename = std::string(filename);
- dwarf_dealloc(fobj.dwarf_handle.get(), filename, DW_DLA_STRING);
- }
-
- Dwarf_Unsigned number = 0;
- if (dwarf_lineno(line, &number, &error) == DW_DLV_OK) {
- trace.source.line = number;
- }
- else {
- trace.source.line = 0;
- }
-
- if (dwarf_lineoff_b(line, &number, &error) == DW_DLV_OK) {
- trace.source.col = number;
- }
- else {
- trace.source.col = 0;
- }
-
- std::vector