From 0c2af766c8cd7b914d0853eefabede23565456b2 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Thu, 17 Jul 2025 17:07:30 +0200 Subject: [PATCH 1/8] Add GraalVM support for E2E tests starting with metrics handler. --- powertools-e2e-tests/handlers/metrics/pom.xml | 45 ++++- .../aws-lambda-java-core/reflect-config.json | 13 ++ .../reflect-config.json | 35 ++++ .../jni-config.json | 11 ++ .../native-image.properties | 1 + .../reflect-config.json | 61 ++++++ .../resource-config.json | 19 ++ .../reflect-config.json | 25 +++ .../reflect-config.json | 20 ++ powertools-e2e-tests/pom.xml | 35 ++++ .../amazon/lambda/powertools/MetricsE2ET.java | 38 ++-- .../testutils/DockerConfiguration.java | 180 ++++++++++++++++++ .../powertools/testutils/Infrastructure.java | 52 ++--- .../src/test/resources/docker/Dockerfile | 14 ++ 14 files changed, 493 insertions(+), 56 deletions(-) create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json create mode 100644 powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DockerConfiguration.java create mode 100644 powertools-e2e-tests/src/test/resources/docker/Dockerfile diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml index e543c2cd0..227905259 100644 --- a/powertools-e2e-tests/handlers/metrics/pom.xml +++ b/powertools-e2e-tests/handlers/metrics/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 @@ -21,6 +21,16 @@ com.amazonaws aws-lambda-java-events + + com.amazonaws + aws-lambda-java-runtime-interface-client + 2.8.2 + + + com.amazonaws + aws-lambda-java-core + 1.3.0 + org.aspectj aspectjrt @@ -57,4 +67,37 @@ + + + + native-image + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.1 + true + + + build-native + + build + + package + + + + handler + com.amazonaws.services.lambda.runtime.api.client.AWSLambda + + --enable-url-protocols=http + --add-opens java.base/java.util=ALL-UNNAMED + + + + + + + diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..e69fa735c --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,61 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields": [{ "name": "logger" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogLevel", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogFormat", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "java.lang.Void", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "java.util.Collections$UnmodifiableMap", + "fields": [{ "name": "m" }] + }, + { + "name": "jdk.internal.module.IllegalAccessLogger", + "fields": [{ "name": "logger" }] + }, + { + "name": "sun.misc.Unsafe", + "fields": [{ "name": "theUnsafe" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true + } +] diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json new file mode 100644 index 000000000..9ddd235e2 --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json @@ -0,0 +1,20 @@ +[ + { + "name": "software.amazon.lambda.powertools.e2e.Function", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "software.amazon.lambda.powertools.e2e.Input", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 4cf4afc3d..8ba14dc31 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -234,6 +234,41 @@ + + e2e-graal + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.5.3 + + + + integration-test + verify + + + + + 1 + + **/MetricsE2ET.java + + + **/TracingE2ET.java + + + + true + + + + + + diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java index 2765e0e70..feb9537d5 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java @@ -38,22 +38,22 @@ import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; import software.amazon.lambda.powertools.testutils.metrics.MetricsFetcher; -public class MetricsE2ET { - private static final String namespace = "MetricsE2ENamespace_" + UUID.randomUUID(); - private static final String service = "MetricsE2EService_" + UUID.randomUUID(); +class MetricsE2ET { + private static final String NAMESPACE = "MetricsE2ENamespace_" + UUID.randomUUID(); + private static final String SERVICE = "MetricsE2EService_" + UUID.randomUUID(); private static Infrastructure infrastructure; private static String functionName; @BeforeAll - @Timeout(value = 5, unit = TimeUnit.MINUTES) - public static void setup() { + @Timeout(value = 10, unit = TimeUnit.MINUTES) + static void setup() { infrastructure = Infrastructure.builder() .testName(MetricsE2ET.class.getSimpleName()) .pathToFunction("metrics") .environmentVariables( Stream.of(new String[][] { - { "POWERTOOLS_METRICS_NAMESPACE", namespace }, - { "POWERTOOLS_SERVICE_NAME", service } + { "POWERTOOLS_METRICS_NAMESPACE", NAMESPACE }, + { "POWERTOOLS_SERVICE_NAME", SERVICE } }) .collect(Collectors.toMap(data -> data[0], data -> data[1]))) .build(); @@ -62,14 +62,14 @@ public static void setup() { } @AfterAll - public static void tearDown() { + static void tearDown() { if (infrastructure != null) { infrastructure.destroy(); } } @Test - public void test_recordMetrics() { + void test_recordMetrics() { // GIVEN Instant currentTimeTruncatedToMinutes = Instant.now(Clock.systemUTC()).truncatedTo(ChronoUnit.MINUTES); @@ -84,17 +84,17 @@ public void test_recordMetrics() { // THEN MetricsFetcher metricsFetcher = new MetricsFetcher(); List coldStart = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, - namespace, + NAMESPACE, "ColdStart", Stream.of(new String[][] { { "FunctionName", functionName }, - { "Service", service } }).collect(Collectors.toMap(data -> data[0], data -> data[1]))); + { "Service", SERVICE } }).collect(Collectors.toMap(data -> data[0], data -> data[1]))); assertThat(coldStart.get(0)).isEqualTo(1); List orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), - 60, namespace, + 60, NAMESPACE, "orders", Collections.singletonMap("Environment", "test")); assertThat(orderMetrics.get(0)).isEqualTo(2); List productMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), - invocationResult.getEnd(), 60, namespace, + invocationResult.getEnd(), 60, NAMESPACE, "products", Collections.singletonMap("Environment", "test")); // When searching across a 1 minute time period with a period of 60 we find both metrics and the sum is 12 @@ -102,24 +102,22 @@ public void test_recordMetrics() { assertThat(productMetrics.get(0)).isEqualTo(12); orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, - namespace, - "orders", Collections.singletonMap("Service", service)); + NAMESPACE, + "orders", Collections.singletonMap("Service", SERVICE)); assertThat(orderMetrics.get(0)).isEqualTo(2); productMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, - namespace, - "products", Collections.singletonMap("Service", service)); + NAMESPACE, + "products", Collections.singletonMap("Service", SERVICE)); assertThat(productMetrics.get(0)).isEqualTo(12); Instant searchStartTime = currentTimeTruncatedToMinutes.plusSeconds(15); Instant searchEndTime = currentTimeTruncatedToMinutes.plusSeconds(45); - List productMetricDataResult = metricsFetcher.fetchMetrics(searchStartTime, searchEndTime, 1, namespace, + List productMetricDataResult = metricsFetcher.fetchMetrics(searchStartTime, searchEndTime, 1, NAMESPACE, "products", Collections.singletonMap("Environment", "test")); // We are searching across the time period the metric was created but with a period of 1 second. Only the high // resolution metric will be available at this point - assertThat(productMetricDataResult.get(0)).isEqualTo(8); - } } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DockerConfiguration.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DockerConfiguration.java new file mode 100644 index 000000000..204d5863a --- /dev/null +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DockerConfiguration.java @@ -0,0 +1,180 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * 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. + * + */ + +package software.amazon.lambda.powertools.testutils; + +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import software.amazon.awscdk.BundlingOptions; +import software.amazon.awscdk.BundlingOutput; +import software.amazon.awscdk.DockerImage; +import software.amazon.awscdk.DockerVolume; + +/** + * Configuration class for managing build environments and Docker settings + * used during Lambda function compilation. + */ +public class DockerConfiguration { + private final String baseImage; + private final List buildArgs; + private final Map environmentVariables; + private final List volumes; + + private DockerConfiguration(Builder builder) { + this.baseImage = builder.baseImage; + this.buildArgs = builder.buildArgs; + this.environmentVariables = builder.environmentVariables; + this.volumes = builder.volumes; + } + + public static Builder builder() { + return new Builder(); + } + + public String getBaseImage() { + return baseImage; + } + + public List getBuildArgs() { + return buildArgs; + } + + public Map getEnvironmentVariables() { + return environmentVariables; + } + + public List getVolumes() { + return volumes; + } + + /** + * Creates bundling options for GraalVM native image compilation. + */ + public BundlingOptions createGraalVMBundlingOptions(String pathToFunction, JavaRuntime runtime) { + List packagingInstruction = Arrays.asList( + "/bin/sh", + "-c", + "cd " + pathToFunction + + " && timeout -s SIGKILL 10m mvn clean package -Pnative-image -ff" + + " -Dmaven.test.skip=true" + + " -Dmaven.compiler.source=" + runtime.getMvnProperty() + + " -Dmaven.compiler.target=" + runtime.getMvnProperty() + + " && mkdir -p /tmp/lambda-package" + + " && cp /asset-input/" + pathToFunction + "/target/handler /tmp/lambda-package/" + + " && chmod +x /tmp/lambda-package/handler" + + " && echo '#!/bin/bash\nset -e\n./handler $_HANDLER' > /tmp/lambda-package/bootstrap" + + " && chmod +x /tmp/lambda-package/bootstrap" + + " && cd /tmp/lambda-package" + + " && zip -r /asset-output/function.zip ."); + + return BundlingOptions.builder() + .command(packagingInstruction) + .image(DockerImage.fromRegistry(baseImage)) + .volumes(volumes) + .environment(environmentVariables) + .user("root") + .outputType(BundlingOutput.ARCHIVED) + .build(); + } + + /** + * Creates bundling options for standard JVM compilation. + */ + public BundlingOptions createJVMBundlingOptions(String pathToFunction, JavaRuntime runtime) { + List packagingInstruction = Arrays.asList( + "/bin/sh", + "-c", + "cd " + pathToFunction + + " && timeout -s SIGKILL 5m mvn clean install -ff" + + " -Dmaven.test.skip=true" + + " -Dmaven.compiler.source=" + runtime.getMvnProperty() + + " -Dmaven.compiler.target=" + runtime.getMvnProperty() + + " && cp /asset-input/" + pathToFunction + "/target/function.jar /asset-output/"); + + return BundlingOptions.builder() + .command(packagingInstruction) + .image(DockerImage.fromRegistry(baseImage)) + .volumes(volumes) + .user("root") + .outputType(BundlingOutput.ARCHIVED) + .build(); + } + + /** + * Creates a default Docker configuration for GraalVM native image compilation. + */ + public static DockerConfiguration createGraalVMDefault(JavaRuntime runtime) { + // Use custom Dockerfile for GraalVM + String dockerDir = Paths.get(System.getProperty("user.dir"), "src", "test", "resources", "docker").toString(); + DockerImage customImage = DockerImage.fromBuild(dockerDir); + + return builder() + .baseImage(customImage.getImage()) + .environmentVariables(Map.of("JAVA_VERSION", runtime.getMvnProperty())) + .volumes(List.of( + DockerVolume.builder() + .hostPath(System.getProperty("user.home") + "/.m2/") + .containerPath("/root/.m2/") + .build())) + .build(); + } + + /** + * Creates a default Docker configuration for standard JVM compilation. + */ + public static DockerConfiguration createJVMDefault(JavaRuntime runtime) { + return builder() + .baseImage(runtime.getCdkRuntime().getBundlingImage().getImage()) + .volumes(List.of( + DockerVolume.builder() + .hostPath(System.getProperty("user.home") + "/.m2/") + .containerPath("/root/.m2/") + .build())) + .build(); + } + + public static class Builder { + private String baseImage; + private List buildArgs; + private Map environmentVariables; + private List volumes; + + public Builder baseImage(String baseImage) { + this.baseImage = baseImage; + return this; + } + + public Builder buildArgs(List buildArgs) { + this.buildArgs = buildArgs; + return this; + } + + public Builder environmentVariables(Map environmentVariables) { + this.environmentVariables = environmentVariables; + return this; + } + + public Builder volumes(List volumes) { + this.volumes = volumes; + return this; + } + + public DockerConfiguration build() { + return new DockerConfiguration(this); + } + } +} diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java index 07d816112..c9194a686 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java @@ -19,13 +19,10 @@ import java.io.File; import java.io.IOException; import java.nio.file.Paths; -import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.UUID; -import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,10 +32,8 @@ import software.amazon.awscdk.App; import software.amazon.awscdk.BundlingOptions; -import software.amazon.awscdk.BundlingOutput; import software.amazon.awscdk.CfnOutput; import software.amazon.awscdk.DefaultStackSynthesizer; -import software.amazon.awscdk.DockerVolume; import software.amazon.awscdk.Duration; import software.amazon.awscdk.RemovalPolicy; import software.amazon.awscdk.Stack; @@ -59,6 +54,7 @@ import software.amazon.awscdk.services.kinesis.StreamMode; import software.amazon.awscdk.services.lambda.Code; import software.amazon.awscdk.services.lambda.Function; +import software.amazon.awscdk.services.lambda.Runtime; import software.amazon.awscdk.services.lambda.StartingPosition; import software.amazon.awscdk.services.lambda.Tracing; import software.amazon.awscdk.services.lambda.eventsources.DynamoEventSource; @@ -218,47 +214,31 @@ private Stack createStackWithLambda() { .build()) .build(); - List packagingInstruction = Arrays.asList( - "/bin/sh", - "-c", - "cd " + pathToFunction + - " && timeout -s SIGKILL 5m mvn clean install -ff " + - " -Dmaven.test.skip=true " + - " -Dmaven.compiler.source=" + runtime.getMvnProperty() + - " -Dmaven.compiler.target=" + runtime.getMvnProperty() + - " && cp /asset-input/" + pathToFunction + "/target/function.jar /asset-output/"); - - BundlingOptions.Builder builderOptions = BundlingOptions.builder() - .command(packagingInstruction) - .image(runtime.getCdkRuntime().getBundlingImage()) - .volumes(singletonList( - // Mount local .m2 repo to avoid download all the dependencies again inside the container - DockerVolume.builder() - .hostPath(System.getProperty("user.home") + "/.m2/") - .containerPath("/root/.m2/") - .build())) - .user("root") - .outputType(BundlingOutput.ARCHIVED); + boolean isGraalVMEnabled = Boolean.parseBoolean(System.getProperty("graalvm.enabled", "false")); + DockerConfiguration dockerConfig = isGraalVMEnabled + ? DockerConfiguration.createGraalVMDefault(runtime) + : DockerConfiguration.createJVMDefault(runtime); + + BundlingOptions bundlingOptions = isGraalVMEnabled + ? dockerConfig.createGraalVMBundlingOptions(pathToFunction, runtime) + : dockerConfig.createJVMBundlingOptions(pathToFunction, runtime); functionName = stackName + "-function"; CfnOutput.Builder.create(e2eStack, FUNCTION_NAME_OUTPUT) .value(functionName) .build(); - LOG.debug("Building Lambda function with command " + - packagingInstruction.stream().collect(Collectors.joining(" ", "[", "]"))); + LOG.debug("Building Lambda function with " + (isGraalVMEnabled ? "GraalVM" : "JVM") + " configuration"); Function function = Function.Builder .create(e2eStack, functionName) .code(Code.fromAsset("handlers/", AssetOptions.builder() - .bundling(builderOptions - .command(packagingInstruction) - .build()) + .bundling(bundlingOptions) .build())) .functionName(functionName) .handler("software.amazon.lambda.powertools.e2e.Function::handleRequest") .memorySize(1024) .timeout(Duration.seconds(timeout)) - .runtime(runtime.getCdkRuntime()) + .runtime(isGraalVMEnabled ? Runtime.PROVIDED_AL2023 : runtime.getCdkRuntime()) .environment(envVar) .tracing(tracing ? Tracing.ACTIVE : Tracing.DISABLED) .build(); @@ -457,17 +437,19 @@ private void synthesize() { private void uploadAssets() { Map assets = findAssets(); assets.forEach((objectKey, asset) -> { - if (!asset.assetPath.endsWith(".jar")) { + // .zip will be used for GraalVM bundles. + if (!asset.assetPath.endsWith(".jar") && !asset.assetPath.endsWith(".zip")) { + LOG.info("Skipping upload of {}", asset); return; } + LOG.info("Uploading {}", asset); ListObjectsV2Response objects = s3 .listObjectsV2(ListObjectsV2Request.builder().bucket(asset.bucketName).build()); if (objects.contents().stream().anyMatch(o -> o.key().equals(objectKey))) { - LOG.debug("Asset already exists, skipping"); + LOG.debug("{} already exists, skipping", asset); return; } - LOG.info("Uploading asset " + objectKey + " to " + asset.bucketName); s3.putObject(PutObjectRequest.builder().bucket(asset.bucketName).key(objectKey).build(), Paths.get(cfnAssetDirectory, asset.assetPath)); }); diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile new file mode 100644 index 000000000..33ff070ff --- /dev/null +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -0,0 +1,14 @@ +# Use the official AWS SAM base image for Java 21 +FROM public.ecr.aws/sam/build-java21:latest + +# Install GraalVM dependencies +RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz +RUN mv graalvm-jdk-21.* /usr/lib/graalvm + +# Make native image and mvn available on CLI +RUN ln -s /usr/lib/graalvm/bin/native-image /usr/bin/native-image +RUN ln -s /usr/lib/maven/bin/mvn /usr/bin/mvn + +# Set GraalVM as default +ENV JAVA_HOME=/usr/lib/graalvm +ENV PATH=/usr/lib/graalvm/bin:$PATH From 4e83acabd06bfe943b03e97ab30d9095bfb92465 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 18 Jul 2025 14:45:04 +0200 Subject: [PATCH 2/8] Add GraalVM E2E test support for Logging and Parameters. Refactor metrics configuration be in parent pom. --- powertools-e2e-tests/handlers/logging/pom.xml | 24 +++++++- .../aws-lambda-java-core/reflect-config.json | 13 ++++ .../reflect-config.json | 35 +++++++++++ .../jni-config.json | 11 ++++ .../native-image.properties | 1 + .../reflect-config.json | 61 +++++++++++++++++++ .../resource-config.json | 19 ++++++ .../reflect-config.json | 25 ++++++++ .../reflect-config.json | 20 ++++++ .../resource-config.json | 7 +++ powertools-e2e-tests/handlers/metrics/pom.xml | 21 ------- .../handlers/parameters/pom.xml | 24 +++++++- .../aws-lambda-java-core/reflect-config.json | 13 ++++ .../reflect-config.json | 35 +++++++++++ .../jni-config.json | 11 ++++ .../native-image.properties | 1 + .../reflect-config.json | 61 +++++++++++++++++++ .../resource-config.json | 19 ++++++ .../reflect-config.json | 25 ++++++++ .../reflect-config.json | 20 ++++++ .../resource-config.json | 7 +++ powertools-e2e-tests/handlers/pom.xml | 51 ++++++++++++---- powertools-e2e-tests/pom.xml | 6 +- .../amazon/lambda/powertools/LoggingE2ET.java | 25 ++++---- .../lambda/powertools/ParametersE2ET.java | 20 +++--- 25 files changed, 498 insertions(+), 57 deletions(-) create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json diff --git a/powertools-e2e-tests/handlers/logging/pom.xml b/powertools-e2e-tests/handlers/logging/pom.xml index 62f2f7530..f5eacf5c5 100644 --- a/powertools-e2e-tests/handlers/logging/pom.xml +++ b/powertools-e2e-tests/handlers/logging/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 @@ -30,6 +30,14 @@ com.amazonaws aws-lambda-java-events + + com.amazonaws + aws-lambda-java-runtime-interface-client + + + com.amazonaws + aws-lambda-java-core + @@ -62,4 +70,18 @@ + + + + native-image + + + + org.graalvm.buildtools + native-maven-plugin + + + + + diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..e69fa735c --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,61 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields": [{ "name": "logger" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogLevel", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogFormat", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "java.lang.Void", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "java.util.Collections$UnmodifiableMap", + "fields": [{ "name": "m" }] + }, + { + "name": "jdk.internal.module.IllegalAccessLogger", + "fields": [{ "name": "logger" }] + }, + { + "name": "sun.misc.Unsafe", + "fields": [{ "name": "theUnsafe" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true + } +] diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json new file mode 100644 index 000000000..9ddd235e2 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json @@ -0,0 +1,20 @@ +[ + { + "name": "software.amazon.lambda.powertools.e2e.Function", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "software.amazon.lambda.powertools.e2e.Input", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml index 227905259..7bdc75591 100644 --- a/powertools-e2e-tests/handlers/metrics/pom.xml +++ b/powertools-e2e-tests/handlers/metrics/pom.xml @@ -24,12 +24,10 @@ com.amazonaws aws-lambda-java-runtime-interface-client - 2.8.2 com.amazonaws aws-lambda-java-core - 1.3.0 org.aspectj @@ -76,25 +74,6 @@ org.graalvm.buildtools native-maven-plugin - 0.10.1 - true - - - build-native - - build - - package - - - - handler - com.amazonaws.services.lambda.runtime.api.client.AWSLambda - - --enable-url-protocols=http - --add-opens java.base/java.util=ALL-UNNAMED - - diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml index 471e79d8f..46e6dc1e5 100644 --- a/powertools-e2e-tests/handlers/parameters/pom.xml +++ b/powertools-e2e-tests/handlers/parameters/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 @@ -25,6 +25,14 @@ com.amazonaws aws-lambda-java-events + + com.amazonaws + aws-lambda-java-runtime-interface-client + + + com.amazonaws + aws-lambda-java-core + org.aspectj aspectjrt @@ -61,4 +69,18 @@ + + + + native-image + + + + org.graalvm.buildtools + native-maven-plugin + + + + + diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..e69fa735c --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,61 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields": [{ "name": "logger" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogLevel", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogFormat", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "java.lang.Void", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "java.util.Collections$UnmodifiableMap", + "fields": [{ "name": "m" }] + }, + { + "name": "jdk.internal.module.IllegalAccessLogger", + "fields": [{ "name": "logger" }] + }, + { + "name": "sun.misc.Unsafe", + "fields": [{ "name": "theUnsafe" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true + } +] diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json new file mode 100644 index 000000000..9ddd235e2 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json @@ -0,0 +1,20 @@ +[ + { + "name": "software.amazon.lambda.powertools.e2e.Function", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "software.amazon.lambda.powertools.e2e.Input", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 988ae3d55..1b3eaf3e0 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda @@ -15,13 +15,13 @@ 11 11 - 1.2.2 - 1.1.2 - 3.11.2 + 1.3.0 + 1.1.6 + 3.16.1 3.5.0 1.13.1 3.11.0 - 2.20.108 + 2.32.2 1.9.20.1 @@ -112,6 +112,11 @@ aws-lambda-java-serialization ${lambda.java.serialization} + + com.amazonaws + aws-lambda-java-runtime-interface-client + 2.8.2 + @@ -134,17 +139,18 @@ - + - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + @@ -185,6 +191,29 @@ + + org.graalvm.buildtools + native-maven-plugin + 0.10.6 + true + + + build-native + + build + + package + + + + handler + com.amazonaws.services.lambda.runtime.api.client.AWSLambda + + --enable-url-protocols=http + --add-opens java.base/java.util=ALL-UNNAMED + + + diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 8ba14dc31..3bbaca3e2 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -253,15 +253,15 @@ 1 + **/MetricsE2ET.java + **/LoggingE2ET.java + **/ParametersE2ET.java **/TracingE2ET.java - true diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java index f78500c65..ad2c2564f 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java @@ -19,22 +19,25 @@ import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction; import static software.amazon.lambda.powertools.testutils.logging.InvocationLogs.Level.INFO; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + import software.amazon.lambda.powertools.testutils.Infrastructure; import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; -public class LoggingE2ET { +class LoggingE2ET { private static final ObjectMapper objectMapper = new ObjectMapper(); @@ -42,17 +45,17 @@ public class LoggingE2ET { private static String functionName; @BeforeAll - @Timeout(value = 5, unit = TimeUnit.MINUTES) - public static void setup() { + @Timeout(value = 10, unit = TimeUnit.MINUTES) + static void setup() { infrastructure = Infrastructure.builder() .testName(LoggingE2ET.class.getSimpleName()) .tracing(true) .pathToFunction("logging") .environmentVariables( Stream.of(new String[][] { - {"POWERTOOLS_LOG_LEVEL", "INFO"}, - {"POWERTOOLS_SERVICE_NAME", LoggingE2ET.class.getSimpleName()} - }) + { "POWERTOOLS_LOG_LEVEL", "INFO" }, + { "POWERTOOLS_SERVICE_NAME", LoggingE2ET.class.getSimpleName() } + }) .collect(Collectors.toMap(data -> data[0], data -> data[1]))) .build(); Map outputs = infrastructure.deploy(); @@ -60,14 +63,14 @@ public static void setup() { } @AfterAll - public static void tearDown() { + static void tearDown() { if (infrastructure != null) { infrastructure.destroy(); } } @Test - public void test_logInfoWithAdditionalKeys() throws JsonProcessingException { + void test_logInfoWithAdditionalKeys() throws JsonProcessingException { // GIVEN String orderId = UUID.randomUUID().toString(); String event = "{\"message\":\"New Order\", \"keys\":{\"orderId\":\"" + orderId + "\"}}"; diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ParametersE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ParametersE2ET.java index 9582f9f23..39254a9e6 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ParametersE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ParametersE2ET.java @@ -24,22 +24,24 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.Timeout; + import software.amazon.lambda.powertools.testutils.AppConfig; import software.amazon.lambda.powertools.testutils.Infrastructure; import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; @TestInstance(TestInstance.Lifecycle.PER_CLASS) -public class ParametersE2ET { +class ParametersE2ET { private final AppConfig appConfig; private Infrastructure infrastructure; private String functionName; - public ParametersE2ET() { + ParametersE2ET() { String appName = UUID.randomUUID().toString(); Map params = new HashMap<>(); params.put("key1", "value1"); @@ -48,17 +50,17 @@ public ParametersE2ET() { } @BeforeAll - @Timeout(value = 5, unit = TimeUnit.MINUTES) - public void setup() { + @Timeout(value = 15, unit = TimeUnit.MINUTES) + void setup() { infrastructure = Infrastructure.builder() .testName(ParametersE2ET.class.getSimpleName()) .pathToFunction("parameters") .appConfig(appConfig) .environmentVariables( Stream.of(new String[][] { - {"POWERTOOLS_LOG_LEVEL", "INFO"}, - {"POWERTOOLS_SERVICE_NAME", ParametersE2ET.class.getSimpleName()} - }) + { "POWERTOOLS_LOG_LEVEL", "INFO" }, + { "POWERTOOLS_SERVICE_NAME", ParametersE2ET.class.getSimpleName() } + }) .collect(Collectors.toMap(data -> data[0], data -> data[1]))) .build(); Map outputs = infrastructure.deploy(); @@ -66,14 +68,14 @@ public void setup() { } @AfterAll - public void tearDown() { + void tearDown() { if (infrastructure != null) { infrastructure.destroy(); } } @Test - public void test_getAppConfigValue() { + void test_getAppConfigValue() { for (Map.Entry configKey : appConfig.getConfigurationValues().entrySet()) { // Arrange From 905ac803a398daa11b25e8b88115d3d301fd4604 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 18 Jul 2025 16:22:12 +0200 Subject: [PATCH 3/8] Add e2e-graal step to e2e test workflow. --- .github/workflows/check-e2e.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index d5c95f156..dfbd43f39 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -71,3 +71,35 @@ jobs: env: JAVA_VERSION: ${{ matrix.java }} run: mvn -DskipTests install --file pom.xml && mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml + + e2e-graal: + name: End-to-end GraalVM Tests (Java ${{ matrix.java }}) + runs-on: ubuntu-latest + permissions: + id-token: write + environment: E2E + strategy: + max-parallel: 3 + matrix: + java: + - 11 + - 17 + - 21 + + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Setup java + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 + with: + distribution: 'corretto' + java-version: ${{ matrix.java }} + cache: maven + - name: Setup AWS credentials + uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 + with: + role-to-assume: ${{ secrets.AWS_IAM_ROLE }} + aws-region: us-east-1 + - name: Run e2e-graal test with Maven + env: + JAVA_VERSION: ${{ matrix.java }} + run: mvn -DskipTests install --file pom.xml && mvn -Pe2e-graal -B verify --file powertools-e2e-tests/pom.xml From 98f517ee6a1292acc86e572dc1f3bc93fa16d929 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 18 Jul 2025 16:35:23 +0200 Subject: [PATCH 4/8] Disable maven download progress logs to reduce amount of logs in GH runner. --- .github/workflows/check-e2e.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index dfbd43f39..3c9bbceb1 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -70,7 +70,7 @@ jobs: - name: Run e2e test with Maven env: JAVA_VERSION: ${{ matrix.java }} - run: mvn -DskipTests install --file pom.xml && mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml + run: mvn -DskipTests -ntp install --file pom.xml && mvn -Pe2e -B -ntp verify --file powertools-e2e-tests/pom.xml e2e-graal: name: End-to-end GraalVM Tests (Java ${{ matrix.java }}) @@ -102,4 +102,4 @@ jobs: - name: Run e2e-graal test with Maven env: JAVA_VERSION: ${{ matrix.java }} - run: mvn -DskipTests install --file pom.xml && mvn -Pe2e-graal -B verify --file powertools-e2e-tests/pom.xml + run: mvn -DskipTests -ntp install --file pom.xml && mvn -Pe2e-graal -B -ntp verify --file powertools-e2e-tests/pom.xml From 580866ebc9703aa503a81a65c3cd648c58ad6bf9 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 18 Jul 2025 17:15:28 +0200 Subject: [PATCH 5/8] Fix sonarlint issue. --- .../amazon/lambda/powertools/testutils/Infrastructure.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java index c9194a686..c65871a0a 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java @@ -228,7 +228,7 @@ private Stack createStackWithLambda() { .value(functionName) .build(); - LOG.debug("Building Lambda function with " + (isGraalVMEnabled ? "GraalVM" : "JVM") + " configuration"); + LOG.debug("Building Lambda function with {} configuration", isGraalVMEnabled ? "GraalVM" : "JVM"); Function function = Function.Builder .create(e2eStack, functionName) .code(Code.fromAsset("handlers/", AssetOptions.builder() From 2a02bf8168730638e154f130da58e11cb69ef3c2 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 18 Jul 2025 17:18:32 +0200 Subject: [PATCH 6/8] Update osv-scanner to 2.1.0. --- .github/workflows/security-osv.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-osv.yml b/.github/workflows/security-osv.yml index 67e2e6e3f..73d6b1835 100644 --- a/.github/workflows/security-osv.yml +++ b/.github/workflows/security-osv.yml @@ -32,4 +32,4 @@ jobs: actions: read contents: read security-events: write - uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@764c91816374ff2d8fc2095dab36eecd42d61638 # v1.9.2 \ No newline at end of file + uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@b00f71e051ddddc6e46a193c31c8c0bf283bf9e6 # v2.1.0 From 70c7c0ecb1306f15b3e841e97620ee3cde17dc53 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 21 Jul 2025 11:14:38 +0200 Subject: [PATCH 7/8] PIN docker image version. --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index 33ff070ff..a244dd60d 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21:latest +FROM public.ecr.aws/sam/build-java21@sha256:a5554d68374e19450c6c88448516ac95a9acedc779f318040f5c230134b4e461 # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz From b5682578bc81afa8fa2aaf9482264ad2a03ceaff Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 21 Jul 2025 11:14:56 +0200 Subject: [PATCH 8/8] Add fail-fast: false option to GH workflow. --- .github/workflows/check-e2e.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 3c9bbceb1..19500b2e5 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -47,6 +47,7 @@ jobs: id-token: write environment: E2E strategy: + fail-fast: false max-parallel: 3 matrix: java: @@ -79,6 +80,7 @@ jobs: id-token: write environment: E2E strategy: + fail-fast: false max-parallel: 3 matrix: java: