diff --git a/.github/workflows/build-common.yml b/.github/workflows/build-common.yml index afaaf43ef094..0cfc5e07e79c 100644 --- a/.github/workflows/build-common.yml +++ b/.github/workflows/build-common.yml @@ -15,6 +15,9 @@ on: skip-windows-smoke-tests: type: boolean required: false + reduced-smoke-tests: + type: boolean + required: false secrets: DEVELOCITY_ACCESS_KEY: required: false @@ -459,6 +462,7 @@ jobs: ./gradlew :smoke-tests:test -PsmokeTestSuite=${{ matrix.smoke-test-suite }} + ${{ inputs.reduced-smoke-tests && '-PreducedSmokeTests=true' || '' }} ${{ inputs.skip-openj9-tests && matrix.smoke-test-suite != 'websphere' && '-PskipOpenJ9SmokeTests=true' || '' }} ${{ inputs.no-build-cache && ' --no-build-cache' || '' }} diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml index 6311386fb9b2..24ef21e1a23f 100644 --- a/.github/workflows/build-pull-request.yml +++ b/.github/workflows/build-pull-request.yml @@ -93,7 +93,12 @@ jobs: needs: [resolve-native, resolve-servlet-images] uses: ./.github/workflows/reusable-pr-build.yml with: + # `test native` is applied automatically by .github/labeler.yml when the + # PR diff touches native-relevant paths. `test openj9`, `test windows`, + # and `test full smoke` are manual force-enables that are picked up on + # the next PR sync/open/reopen event. skip-native-tests: ${{ !(needs.resolve-native.outputs.run-native-tests == 'true' || contains(github.event.pull_request.labels.*.name, 'test native')) }} skip-openj9-tests: ${{ !contains(github.event.pull_request.labels.*.name, 'test openj9') }} skip-windows-smoke-tests: ${{ !contains(github.event.pull_request.labels.*.name, 'test windows') }} + reduced-smoke-tests: ${{ !contains(github.event.pull_request.labels.*.name, 'test full smoke') }} skip-servlet-images: ${{ needs.resolve-servlet-images.outputs.build-servlet-images != 'true' }} diff --git a/.github/workflows/reusable-pr-build.yml b/.github/workflows/reusable-pr-build.yml index c9e269f41de6..2d5b64f709e8 100644 --- a/.github/workflows/reusable-pr-build.yml +++ b/.github/workflows/reusable-pr-build.yml @@ -14,6 +14,9 @@ on: skip-windows-smoke-tests: type: boolean default: false + reduced-smoke-tests: + type: boolean + default: false skip-servlet-images: type: boolean default: false @@ -27,6 +30,7 @@ jobs: with: skip-openj9-tests: ${{ inputs.skip-openj9-tests }} skip-windows-smoke-tests: ${{ inputs.skip-windows-smoke-tests }} + reduced-smoke-tests: ${{ inputs.reduced-smoke-tests }} cache-read-only: true test-latest-deps: diff --git a/smoke-tests/build.gradle.kts b/smoke-tests/build.gradle.kts index 8c3335f17878..7ee327bfc79b 100644 --- a/smoke-tests/build.gradle.kts +++ b/smoke-tests/build.gradle.kts @@ -88,6 +88,11 @@ tasks { val extensionTestAppTask = project(":smoke-tests:extensions:testapp").tasks.named("jar") val extensionTestAppJarPath = extensionTestAppTask.flatMap { it.archiveFile } + val reducedSmokeTests = findProperty("reducedSmokeTests") == "true" + if (reducedSmokeTests) { + systemProperty("reducedSmokeTests", "true") + } + dependsOn(shadowTask, extensionTestAppTask, extensionTask) doFirst { diff --git a/smoke-tests/images/servlet/build.gradle.kts b/smoke-tests/images/servlet/build.gradle.kts index 759c21dc0f8f..25662365d10b 100644 --- a/smoke-tests/images/servlet/build.gradle.kts +++ b/smoke-tests/images/servlet/build.gradle.kts @@ -198,8 +198,8 @@ tasks { description = "Builds all Windows Docker images for the test matrix" } - val linuxImages = createDockerTasks(buildLinuxTestImages, false) - val windowsImages = createDockerTasks(buildWindowsTestImages, true) + val linuxImages = createDockerTasks(buildLinuxTestImages, false, targets) + val windowsImages = createDockerTasks(buildWindowsTestImages, true, targets) val pushLinuxImages by registering(DockerPushImage::class) { dependsOn(buildLinuxTestImages) @@ -376,7 +376,7 @@ fun configureImage( return image } -fun createDockerTasks(parentTask: TaskProvider, isWindows: Boolean): Set { +fun createDockerTasks(parentTask: TaskProvider, isWindows: Boolean, targets: Map>): Set { val resultImages = mutableSetOf() for ((server, matrices) in targets) { val smokeTestServer = findProperty("smokeTestServer") diff --git a/smoke-tests/src/test/java/io/opentelemetry/smoketest/appserver/AppServerTest.java b/smoke-tests/src/test/java/io/opentelemetry/smoketest/appserver/AppServerTest.java index c6b847454160..b388d9ca57f8 100644 --- a/smoke-tests/src/test/java/io/opentelemetry/smoketest/appserver/AppServerTest.java +++ b/smoke-tests/src/test/java/io/opentelemetry/smoketest/appserver/AppServerTest.java @@ -51,6 +51,10 @@ void setUpServer() { var jdk = appServer.jdk(); isWindows = TestContainerManager.useWindowsContainers(); + // In reduced mode (PR builds), only run a representative subset of the full matrix. + // The full matrix runs on merge to main. + skipIfNotReduced(appServer); + // ibm-semeru-runtimes doesn't publish windows images // adoptopenjdk is deprecated and doesn't publish Windows 2022 images assumeFalse(isWindows && jdk.endsWith("-openj9")); @@ -59,6 +63,50 @@ void setUpServer() { startWithoutCleanup(new AppServerImage(jdk, serverVersion, isWindows)); } + // Reduced smoke test rules for PR builds. The full matrix runs on merge to main. + // Tomcat covers all JDKs (hotspot), TomEE covers all JDKs (openj9), + // Websphere is already minimal, other servers test only minimum JDK on hotspot. + private void skipIfNotReduced(AppServer appServer) { + if (!Boolean.getBoolean("reducedSmokeTests")) { + return; + } + String jdk = appServer.jdk(); + boolean isOpenj9 = jdk.contains("-openj9"); + + if (this instanceof TomcatSmokeTest) { + assumeFalse(isOpenj9, "Reduced mode: Tomcat runs hotspot only"); + return; + } + if (this instanceof TomeeSmokeTest) { + assumeTrue(isOpenj9, "Reduced mode: TomEE runs openj9 only"); + return; + } + if (this instanceof WebsphereSmokeTest) { + return; + } + // All other servers: hotspot only, minimum JDK per server version + assumeFalse(isOpenj9, "Reduced mode: hotspot only"); + assumeTrue(isMinimumJdk(appServer), "Reduced mode: only minimum JDK per server version"); + } + + private boolean isMinimumJdk(AppServer appServer) { + int myJdk = parseJdkVersion(appServer.jdk()); + for (Class sibling : getClass().getEnclosingClass().getDeclaredClasses()) { + AppServer other = sibling.getAnnotation(AppServer.class); + if (other != null + && other.version().equals(appServer.version()) + && !other.jdk().contains("-openj9") + && parseJdkVersion(other.jdk()) < myJdk) { + return false; + } + } + return true; + } + + private static int parseJdkVersion(String jdk) { + return Integer.parseInt(jdk.split("-")[0]); + } + @AfterAll void afterAll() { stop();