From 34e117c4629b1baa0edca222aedb48833da6ce9e Mon Sep 17 00:00:00 2001 From: ReaJason Date: Thu, 21 Aug 2025 18:14:18 +0800 Subject: [PATCH] ci: separate test workflow --- .github/workflows/docker-build-test.yml | 40 ++++ .../workflows/memshell-integration-test.yml | 74 ++++++++ .github/workflows/probe-integration-test.yml | 71 +++++++ .github/workflows/test.yaml | 174 ------------------ .github/workflows/unit-test.yml | 35 ++++ .../MarkdownTestExecutionListener.java | 145 --------------- ...it.platform.launcher.TestExecutionListener | 1 - 7 files changed, 220 insertions(+), 320 deletions(-) create mode 100644 .github/workflows/docker-build-test.yml create mode 100644 .github/workflows/memshell-integration-test.yml create mode 100644 .github/workflows/probe-integration-test.yml delete mode 100644 .github/workflows/test.yaml create mode 100644 .github/workflows/unit-test.yml delete mode 100644 integration-test/src/test/java/com/reajason/javaweb/integration/MarkdownTestExecutionListener.java delete mode 100644 integration-test/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener diff --git a/.github/workflows/docker-build-test.yml b/.github/workflows/docker-build-test.yml new file mode 100644 index 00000000..39fafd56 --- /dev/null +++ b/.github/workflows/docker-build-test.yml @@ -0,0 +1,40 @@ +name: Docker Build Test + +on: + push: + branches: + - master + paths-ignore: + - 'docs/**' + - 'boot/**' + - 'examples/**' + - 'web/**' + - '**.md' + - '**/*.png' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} + cancel-in-progress: true + +jobs: + docker-build-test: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Build Docker image + run: | + docker build --build-arg ROUTE_ROOT_PATH=/memshell-party --build-arg CONTEXT_PATH=/memshell-party -t app . + docker images + - name: Run Docker container + run: | + docker run -d -e BOOT_OPTS=--server.servlet.context-path=/memshell-party -p 8080:8080 app + sleep 10 + - name: Test with curl + run: | + if [[ $(curl -w "%{http_code}" -o /dev/null http://localhost:8080/memshell-party/version) -eq 200 ]]; then + echo "Test successful!" + else + echo "Test failed!" + exit 1 + fi diff --git a/.github/workflows/memshell-integration-test.yml b/.github/workflows/memshell-integration-test.yml new file mode 100644 index 00000000..a328cedf --- /dev/null +++ b/.github/workflows/memshell-integration-test.yml @@ -0,0 +1,74 @@ +name: Memshell IntegrationTest + +on: + push: + branches: + - '**' + paths: + - '**/memshell/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} + cancel-in-progress: true + +jobs: + memshell-integration-test: + strategy: + fail-fast: false + matrix: + cases: + - middleware: "tomcat" + depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war" + - middleware: "jetty" + depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" + - middleware: "jbossas" + depend_tasks: ":vul:vul-webapp:war" + - middleware: "jbosseap" + depend_tasks: ":vul:vul-webapp:war" + - middleware: "wildfly" + depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" + - middleware: "glassfish" + depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" + - middleware: "resin" + depend_tasks: ":vul:vul-webapp:war" + - middleware: "payara" + depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" + - middleware: "websphere" + depend_tasks: ":vul:vul-webapp:war" + - middleware: "websphere7" + depend_tasks: ":vul:vul-webapp:war" + - middleware: "weblogic" + depend_tasks: ":vul:vul-webapp:war" + - middleware: "springwebmvc" + depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar" + - middleware: "springwebflux" + depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar" + - middleware: "xxljob" + depend_tasks: "" + runs-on: ubuntu-latest + name: ${{ matrix.cases.middleware }} + needs: [ unit-test ] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 17 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Prepare for Integration Test + run: ./gradlew ${{ matrix.cases.depend_tasks }} + + - name: Integration Test with gradle + run: ./gradlew :integration-test:test --tests '*.memshell.${{ matrix.cases.middleware }}.*' --info + + - name: Export Integration Test Summary + uses: mikepenz/action-junit-report@v5 + if: success() || failure() + with: + report_paths: '**/build/test-results/test/TEST-*.xml' diff --git a/.github/workflows/probe-integration-test.yml b/.github/workflows/probe-integration-test.yml new file mode 100644 index 00000000..f8103a7d --- /dev/null +++ b/.github/workflows/probe-integration-test.yml @@ -0,0 +1,71 @@ +name: Probe IntegrationTest + +on: + push: + branches: + - '**' + paths: + - '**/probe/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} + cancel-in-progress: true + +jobs: + test: + strategy: + fail-fast: false + matrix: + cases: + - middleware: "tomcat" + depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war" + - middleware: "jetty" + depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" + - middleware: "jbossas" + depend_tasks: ":vul:vul-webapp:war" + - middleware: "jbosseap" + depend_tasks: ":vul:vul-webapp:war" + - middleware: "wildfly" + depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" + - middleware: "glassfish" + depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" + - middleware: "resin" + depend_tasks: ":vul:vul-webapp:war" + - middleware: "payara" + depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" + - middleware: "websphere" + depend_tasks: ":vul:vul-webapp:war" + - middleware: "websphere7" + depend_tasks: ":vul:vul-webapp:war" + - middleware: "weblogic" + depend_tasks: ":vul:vul-webapp:war" + - middleware: "springwebmvc" + depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar" + - middleware: "springwebflux" + depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar" + runs-on: ubuntu-latest + name: ${{ matrix.cases.middleware }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 17 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Prepare for Integration Test + run: ./gradlew ${{ matrix.cases.depend_tasks }} + + - name: Integration Test with gradle + run: ./gradlew :integration-test:test --tests '*.probe.${{ matrix.cases.middleware }}.*' --info + + - name: Export Integration Test Summary + uses: mikepenz/action-junit-report@v5 + if: success() || failure() + with: + report_paths: '**/build/test-results/test/TEST-*.xml' diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml deleted file mode 100644 index ccb0149a..00000000 --- a/.github/workflows/test.yaml +++ /dev/null @@ -1,174 +0,0 @@ -name: Test - -on: - push: - branches: - - '**' - paths-ignore: - - 'docs/**' - - 'boot/**' - - 'examples/**' - - 'web/**' - - '**.md' - - '**/*.png' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} - cancel-in-progress: true - -jobs: - unit-test: - name: UniteTest - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Java - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: 17 - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - - - name: Generator Unit Test with Gradle - run: ./gradlew :generator:test - - - name: Boot Unit Test with Gradle - run: ./gradlew :boot:test - - docker-build-test: - runs-on: ubuntu-latest - if: github.ref == 'refs/heads/master' - steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Build Docker image - run: | - docker build --build-arg ROUTE_ROOT_PATH=/memshell-party --build-arg CONTEXT_PATH=/memshell-party -t app . - docker images - - name: Run Docker container - run: | - docker run -d -e BOOT_OPTS=--server.servlet.context-path=/memshell-party -p 8080:8080 app - sleep 10 - - name: Test with curl - run: | - if [[ $(curl -w "%{http_code}" -o /dev/null http://localhost:8080/memshell-party/version) -eq 200 ]]; then - echo "Test successful!" - else - echo "Test failed!" - exit 1 - fi - - memshell-integration-test: - strategy: - fail-fast: false - matrix: - cases: - - middleware: "tomcat" - depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war" - - middleware: "jetty" - depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" - - middleware: "jbossas" - depend_tasks: ":vul:vul-webapp:war" - - middleware: "jbosseap" - depend_tasks: ":vul:vul-webapp:war" - - middleware: "wildfly" - depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" - - middleware: "glassfish" - depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" - - middleware: "resin" - depend_tasks: ":vul:vul-webapp:war" - - middleware: "payara" - depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" - - middleware: "websphere" - depend_tasks: ":vul:vul-webapp:war" - - middleware: "websphere7" - depend_tasks: ":vul:vul-webapp:war" - - middleware: "weblogic" - depend_tasks: ":vul:vul-webapp:war" - - middleware: "springwebmvc" - depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar" - - middleware: "springwebflux" - depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar" - - middleware: "xxljob" - depend_tasks: "" - runs-on: ubuntu-latest - name: ${{ matrix.cases.middleware }} - needs: [ unit-test ] - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Java - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: 17 - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - - - name: Prepare for Integration Test - run: ./gradlew ${{ matrix.cases.depend_tasks }} - - - name: Integration Test with gradle - run: ./gradlew :integration-test:test --tests '*.memshell.${{ matrix.cases.middleware }}.*' --info - - - name: Export Integration Test Summary - run: cat integration-test/build/test-results/report.md >> $GITHUB_STEP_SUMMARY - - detection-integration-test: - strategy: - fail-fast: false - matrix: - cases: - - middleware: "tomcat" - depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war" - - middleware: "jetty" - depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" - - middleware: "jbossas" - depend_tasks: ":vul:vul-webapp:war" - - middleware: "jbosseap" - depend_tasks: ":vul:vul-webapp:war" - - middleware: "wildfly" - depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" - - middleware: "glassfish" - depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" - - middleware: "resin" - depend_tasks: ":vul:vul-webapp:war" - - middleware: "payara" - depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" - - middleware: "websphere" - depend_tasks: ":vul:vul-webapp:war" - - middleware: "websphere7" - depend_tasks: ":vul:vul-webapp:war" - - middleware: "weblogic" - depend_tasks: ":vul:vul-webapp:war" - - middleware: "springwebmvc" - depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar" - - middleware: "springwebflux" - depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar" - runs-on: ubuntu-latest - name: ${{ matrix.cases.middleware }} - needs: [ unit-test ] - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Java - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: 17 - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - - - name: Prepare for Integration Test - run: ./gradlew ${{ matrix.cases.depend_tasks }} - - - name: Integration Test with gradle - run: ./gradlew :integration-test:test --tests '*.probe.${{ matrix.cases.middleware }}.*' --info \ No newline at end of file diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml new file mode 100644 index 00000000..0d252b7a --- /dev/null +++ b/.github/workflows/unit-test.yml @@ -0,0 +1,35 @@ +name: Unit-Test + +on: + push: + branches: + - '**' + paths: + - 'generator/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} + cancel-in-progress: true + +jobs: + unit-test: + name: UniteTest + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 17 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Generator Unit Test with Gradle + run: ./gradlew :generator:test + + - name: Boot Unit Test with Gradle + run: ./gradlew :boot:test diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/MarkdownTestExecutionListener.java b/integration-test/src/test/java/com/reajason/javaweb/integration/MarkdownTestExecutionListener.java deleted file mode 100644 index 96901274..00000000 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/MarkdownTestExecutionListener.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.reajason.javaweb.integration; - -import lombok.Builder; -import lombok.Data; -import lombok.SneakyThrows; -import org.junit.platform.engine.TestExecutionResult; -import org.junit.platform.engine.UniqueId; -import org.junit.platform.launcher.TestExecutionListener; -import org.junit.platform.launcher.TestIdentifier; -import org.junit.platform.launcher.TestPlan; -import org.testcontainers.shaded.org.apache.commons.lang3.tuple.Pair; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.time.Duration; -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -/** - * @author ReaJason - * @since 2024/12/1 - */ -public class MarkdownTestExecutionListener implements TestExecutionListener { - private final Map timeStamps = new ConcurrentHashMap<>(); - private final Map> testCases = new ConcurrentHashMap<>(); - private final Path markdownPath = Paths.get("build", "test-results", "report.md"); - private Instant startTime; - - @SneakyThrows - @Override - public void testPlanExecutionStarted(TestPlan testPlan) { - Files.deleteIfExists(markdownPath); - ArrayList lines = new ArrayList<>(); - lines.add("## Integration Test"); - startTime = Instant.now(); - lines.add("- Started: " + startTime); - Files.write(markdownPath, lines, StandardOpenOption.CREATE_NEW); - } - - @Override - @SneakyThrows - public void testPlanExecutionFinished(TestPlan testPlan) { - List lines = new ArrayList<>(); - Instant endTime = Instant.now(); - lines.add("- Finished: " + endTime); - Duration duration = Duration.between(startTime, endTime); - lines.add("- Total Duration: " + getDuration(duration)); - Pair countPair = parseCases(); - lines.add(String.format("- Total Cases: %d/%d, %d failed", countPair.getLeft(), countPair.getRight(), countPair.getRight() - countPair.getLeft())); - lines.add(""); - - for (Map.Entry> entry : testCases.entrySet()) { - lines.add(String.format("### %s", entry.getKey())); - lines.add("|**Shell Type** | **Packer** | **Status**| **Duration(ms)** |"); - lines.add("|---------------|------------|-----------|------------------|"); - List value = entry.getValue().stream().sorted((tc1, tc2) -> { - if (tc1.getStatus() == tc2.getStatus()) { - return 0; - } - return tc1.getStatus() == TestExecutionResult.Status.FAILED ? -1 : 1; - }).collect(Collectors.toList()); - for (TestCase testCase : value) { - String status = testCase.getStatus().equals(TestExecutionResult.Status.SUCCESSFUL) ? "✔" : "✘"; - lines.add("|" + testCase.getShellType() + "|" + testCase.getPacker() + "|" + status + "|" + testCase.getDuration().toMillis() + "|"); - } - } - - Files.write(markdownPath, lines, StandardOpenOption.APPEND); - } - - private String getDuration(Duration duration) { - long totalSeconds = duration.getSeconds(); - long minutes = totalSeconds / 60; - long seconds = totalSeconds % 60; - if (totalSeconds < 60) { - return String.format("%d seconds", totalSeconds); - } else { - return String.format("%d minutes and %d seconds", minutes, seconds); - } - } - - private Pair parseCases() { - long totalCases = 0; - long successCases = 0; - - for (List caseList : testCases.values()) { - totalCases += caseList.size(); - for (TestCase testCase : caseList) { - if (testCase.getStatus().equals(TestExecutionResult.Status.SUCCESSFUL)) { - successCases++; - } - } - } - return Pair.of(successCases, totalCases); - } - - @Override - public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { - if (!testIdentifier.isTest()) { - return; - } - Instant startTime = timeStamps.get(testIdentifier.getUniqueIdObject()); - if (startTime == null) { - return; - } - String[] split = testIdentifier.getDisplayName().split("\\|"); - if (split.length == 3) { - String imageName = split[0].trim(); - String shellType = split[1].trim(); - String packer = split[2].trim(); - List cases = testCases.getOrDefault(imageName, new ArrayList<>()); - cases.add(TestCase.builder() - .imageName(imageName) - .shellType(shellType) - .packer(packer) - .duration(Duration.between(startTime, Instant.now())) - .status(testExecutionResult.getStatus()) - .build()); - testCases.put(imageName, cases); - } - } - - @Override - public void executionStarted(TestIdentifier testIdentifier) { - if (testIdentifier.isTest()) { - timeStamps.put(testIdentifier.getUniqueIdObject(), Instant.now()); - } - } - - @Data - @Builder - static class TestCase { - private String imageName; - private String shellType; - private String packer; - private Duration duration; - private TestExecutionResult.Status status; - } -} diff --git a/integration-test/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener b/integration-test/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener deleted file mode 100644 index a958fe24..00000000 --- a/integration-test/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener +++ /dev/null @@ -1 +0,0 @@ -com.reajason.javaweb.integration.MarkdownTestExecutionListener \ No newline at end of file