From 49174a4ea9f1b6f6f50b026d0b8345dade068ebd Mon Sep 17 00:00:00 2001 From: liuhy Date: Tue, 31 Mar 2026 19:18:31 +0800 Subject: [PATCH 1/7] goalx: snapshot before shenyu-analysis --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index ed771e556c44..e266500fd74d 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,6 @@ Thumbs.db # Private individual user cursor rules .cursor/rules/_*.mdc + +# local worktrees +.worktrees/ From 89df3b5675ad7a66385681542bd61ea978c3fb42 Mon Sep 17 00:00:00 2001 From: liuhy Date: Wed, 15 Apr 2026 09:45:17 +0800 Subject: [PATCH 2/7] Reduce duplicate PR CI work to improve queue time and feedback speed The heavy PR workflows were rebuilding the same Docker images and example artifacts in each matrix case, which multiplied machine time and increased queue pressure. This change adds workflow-level concurrency cancellation and restructures the e2e and it-k8s flows so expensive image preparation happens once before fan-out. Constraint: GitHub Actions matrix jobs do not share local Docker state across runners Constraint: Changes must preserve existing test case topology and repository-local workflow behavior Rejected: Keep per-case image builds and only add Maven cache tuning | leaves most duplicated runtime intact Rejected: Push temporary images to an external registry | adds auth and lifecycle complexity not needed for first pass Confidence: medium Scope-risk: moderate Reversibility: clean Directive: If artifact transfer becomes the new bottleneck, split image bundles by case family before reintroducing per-case builds Tested: YAML parse for modified workflows; actionlint on modified workflows with existing repo-specific false-positive filters; git diff --check Not-tested: Live GitHub Actions execution time and artifact transfer overhead on hosted runners --- .github/workflows/ci.yml | 4 + .github/workflows/codeql-analysis.yml | 4 + .github/workflows/e2e-k8s.yml | 210 ++++++----------- .../workflows/integrated-test-k8s-ingress.yml | 220 +++++++++++------- .github/workflows/integrated-test.yml | 4 + .github/workflows/k8s-examples-http.yml | 4 + 6 files changed, 216 insertions(+), 230 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0da28afeacbf..93274ddcf7f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,10 @@ name: ci +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + on: pull_request: push: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 2e835dcbbe97..a70ae7248931 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -15,6 +15,10 @@ name: "CodeQL" +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + on: push: branches: diff --git a/.github/workflows/e2e-k8s.yml b/.github/workflows/e2e-k8s.yml index b9451ecff7c0..cc99de1d6b3b 100644 --- a/.github/workflows/e2e-k8s.yml +++ b/.github/workflows/e2e-k8s.yml @@ -15,6 +15,10 @@ name: e2e +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + on: pull_request: push: @@ -30,15 +34,7 @@ jobs: - uses: actions/checkout@v3 with: submodules: true - - name: Free disk space - run: | - df --human-readable - sudo apt clean - for image in $(docker image ls --all --quiet); do - docker rmi $image - done - rm --recursive --force "$AGENT_TOOLSDIRECTORY" - df --human-readable + - uses: ./actions/paths-filter id: filter with: @@ -62,12 +58,13 @@ jobs: build-docker-images: needs: changes - if: ${{ needs.changes.outputs.e2e == 'true' }} + if: github.repository == 'apache/shenyu' && needs.changes.outputs.e2e == 'true' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true + - name: Free disk space run: | df --human-readable @@ -84,25 +81,25 @@ jobs: java-version: "17" distribution: "temurin" + - name: Restore ShenYu Maven Repos + id: restore-maven-cache + uses: actions/cache/restore@v3 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - name: Install mvnd shell: bash run: | MVND_VERSION=1.0.2 - if [[ "${{ runner.os }}" == "Windows" ]]; then - curl -sL https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-windows-amd64.zip -o mvnd.zip - unzip -q mvnd.zip - mkdir -p $HOME/.local - mv maven-mvnd-${MVND_VERSION}-windows-amd64 $HOME/.local/mvnd - echo "$HOME/.local/mvnd/bin" >> $GITHUB_PATH - echo "MVND_HOME=$HOME/.local/mvnd" >> $GITHUB_ENV - else - curl -sL https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-linux-amd64.zip -o mvnd.zip - unzip -q mvnd.zip - mkdir -p $HOME/.local - mv maven-mvnd-${MVND_VERSION}-linux-amd64 $HOME/.local/mvnd - echo "$HOME/.local/mvnd/bin" >> $GITHUB_PATH - echo "MVND_HOME=$HOME/.local/mvnd" >> $GITHUB_ENV - fi + curl -sL https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-linux-amd64.zip -o mvnd.zip + unzip -q mvnd.zip + mkdir -p $HOME/.local + mv maven-mvnd-${MVND_VERSION}-linux-amd64 $HOME/.local/mvnd + echo "$HOME/.local/mvnd/bin" >> $GITHUB_PATH + echo "MVND_HOME=$HOME/.local/mvnd" >> $GITHUB_ENV - name: Build with Maven shell: bash @@ -112,39 +109,58 @@ jobs: mvnd -B clean install -Prelease,docker -Dmaven.javadoc.skip=true -B -Drat.skip=true -Dmaven.test.skip=true -Djacoco.skip=true -DskipITs -DskipTests package -T1C else echo "Falling back to maven wrapper" - if [[ "${{ runner.os }}" == "Windows" ]]; then - ./mvnw.cmd -B clean install -Prelease,docker -Dmaven.javadoc.skip=true -B -Drat.skip=true -Dmaven.test.skip=true -Djacoco.skip=true -DskipITs -DskipTests package -T1C - else - ./mvnw -B clean install -Prelease,docker -Dmaven.javadoc.skip=true -B -Drat.skip=true -Dmaven.test.skip=true -Djacoco.skip=true -DskipITs -DskipTests package -T1C - fi + ./mvnw -B clean install -Prelease,docker -Dmaven.javadoc.skip=true -B -Drat.skip=true -Dmaven.test.skip=true -Djacoco.skip=true -DskipITs -DskipTests package -T1C + fi + + - name: Build examples with Maven + shell: bash + run: | + if mvnd --version > /dev/null 2>&1; then + echo "Using mvnd for build examples" + mvnd -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml + else + echo "Falling back to maven wrapper for examples" + ./mvnw -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml fi - name: Save ShenYu Maven Repos + if: steps.restore-maven-cache.outputs.cache-hit != 'true' uses: actions/cache/save@v3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - # - name: Build shenyu-e2e-engine with Maven - # run: ./mvnw -B -f ./shenyu-e2e/pom.xml -pl shenyu-e2e-engine -am clean install - - # - name: Save ShenYu E2E Maven Repos - # if: steps.restore-e2e-maven-cache.outputs.cache-hit != 'true' - # uses: actions/cache/save@v3 - # with: - # path: ~/.m2/repository - # key: ${{ runner.os }}-e2e-maven-${{ hashFiles('**/pom.xml') }} + - name: Export base images + run: | + docker save \ + apache/shenyu-bootstrap:latest \ + apache/shenyu-admin:latest \ + > /tmp/shenyu-base-images.tar - - name: Build Docker Image + - name: Export example images run: | - docker save apache/shenyu-bootstrap:latest > /tmp/apache-shenyu-bootstrap.tar - docker save apache/shenyu-admin:latest > /tmp/apache-shenyu-admin.tar + docker save \ + shenyu-examples-http:latest \ + shenyu-examples-eureka:latest \ + shenyu-examples-springcloud:latest \ + shenyu-examples-apache-dubbo-service:latest \ + shenyu-examples-sofa:latest \ + shenyu-examples-grpc:latest \ + shenyu-example-spring-native-websocket:latest \ + > /tmp/shenyu-e2e-example-images.tar + + - name: Upload base image artifacts + uses: actions/upload-artifact@v4 + with: + name: shenyu-base-images + path: /tmp/shenyu-base-images.tar + retention-days: 1 - - name: Upload Docker Image Artifacts + - name: Upload example image artifacts uses: actions/upload-artifact@v4 with: - name: shenyu-images - path: /tmp/apache-shenyu-*.tar + name: shenyu-e2e-example-images + path: /tmp/shenyu-e2e-example-images.tar retention-days: 1 e2e-storage: @@ -152,8 +168,7 @@ jobs: needs: - changes - build-docker-images - if: (github.repository == 'apache/shenyu' && ${{ needs.changes.outputs.e2e == 'true' }}) - # if: (github.repository == 'apache/shenyu') + if: github.repository == 'apache/shenyu' && needs.changes.outputs.e2e == 'true' strategy: matrix: include: @@ -182,14 +197,6 @@ jobs: rm -rf /tmp/shenyu mkdir -p /tmp/shenyu - # - name: Install k8s - # if: steps.filter.outputs.changed == 'true' - # run: | - # curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.29.6+k3s2 K3S_KUBECONFIG_MODE=777 sh - - # cat /etc/rancher/k3s/k3s.yaml - # mkdir -p ~/.kube - # cp /etc/rancher/k3s/k3s.yaml ~/.kube/config - - name: Set up JDK 17 for Building ShenYu uses: actions/setup-java@v4 with: @@ -206,38 +213,24 @@ jobs: - uses: actions/download-artifact@v4 with: - name: shenyu-images + name: shenyu-base-images path: /tmp/shenyu/ - name: Load ShenYu Docker Images run: | - docker load --input /tmp/shenyu/apache-shenyu-admin.tar - docker load --input /tmp/shenyu/apache-shenyu-bootstrap.tar + docker load --input /tmp/shenyu/shenyu-base-images.tar docker image ls -a - # - name: Build k8s Cluster - # if: steps.filter.outputs.changed == 'true' - # run: | - # sudo k3s ctr images import /tmp/shenyu/apache-shenyu-admin.tar - # sudo k3s ctr images import /tmp/shenyu/apache-shenyu-bootstrap.tar - - name: Run E2E Tests run: | bash ./shenyu-e2e/shenyu-e2e-case/${{ matrix.case }}/compose/script/${{ matrix.script }}.sh - # - name: Cluster Test after Healthcheck - # if: steps.filter.outputs.changed == 'true' - # run: | - # kubectl get all - # kubectl get events --all-namespaces - e2e-case: runs-on: ubuntu-latest needs: - changes - build-docker-images - if: (github.repository == 'apache/shenyu' && ${{ needs.changes.outputs.e2e == 'true' }}) - # if: (github.repository == 'apache/shenyu') + if: github.repository == 'apache/shenyu' && needs.changes.outputs.e2e == 'true' strategy: matrix: include: @@ -261,7 +254,6 @@ jobs: script: e2e-logging-rocketmq-compose # - case: shenyu-e2e-case-logging-kafka # script: e2e-logging-kafka-compose - steps: - uses: actions/checkout@v2 with: @@ -279,14 +271,6 @@ jobs: rm -rf /tmp/shenyu mkdir -p /tmp/shenyu - # - name: Install k8s - # if: steps.filter.outputs.changed == 'true' - # run: | - # curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.29.6+k3s2 K3S_KUBECONFIG_MODE=777 sh - - # cat /etc/rancher/k3s/k3s.yaml - # mkdir -p ~/.kube - # cp /etc/rancher/k3s/k3s.yaml ~/.kube/config - - name: Set up JDK 17 for Building ShenYu uses: actions/setup-java@v4 with: @@ -301,82 +285,26 @@ jobs: restore-keys: | ${{ runner.os }}-maven- - - name: Install mvnd - shell: bash - run: | - MVND_VERSION=1.0.2 - if [[ "${{ runner.os }}" == "Windows" ]]; then - curl -sL https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-windows-amd64.zip -o mvnd.zip - unzip -q mvnd.zip - mkdir -p $HOME/.local - mv maven-mvnd-${MVND_VERSION}-windows-amd64 $HOME/.local/mvnd - echo "$HOME/.local/mvnd/bin" >> $GITHUB_PATH - echo "MVND_HOME=$HOME/.local/mvnd" >> $GITHUB_ENV - else - curl -sL https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-linux-amd64.zip -o mvnd.zip - unzip -q mvnd.zip - mkdir -p $HOME/.local - mv maven-mvnd-${MVND_VERSION}-linux-amd64 $HOME/.local/mvnd - echo "$HOME/.local/mvnd/bin" >> $GITHUB_PATH - echo "MVND_HOME=$HOME/.local/mvnd" >> $GITHUB_ENV - fi - - uses: actions/download-artifact@v4 with: - name: shenyu-images + name: shenyu-base-images path: /tmp/shenyu/ - # - name: Restore ShenYu E2E Maven Repos - # uses: actions/cache/restore@v3 - # with: - # path: ~/.m2/repository - # key: ${{ runner.os }}-e2e-maven-${{ hashFiles('**/pom.xml') }} - # restore-keys: | - # ${{ runner.os }}-e2e-maven- - - - name: Build examples with Maven - shell: bash - run: | - echo "Falling back to maven wrapper for examples" - if [[ "${{ runner.os }}" == "Windows" ]]; then - ./mvnw.cmd -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml - else - ./mvnw -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml - fi - - uses: actions/download-artifact@v4 with: - name: shenyu-images + name: shenyu-e2e-example-images path: /tmp/shenyu/ - name: Load ShenYu Docker Images run: | - docker load --input /tmp/shenyu/apache-shenyu-admin.tar - docker load --input /tmp/shenyu/apache-shenyu-bootstrap.tar + docker load --input /tmp/shenyu/shenyu-base-images.tar + docker load --input /tmp/shenyu/shenyu-e2e-example-images.tar docker image ls -a - # - name: Build k8s Cluster - # if: steps.filter.outputs.changed == 'true' - # run: | - # sudo k3s ctr images import /tmp/shenyu/apache-shenyu-admin.tar - # sudo k3s ctr images import /tmp/shenyu/apache-shenyu-bootstrap.tar - - # - name: Setup Debug Session - # uses: mxschmitt/action-tmate@v3 - # timeout-minutes: 15 - # with: - # detached: true - - name: Run E2E Tests run: | bash ./shenyu-e2e/shenyu-e2e-case/${{ matrix.case }}/compose/script/${{ matrix.script }}.sh - # - name: Cluster Test after Healthcheck - # if: steps.filter.outputs.changed == 'true' - # run: | - # kubectl get all - # kubectl get events --all-namespaces - requirement: name: e2e if: ${{ needs.changes.outputs.e2e == 'true' }} diff --git a/.github/workflows/integrated-test-k8s-ingress.yml b/.github/workflows/integrated-test-k8s-ingress.yml index c6aa33c88b55..8b40cce88e66 100644 --- a/.github/workflows/integrated-test-k8s-ingress.yml +++ b/.github/workflows/integrated-test-k8s-ingress.yml @@ -15,6 +15,10 @@ name: it-k8s +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + on: pull_request: push: @@ -22,18 +26,10 @@ on: - master jobs: - build: - strategy: - matrix: - case: - - shenyu-integrated-test-k8s-ingress-http - - shenyu-integrated-test-k8s-ingress-apache-dubbo - - shenyu-integrated-test-k8s-ingress-motan - - shenyu-integrated-test-k8s-ingress-websocket - - shenyu-integrated-test-k8s-ingress-grpc - # - shenyu-integrated-test-k8s-ingress-sofa + changes: runs-on: ubuntu-latest - if: github.repository == 'apache/shenyu' + outputs: + k8s-ingress: ${{ steps.filter.outputs.k8s-ingress }} steps: - uses: actions/checkout@v3 with: @@ -60,44 +56,25 @@ jobs: - '!.github/ISSUE_TEMPLATE/**' - '!.github/PULL_REQUEST_TEMPLATE' + prepare-images: + needs: changes + if: github.repository == 'apache/shenyu' && needs.changes.outputs.k8s-ingress == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: Clean Space - if: steps.filter.outputs.k8s-ingress == 'true' run: | sudo rm -rf /usr/share/dotnet sudo rm -rf /opt/ghc sudo rm -rf "/usr/local/share/boost" sudo rm -rf "$AGENT_TOOLSDIRECTORY" - - name: Cache Maven Repos - if: steps.filter.outputs.k8s-ingress == 'true' - uses: actions/cache@v3 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- - - - uses: actions/setup-java@v4 - if: steps.filter.outputs.k8s-ingress == 'true' - with: - java-version: 17 - distribution: "temurin" - - - name: Install Go - uses: actions/setup-go@v3 - with: - go-version: 1.17.x - - - name: Install k8s - if: steps.filter.outputs.k8s-ingress == 'true' - run: | - go install sigs.k8s.io/kind@v0.14.0 - curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.24.14/bin/linux/amd64/kubectl && sudo install kubectl /usr/local/bin/kubectl - kind create cluster --image=kindest/node:v1.21.1 --config=./shenyu-integrated-test/${{ matrix.case }}/deploy/kind-config.yaml - - - name: Cache Maven Repos - if: steps.filter.outputs.k8s-ingress == 'true' - uses: actions/cache@v3 + - name: Restore Maven Repos + id: restore-maven-cache + uses: actions/cache/restore@v3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} @@ -105,34 +82,22 @@ jobs: ${{ runner.os }}-maven- - uses: actions/setup-java@v4 - if: steps.filter.outputs.k8s-ingress == 'true' with: java-version: 17 distribution: "temurin" - name: Install mvnd - if: steps.filter.outputs.k8s-ingress == 'true' shell: bash run: | MVND_VERSION=1.0.2 - if [[ "${{ runner.os }}" == "Windows" ]]; then - curl -sL https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-windows-amd64.zip -o mvnd.zip - unzip -q mvnd.zip - mkdir -p $HOME/.local - mv maven-mvnd-${MVND_VERSION}-windows-amd64 $HOME/.local/mvnd - echo "$HOME/.local/mvnd/bin" >> $GITHUB_PATH - echo "MVND_HOME=$HOME/.local/mvnd" >> $GITHUB_ENV - else - curl -sL https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-linux-amd64.zip -o mvnd.zip - unzip -q mvnd.zip - mkdir -p $HOME/.local - mv maven-mvnd-${MVND_VERSION}-linux-amd64 $HOME/.local/mvnd - echo "$HOME/.local/mvnd/bin" >> $GITHUB_PATH - echo "MVND_HOME=$HOME/.local/mvnd" >> $GITHUB_ENV - fi + curl -sL https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-linux-amd64.zip -o mvnd.zip + unzip -q mvnd.zip + mkdir -p $HOME/.local + mv maven-mvnd-${MVND_VERSION}-linux-amd64 $HOME/.local/mvnd + echo "$HOME/.local/mvnd/bin" >> $GITHUB_PATH + echo "MVND_HOME=$HOME/.local/mvnd" >> $GITHUB_ENV - name: Build with Maven - if: steps.filter.outputs.k8s-ingress == 'true' shell: bash run: | if mvnd --version > /dev/null 2>&1; then @@ -140,15 +105,10 @@ jobs: mvnd -B clean install -Dmaven.javadoc.skip=true -Dmaven.test.skip=true else echo "Falling back to maven wrapper" - if [[ "${{ runner.os }}" == "Windows" ]]; then - ./mvnw.cmd -B clean install -Dmaven.javadoc.skip=true -Dmaven.test.skip=true - else - ./mvnw -B clean install -Dmaven.javadoc.skip=true -Dmaven.test.skip=true - fi + ./mvnw -B clean install -Dmaven.javadoc.skip=true -Dmaven.test.skip=true fi - name: Build integrated tests - if: steps.filter.outputs.k8s-ingress == 'true' shell: bash run: | if mvnd --version > /dev/null 2>&1; then @@ -156,15 +116,10 @@ jobs: mvnd -B clean install -Pit -DskipTests -am -f ./shenyu-integrated-test/pom.xml else echo "Falling back to maven wrapper for integrated tests" - if [[ "${{ runner.os }}" == "Windows" ]]; then - ./mvnw.cmd -B clean install -Pit -DskipTests -am -f ./shenyu-integrated-test/pom.xml - else - ./mvnw -B clean install -Pit -DskipTests -am -f ./shenyu-integrated-test/pom.xml - fi + ./mvnw -B clean install -Pit -DskipTests -am -f ./shenyu-integrated-test/pom.xml fi - name: Build examples - if: steps.filter.outputs.k8s-ingress == 'true' shell: bash run: | if mvnd --version > /dev/null 2>&1; then @@ -172,26 +127,118 @@ jobs: mvnd -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml else echo "Falling back to maven wrapper for examples" - if [[ "${{ runner.os }}" == "Windows" ]]; then - ./mvnw.cmd -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml - else - ./mvnw -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml - fi + ./mvnw -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml fi + - name: Export prebuilt images + run: | + docker save \ + shenyu-examples-http:latest \ + apache/shenyu-integrated-test-k8s-ingress-http:latest \ + shenyu-examples-apache-dubbo-service:latest \ + apache/shenyu-integrated-test-k8s-ingress-apache-dubbo:latest \ + shenyu-examples-motan:latest \ + apache/shenyu-integrated-test-k8s-ingress-motan:latest \ + shenyu-example-spring-annotation-websocket:latest \ + apache/shenyu-integrated-test-k8s-ingress-websocket:latest \ + shenyu-examples-grpc:latest \ + apache/shenyu-integrated-test-k8s-ingress-grpc:latest \ + > /tmp/shenyu-it-k8s-images.tar + + - name: Upload prebuilt images + uses: actions/upload-artifact@v4 + with: + name: shenyu-it-k8s-images + path: /tmp/shenyu-it-k8s-images.tar + retention-days: 1 + + - name: Save Maven Repos + if: steps.restore-maven-cache.outputs.cache-hit != 'true' + uses: actions/cache/save@v3 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + + build: + needs: + - changes + - prepare-images + strategy: + matrix: + case: + - shenyu-integrated-test-k8s-ingress-http + - shenyu-integrated-test-k8s-ingress-apache-dubbo + - shenyu-integrated-test-k8s-ingress-motan + - shenyu-integrated-test-k8s-ingress-websocket + - shenyu-integrated-test-k8s-ingress-grpc + runs-on: ubuntu-latest + if: github.repository == 'apache/shenyu' && needs.changes.outputs.k8s-ingress == 'true' + steps: + - uses: actions/checkout@v3 + with: + submodules: true + + - name: Clean Space + run: | + sudo rm -rf /usr/share/dotnet + sudo rm -rf /opt/ghc + sudo rm -rf "/usr/local/share/boost" + sudo rm -rf "$AGENT_TOOLSDIRECTORY" + + - name: Restore Maven Repos + uses: actions/cache/restore@v3 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + + - uses: actions/setup-java@v4 + with: + java-version: 17 + distribution: "temurin" + + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.17.x + + - name: Install k8s + run: | + go install sigs.k8s.io/kind@v0.14.0 + curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.24.14/bin/linux/amd64/kubectl + sudo install kubectl /usr/local/bin/kubectl + kind create cluster --image=kindest/node:v1.21.1 --config=./shenyu-integrated-test/${{ matrix.case }}/deploy/kind-config.yaml + + - name: Install mvnd + shell: bash + run: | + MVND_VERSION=1.0.2 + curl -sL https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-linux-amd64.zip -o mvnd.zip + unzip -q mvnd.zip + mkdir -p $HOME/.local + mv maven-mvnd-${MVND_VERSION}-linux-amd64 $HOME/.local/mvnd + echo "$HOME/.local/mvnd/bin" >> $GITHUB_PATH + echo "MVND_HOME=$HOME/.local/mvnd" >> $GITHUB_ENV + + - name: Download prebuilt images + uses: actions/download-artifact@v4 + with: + name: shenyu-it-k8s-images + path: /tmp + + - name: Load prebuilt images + run: docker load --input /tmp/shenyu-it-k8s-images.tar + - name: Build k8s Cluster - if: steps.filter.outputs.k8s-ingress == 'true' run: bash ./shenyu-integrated-test/${{ matrix.case }}/script/build_k8s_cluster.sh - name: Wait for k8s Cluster Start up - if: steps.filter.outputs.k8s-ingress == 'true' timeout-minutes: 15 - run: | - bash ./shenyu-integrated-test/${{ matrix.case }}/script/healthcheck.sh + run: bash ./shenyu-integrated-test/${{ matrix.case }}/script/healthcheck.sh - name: Run test id: test - if: steps.filter.outputs.k8s-ingress == 'true' shell: bash run: | if mvnd --version > /dev/null 2>&1; then @@ -199,16 +246,11 @@ jobs: mvnd test -Pit -f ./shenyu-integrated-test/${{ matrix.case }}/pom.xml else echo "Falling back to maven wrapper for tests" - if [[ "${{ runner.os }}" == "Windows" ]]; then - ./mvnw.cmd test -Pit -f ./shenyu-integrated-test/${{ matrix.case }}/pom.xml - else - ./mvnw test -Pit -f ./shenyu-integrated-test/${{ matrix.case }}/pom.xml - fi + ./mvnw test -Pit -f ./shenyu-integrated-test/${{ matrix.case }}/pom.xml fi continue-on-error: true - name: Cluster Test after Healthcheck - if: steps.filter.outputs.k8s-ingress == 'true' run: | echo "----------kubectl get all -o wide----------" kubectl get all -o wide @@ -218,7 +260,7 @@ jobs: kubectl get events --all-namespaces echo "----------kubectl logs -l app=shenyu-ingress-controller -n shenyu-ingress --tail=-1----------" kubectl logs -l app=shenyu-ingress-controller -n shenyu-ingress --tail=-1 - if [[ ${{steps.test.outcome}} == "failure" ]]; then + if [[ ${{ steps.test.outcome }} == "failure" ]]; then echo "Test Failed" exit 1 else diff --git a/.github/workflows/integrated-test.yml b/.github/workflows/integrated-test.yml index 9afc310f1c2f..fd82ff314add 100644 --- a/.github/workflows/integrated-test.yml +++ b/.github/workflows/integrated-test.yml @@ -15,6 +15,10 @@ name: it +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + on: pull_request: push: diff --git a/.github/workflows/k8s-examples-http.yml b/.github/workflows/k8s-examples-http.yml index 7f3cb06de7db..68c67f15a4cc 100644 --- a/.github/workflows/k8s-examples-http.yml +++ b/.github/workflows/k8s-examples-http.yml @@ -15,6 +15,10 @@ name: k8s-examples-http +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + on: pull_request: push: From 1d94fb91090395db9c047587e20d6bac744bac85 Mon Sep 17 00:00:00 2001 From: liuhy Date: Wed, 15 Apr 2026 09:48:26 +0800 Subject: [PATCH 3/7] Validate workflow concurrency cancellation on follow-up PR updates This empty commit exists to verify that the newly added workflow-level concurrency keys cancel obsolete runs for the same pull request instead of letting queued heavy workflows accumulate. Constraint: Validation should exercise the real PR workflow path without altering CI logic again Rejected: Manual re-run from the GitHub UI | does not verify cancel-in-progress behavior on new commits Confidence: medium Scope-risk: narrow Reversibility: clean Directive: Drop this commit from final history only if project history policy requires squashing PR validation noise Tested: Commit creation only Not-tested: Resulting run cancellation until GitHub reports updated statuses From 0a99dbd0c4ccd351617b5ad09681712b0a1ec048 Mon Sep 17 00:00:00 2001 From: liuhy Date: Wed, 15 Apr 2026 10:04:43 +0800 Subject: [PATCH 4/7] Reduce follow-up rebuild work in deduplicated CI flows The first pass removed duplicated work across matrix jobs, but the prepare jobs still used repeated `clean install` calls that threw away outputs from prior steps. This follow-up keeps the workflow shape intact while letting the later Maven invocations reuse artifacts from earlier phases. It also updates `e2e-k8s.yml` checkout steps to v4 so the workflow no longer mixes in the deprecated v2 action. Constraint: Keep the new prepare-once/run-many workflow topology unchanged while addressing review feedback Rejected: Merge all Maven/profile work into one invocation | higher risk without validating profile interactions in this repo Confidence: medium Scope-risk: narrow Reversibility: clean Directive: If prepare jobs remain the bottleneck after this change, profile consolidation is the next place to investigate Tested: YAML parse for modified workflows; actionlint on modified workflows with repo-specific false-positive filters; git diff --check Not-tested: Live GitHub Actions runtime after removing `clean` from prepare-stage Maven invocations --- .github/workflows/e2e-k8s.yml | 12 ++++++------ .github/workflows/integrated-test-k8s-ingress.yml | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/e2e-k8s.yml b/.github/workflows/e2e-k8s.yml index cc99de1d6b3b..00b7d5a5fc68 100644 --- a/.github/workflows/e2e-k8s.yml +++ b/.github/workflows/e2e-k8s.yml @@ -31,7 +31,7 @@ jobs: outputs: e2e: ${{ steps.filter.outputs.e2e }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true @@ -61,7 +61,7 @@ jobs: if: github.repository == 'apache/shenyu' && needs.changes.outputs.e2e == 'true' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true @@ -117,10 +117,10 @@ jobs: run: | if mvnd --version > /dev/null 2>&1; then echo "Using mvnd for build examples" - mvnd -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml + mvnd -B install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml else echo "Falling back to maven wrapper for examples" - ./mvnw -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml + ./mvnw -B install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml fi - name: Save ShenYu Maven Repos @@ -181,7 +181,7 @@ jobs: - case: shenyu-e2e-case-storage script: e2e-opengauss-compose steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: true @@ -255,7 +255,7 @@ jobs: # - case: shenyu-e2e-case-logging-kafka # script: e2e-logging-kafka-compose steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: true diff --git a/.github/workflows/integrated-test-k8s-ingress.yml b/.github/workflows/integrated-test-k8s-ingress.yml index 8b40cce88e66..d14c4a1c7a4a 100644 --- a/.github/workflows/integrated-test-k8s-ingress.yml +++ b/.github/workflows/integrated-test-k8s-ingress.yml @@ -102,10 +102,10 @@ jobs: run: | if mvnd --version > /dev/null 2>&1; then echo "Using mvnd for build" - mvnd -B clean install -Dmaven.javadoc.skip=true -Dmaven.test.skip=true + mvnd -B install -Dmaven.javadoc.skip=true -Dmaven.test.skip=true else echo "Falling back to maven wrapper" - ./mvnw -B clean install -Dmaven.javadoc.skip=true -Dmaven.test.skip=true + ./mvnw -B install -Dmaven.javadoc.skip=true -Dmaven.test.skip=true fi - name: Build integrated tests @@ -113,10 +113,10 @@ jobs: run: | if mvnd --version > /dev/null 2>&1; then echo "Using mvnd for build integrated tests" - mvnd -B clean install -Pit -DskipTests -am -f ./shenyu-integrated-test/pom.xml + mvnd -B install -Pit -DskipTests -am -f ./shenyu-integrated-test/pom.xml else echo "Falling back to maven wrapper for integrated tests" - ./mvnw -B clean install -Pit -DskipTests -am -f ./shenyu-integrated-test/pom.xml + ./mvnw -B install -Pit -DskipTests -am -f ./shenyu-integrated-test/pom.xml fi - name: Build examples @@ -124,10 +124,10 @@ jobs: run: | if mvnd --version > /dev/null 2>&1; then echo "Using mvnd for build examples" - mvnd -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml + mvnd -B install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml else echo "Falling back to maven wrapper for examples" - ./mvnw -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml + ./mvnw -B install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml fi - name: Export prebuilt images From 122ee19ec464c3295ab49d2855da7e8940c10670 Mon Sep 17 00:00:00 2001 From: liuhy Date: Wed, 15 Apr 2026 10:24:19 +0800 Subject: [PATCH 5/7] Carry prepared local snapshots into it-k8s matrix runners The prepare job was installing local SNAPSHOT artifacts into its own Maven repository, but the matrix runners only restored the stale shared cache. That left modules like `shenyu-integrated-test-common` unresolved during the test step even though prepare-images had built them successfully. This change packages the prepared `org/apache/shenyu` subtree and restores it in each test runner before running Maven. Constraint: Matrix runners are isolated and cannot see the prepare job's local ~/.m2 state Rejected: Re-add per-case prepare builds | fixes the failure but gives back most of the deduplication win Confidence: high Scope-risk: narrow Reversibility: clean Directive: If artifact size becomes problematic, switch from subtree tarball transfer to a run-scoped cache key or a narrower module subset Tested: YAML parse; actionlint on the modified workflow with repo-specific false-positive filters; git diff --check Not-tested: Live GitHub Actions rerun after adding the local Maven artifact handoff --- .../workflows/integrated-test-k8s-ingress.yml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/integrated-test-k8s-ingress.yml b/.github/workflows/integrated-test-k8s-ingress.yml index d14c4a1c7a4a..37634079acbc 100644 --- a/.github/workflows/integrated-test-k8s-ingress.yml +++ b/.github/workflows/integrated-test-k8s-ingress.yml @@ -145,6 +145,10 @@ jobs: apache/shenyu-integrated-test-k8s-ingress-grpc:latest \ > /tmp/shenyu-it-k8s-images.tar + - name: Package local Maven artifacts + run: | + tar -C "$HOME/.m2/repository" -czf /tmp/shenyu-it-k8s-local-m2.tar.gz org/apache/shenyu + - name: Upload prebuilt images uses: actions/upload-artifact@v4 with: @@ -152,6 +156,13 @@ jobs: path: /tmp/shenyu-it-k8s-images.tar retention-days: 1 + - name: Upload local Maven artifacts + uses: actions/upload-artifact@v4 + with: + name: shenyu-it-k8s-local-m2 + path: /tmp/shenyu-it-k8s-local-m2.tar.gz + retention-days: 1 + - name: Save Maven Repos if: steps.restore-maven-cache.outputs.cache-hit != 'true' uses: actions/cache/save@v3 @@ -227,6 +238,17 @@ jobs: name: shenyu-it-k8s-images path: /tmp + - name: Download local Maven artifacts + uses: actions/download-artifact@v4 + with: + name: shenyu-it-k8s-local-m2 + path: /tmp + + - name: Restore local Maven artifacts + run: | + mkdir -p "$HOME/.m2/repository" + tar -C "$HOME/.m2/repository" -xzf /tmp/shenyu-it-k8s-local-m2.tar.gz + - name: Load prebuilt images run: docker load --input /tmp/shenyu-it-k8s-images.tar From 05457d82e63f38e2ee85a4ce9e11c18a8b87b471 Mon Sep 17 00:00:00 2001 From: liuhy Date: Wed, 15 Apr 2026 11:31:38 +0800 Subject: [PATCH 6/7] Deduplicate integrated-test setup across matrix cases The integrated-test workflow was still rebuilding the same repo artifacts, example images, and integrated-test modules inside each of the 12 matrix cases. This change splits it into a changes gate, a one-time prepare job, and a matrix execution job that reuses prebuilt Docker images and local ShenYu SNAPSHOT Maven artifacts. Constraint: GitHub Actions matrix runners do not share local Docker or Maven state Constraint: Preserve the existing 12-case matrix and compose/test failure logging behavior Rejected: Keep per-case builds and optimize only cache keys | leaves the dominant repeated work in place Rejected: Add per-case artifact fan-out in the first pass | lower download cost, but more YAML complexity and higher failure surface Confidence: medium Scope-risk: moderate Reversibility: clean Directive: If CI runtime shifts from build CPU to artifact transfer, next optimize the snapshot bundle and image artifact granularity Tested: YAML parse for integrated-test.yml; bash -n for helper scripts; actionlint on integrated-test.yml with repo-specific false-positive filter; git diff --check; dry-run on both helper scripts Not-tested: End-to-end GitHub Actions execution for the refactored integrated-test workflow --- .../package-integrated-test-local-images.sh | 166 ++++++++++++ .../scripts/package-shenyu-maven-snapshots.sh | 130 +++++++++ .github/workflows/integrated-test.yml | 249 ++++++++++++------ 3 files changed, 466 insertions(+), 79 deletions(-) create mode 100755 .github/scripts/package-integrated-test-local-images.sh create mode 100755 .github/scripts/package-shenyu-maven-snapshots.sh diff --git a/.github/scripts/package-integrated-test-local-images.sh b/.github/scripts/package-integrated-test-local-images.sh new file mode 100755 index 000000000000..adf7a733b294 --- /dev/null +++ b/.github/scripts/package-integrated-test-local-images.sh @@ -0,0 +1,166 @@ +#!/usr/bin/env bash + +set -euo pipefail + +usage() { + cat <<'EOF' +Usage: package-integrated-test-local-images.sh [options] + +Create one tarball containing all local :latest Docker images referenced by the +matrix cases in .github/workflows/integrated-test.yml. + +Options: + --workflow FILE Workflow to inspect. Default: .github/workflows/integrated-test.yml + --compose-root DIR Compose root. Default: shenyu-integrated-test + --output FILE Output tar path. Default: ./artifacts/integrated-test-local-images.tar + --exclude-image IMG Exclude a specific image. Repeatable. + --exclude-file FILE Read excluded images from a file, one per line. + --image-regex REGEX Local image regex. Default: ^(apache/shenyu-|shenyu-).+:latest$ + --dry-run Print the images that would be packaged + -h, --help Show this help +EOF +} + +die() { + echo "error: $*" >&2 + exit 1 +} + +repo_root() { + git rev-parse --show-toplevel 2>/dev/null || pwd +} + +contains_exact() { + local needle="$1" + shift || true + local item + for item in "$@"; do + if [ "$item" = "$needle" ]; then + return 0 + fi + done + return 1 +} + +workflow="$(repo_root)/.github/workflows/integrated-test.yml" +compose_root="$(repo_root)/shenyu-integrated-test" +output="$(repo_root)/artifacts/integrated-test-local-images.tar" +image_regex='^(apache/shenyu-|shenyu-).+:latest$' +dry_run=0 +exclude_images=() + +while [ "$#" -gt 0 ]; do + case "$1" in + --workflow) + workflow="$2" + shift 2 + ;; + --compose-root) + compose_root="$2" + shift 2 + ;; + --output) + output="$2" + shift 2 + ;; + --exclude-image) + exclude_images+=("$2") + shift 2 + ;; + --exclude-file) + [ -f "$2" ] || die "exclude file not found: $2" + while IFS= read -r line || [ -n "$line" ]; do + case "$line" in + ''|\#*) + continue + ;; + *) + exclude_images+=("$line") + ;; + esac + done < "$2" + shift 2 + ;; + --image-regex) + image_regex="$2" + shift 2 + ;; + --dry-run) + dry_run=1 + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + die "unknown argument: $1" + ;; + esac +done + +command -v docker >/dev/null 2>&1 || die "docker is required" +[ -f "$workflow" ] || die "workflow not found: $workflow" +[ -d "$compose_root" ] || die "compose root not found: $compose_root" + +tmp_cases="$(mktemp "${TMPDIR:-/tmp}/shenyu-it-cases.XXXXXX")" +tmp_images="$(mktemp "${TMPDIR:-/tmp}/shenyu-it-images.XXXXXX")" +trap 'rm -f "$tmp_cases" "$tmp_images"' EXIT + +awk ' + $1 == "case:" { in_case = 1; next } + in_case && $1 == "runs-on:" { exit } + in_case && $1 == "-" { print $2 } +' "$workflow" > "$tmp_cases" + +[ -s "$tmp_cases" ] || die "no matrix cases found in $workflow" + +while IFS= read -r case_name; do + compose_file="${compose_root%/}/${case_name}/docker-compose.yml" + [ -f "$compose_file" ] || die "compose file not found for ${case_name}: ${compose_file}" + + docker compose -f "$compose_file" config --images 2>/dev/null \ + | grep -E "$image_regex" \ + >> "$tmp_images" || true +done < "$tmp_cases" + +sort -u "$tmp_images" -o "$tmp_images" + +if [ "${#exclude_images[@]}" -gt 0 ]; then + tmp_filtered="$(mktemp "${TMPDIR:-/tmp}/shenyu-it-images-filtered.XXXXXX")" + trap 'rm -f "$tmp_cases" "$tmp_images" "$tmp_filtered"' EXIT + + while IFS= read -r image; do + if contains_exact "$image" "${exclude_images[@]}"; then + continue + fi + printf '%s\n' "$image" + done < "$tmp_images" > "$tmp_filtered" + + mv "$tmp_filtered" "$tmp_images" +fi + +[ -s "$tmp_images" ] || die "no matching local images found" + +if [ "$dry_run" -eq 1 ]; then + cat "$tmp_images" + exit 0 +fi + +while IFS= read -r image; do + docker image inspect "$image" >/dev/null 2>&1 || die "local image not found: $image" +done < "$tmp_images" + +mkdir -p "$(dirname "$output")" + +images=() +while IFS= read -r image; do + images+=("$image") +done < "$tmp_images" + +docker save -o "$output" "${images[@]}" +cp "$tmp_images" "${output}.manifest.txt" + +count="$(wc -l < "$tmp_images" | tr -d ' ')" +echo "packaged ${count} images into ${output}" +echo "manifest written to ${output}.manifest.txt" diff --git a/.github/scripts/package-shenyu-maven-snapshots.sh b/.github/scripts/package-shenyu-maven-snapshots.sh new file mode 100755 index 000000000000..9e6b3a4efb95 --- /dev/null +++ b/.github/scripts/package-shenyu-maven-snapshots.sh @@ -0,0 +1,130 @@ +#!/usr/bin/env bash + +set -euo pipefail + +usage() { + cat <<'EOF' +Usage: package-shenyu-maven-snapshots.sh [options] + +Package local org/apache/shenyu SNAPSHOT artifacts from ~/.m2/repository into +one tarball that can be extracted into another runner's Maven repository. + +Options: + --repo DIR Maven repository root. Default: $HOME/.m2/repository + --group-path DIR Group path under the repository. Default: org/apache/shenyu + --version VER Snapshot version to package. Default: parsed from ./pom.xml + --output FILE Output tar.gz path. Default: ./artifacts/shenyu-maven-snapshots.tar.gz + --dry-run Print the files that would be packaged + -h, --help Show this help +EOF +} + +die() { + echo "error: $*" >&2 + exit 1 +} + +repo_root() { + git rev-parse --show-toplevel 2>/dev/null || pwd +} + +parse_version() { + local root + root="$(repo_root)" + + perl -0777 -ne ' + if (m{\s*shenyu\s*.*?\s*([^<]+)\s*}s) { + print $1; + exit 0; + } + exit 1; + ' "$root/pom.xml" +} + +repo="${HOME}/.m2/repository" +group_path="org/apache/shenyu" +version="" +output="" +dry_run=0 + +while [ "$#" -gt 0 ]; do + case "$1" in + --repo) + repo="$2" + shift 2 + ;; + --group-path) + group_path="$2" + shift 2 + ;; + --version) + version="$2" + shift 2 + ;; + --output) + output="$2" + shift 2 + ;; + --dry-run) + dry_run=1 + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + die "unknown argument: $1" + ;; + esac +done + +[ -d "$repo" ] || die "maven repository not found: $repo" + +if [ -z "$version" ]; then + version="$(parse_version)" || die "failed to parse project version from pom.xml" +fi + +if [ -z "$output" ]; then + output="$(repo_root)/artifacts/shenyu-maven-snapshots.tar.gz" +fi + +search_root="${repo%/}/${group_path}" +[ -d "$search_root" ] || die "group path not found in repository: $search_root" + +tmp_list="$(mktemp "${TMPDIR:-/tmp}/shenyu-maven-snapshots.XXXXXX")" +trap 'rm -f "$tmp_list"' EXIT + +find "$search_root" -type d -path "*/${version}" | while IFS= read -r version_dir; do + find "$version_dir" -maxdepth 1 -type f \ + \( -name '*.pom' -o -name '*.jar' -o -name '_remote.repositories' \) \ + ! -name '*-sources.jar' \ + ! -name '*-javadoc.jar' \ + ! -name '*.lastUpdated' \ + | while IFS= read -r artifact_file; do + printf '%s\n' "${artifact_file#${repo%/}/}" + done + + artifact_dir="$(dirname "$version_dir")" + metadata="${artifact_dir}/maven-metadata-local.xml" + if [ -f "$metadata" ]; then + printf '%s\n' "${metadata#${repo%/}/}" + fi +done | sort -u > "$tmp_list" + +if [ ! -s "$tmp_list" ]; then + die "no ${version} artifacts found under ${search_root}" +fi + +if [ "$dry_run" -eq 1 ]; then + cat "$tmp_list" + exit 0 +fi + +mkdir -p "$(dirname "$output")" +tar -C "$repo" -czf "$output" -T "$tmp_list" +cp "$tmp_list" "${output}.manifest.txt" + +count="$(wc -l < "$tmp_list" | tr -d ' ')" +echo "packaged ${count} paths into ${output}" +echo "manifest written to ${output}.manifest.txt" diff --git a/.github/workflows/integrated-test.yml b/.github/workflows/integrated-test.yml index fd82ff314add..c2698595df53 100644 --- a/.github/workflows/integrated-test.yml +++ b/.github/workflows/integrated-test.yml @@ -25,40 +25,20 @@ on: branches: - master +env: + MVND_VERSION: 1.0.2 + IT_IMAGES_ARTIFACT: shenyu-it-images + IT_LOCAL_M2_ARTIFACT: shenyu-it-local-m2 + jobs: - build: - strategy: - matrix: - case: - - shenyu-integrated-test-apache-dubbo - - shenyu-integrated-test-grpc - - shenyu-integrated-test-http - - shenyu-integrated-test-https - - shenyu-integrated-test-motan - - shenyu-integrated-test-spring-cloud - - shenyu-integrated-test-sofa - - shenyu-integrated-test-websocket - - shenyu-integrated-test-rewrite - - shenyu-integrated-test-combination - - shenyu-integrated-test-sdk-apache-dubbo - - shenyu-integrated-test-sdk-http + changes: runs-on: ubuntu-latest - if: (github.repository == 'apache/shenyu') + outputs: + integration: ${{ steps.filter.outputs.integration }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - # Copied from https://github.com/jens-maus/RaspberryMatic/blob/ea6b8ce0dd2d53ea88b2766ba8d7f8e1d667281f/.github/workflows/ci.yml#L34-L40 - # and https://github.com/actions/virtual-environments/issues/709#issuecomment-612569242 - - name: Free disk space - run: | - df --human-readable - sudo apt clean - for image in $(docker image ls --all --quiet); do - docker rmi $image - done - rm --recursive --force "$AGENT_TOOLSDIRECTORY" - df --human-readable - uses: ./actions/paths-filter id: filter with: @@ -79,41 +59,53 @@ jobs: - '!NOTICE' - '!.github/ISSUE_TEMPLATE/**' - '!.github/PULL_REQUEST_TEMPLATE' + + prepare-images: + needs: changes + runs-on: ubuntu-latest + if: github.repository == 'apache/shenyu' && needs.changes.outputs.integration == 'true' + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + # Copied from https://github.com/jens-maus/RaspberryMatic/blob/ea6b8ce0dd2d53ea88b2766ba8d7f8e1d667281f/.github/workflows/ci.yml#L34-L40 + # and https://github.com/actions/virtual-environments/issues/709#issuecomment-612569242 + - name: Free disk space + run: | + df --human-readable + sudo apt clean + for image in $(docker image ls --all --quiet); do + docker rmi "$image" + done + rm --recursive --force "$AGENT_TOOLSDIRECTORY" + df --human-readable + - name: Restore ShenYu Maven Repos - if: steps.filter.outputs.integration == 'true' - uses: actions/cache/restore@v3 + id: restore-maven-cache + uses: actions/cache/restore@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- + - uses: actions/setup-java@v4 - if: steps.filter.outputs.integration == 'true' with: java-version: 17 distribution: "temurin" + - name: Install mvnd - if: steps.filter.outputs.integration == 'true' shell: bash run: | - MVND_VERSION=1.0.2 - if [[ "${{ runner.os }}" == "Windows" ]]; then - curl -sL https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-windows-amd64.zip -o mvnd.zip - unzip -q mvnd.zip - mkdir -p $HOME/.local - mv maven-mvnd-${MVND_VERSION}-windows-amd64 $HOME/.local/mvnd - echo "$HOME/.local/mvnd/bin" >> $GITHUB_PATH - echo "MVND_HOME=$HOME/.local/mvnd" >> $GITHUB_ENV - else - curl -sL https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-linux-amd64.zip -o mvnd.zip - unzip -q mvnd.zip - mkdir -p $HOME/.local - mv maven-mvnd-${MVND_VERSION}-linux-amd64 $HOME/.local/mvnd - echo "$HOME/.local/mvnd/bin" >> $GITHUB_PATH - echo "MVND_HOME=$HOME/.local/mvnd" >> $GITHUB_ENV - fi + curl -sL "https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-linux-amd64.zip" -o mvnd.zip + unzip -q mvnd.zip + mkdir -p "$HOME/.local" + mv "maven-mvnd-${MVND_VERSION}-linux-amd64" "$HOME/.local/mvnd" + echo "$HOME/.local/mvnd/bin" >> "$GITHUB_PATH" + echo "MVND_HOME=$HOME/.local/mvnd" >> "$GITHUB_ENV" + - name: Build with Maven - if: steps.filter.outputs.integration == 'true' shell: bash run: | if mvnd --version > /dev/null 2>&1; then @@ -121,54 +113,157 @@ jobs: mvnd -B clean install -Prelease,docker -Dmaven.javadoc.skip=true -Dmaven.test.skip=true else echo "Falling back to maven wrapper" - if [[ "${{ runner.os }}" == "Windows" ]]; then - ./mvnw.cmd -B clean install -Prelease,docker -Dmaven.javadoc.skip=true -Dmaven.test.skip=true - else - ./mvnw -B clean install -Prelease,docker -Dmaven.javadoc.skip=true -Dmaven.test.skip=true - fi + ./mvnw -B clean install -Prelease,docker -Dmaven.javadoc.skip=true -Dmaven.test.skip=true fi + - name: Build examples - if: steps.filter.outputs.integration == 'true' shell: bash run: | if mvnd --version > /dev/null 2>&1; then echo "Using mvnd for build examples" - mvnd -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml + mvnd -B install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml else echo "Falling back to maven wrapper for examples" - if [[ "${{ runner.os }}" == "Windows" ]]; then - ./mvnw.cmd -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml - else - ./mvnw -B clean install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml - fi + ./mvnw -B install -Pexample -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -am -f ./shenyu-examples/pom.xml fi + - name: Build integrated tests - if: steps.filter.outputs.integration == 'true' shell: bash run: | if mvnd --version > /dev/null 2>&1; then echo "Using mvnd for build integrated tests" - mvnd -B clean install -Pit -DskipTests -f ./shenyu-integrated-test/pom.xml + mvnd -B install -Pit -DskipTests -f ./shenyu-integrated-test/pom.xml else echo "Falling back to maven wrapper for integrated tests" - if [[ "${{ runner.os }}" == "Windows" ]]; then - ./mvnw.cmd -B clean install -Pit -DskipTests -f ./shenyu-integrated-test/pom.xml - else - ./mvnw -B clean install -Pit -DskipTests -f ./shenyu-integrated-test/pom.xml - fi + ./mvnw -B install -Pit -DskipTests -f ./shenyu-integrated-test/pom.xml fi + + - name: Export prebuilt images + run: | + bash .github/scripts/package-integrated-test-local-images.sh \ + --output /tmp/shenyu-it-images.tar + + - name: Package local Maven artifacts + run: | + bash .github/scripts/package-shenyu-maven-snapshots.sh \ + --output /tmp/shenyu-it-local-m2.tar.gz + + - name: Upload prebuilt images + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_IMAGES_ARTIFACT }} + path: /tmp/shenyu-it-images.tar + retention-days: 1 + compression-level: 0 + + - name: Upload local Maven artifacts + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_LOCAL_M2_ARTIFACT }} + path: /tmp/shenyu-it-local-m2.tar.gz + retention-days: 1 + compression-level: 0 + + - name: Save ShenYu Maven Repos + if: steps.restore-maven-cache.outputs.cache-hit != 'true' + uses: actions/cache/save@v4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + + build: + needs: + - changes + - prepare-images + strategy: + matrix: + case: + - shenyu-integrated-test-apache-dubbo + - shenyu-integrated-test-grpc + - shenyu-integrated-test-http + - shenyu-integrated-test-https + - shenyu-integrated-test-motan + - shenyu-integrated-test-spring-cloud + - shenyu-integrated-test-sofa + - shenyu-integrated-test-websocket + - shenyu-integrated-test-rewrite + - shenyu-integrated-test-combination + - shenyu-integrated-test-sdk-apache-dubbo + - shenyu-integrated-test-sdk-http + runs-on: ubuntu-latest + if: github.repository == 'apache/shenyu' && needs.changes.outputs.integration == 'true' + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + # Copied from https://github.com/jens-maus/RaspberryMatic/blob/ea6b8ce0dd2d53ea88b2766ba8d7f8e1d667281f/.github/workflows/ci.yml#L34-L40 + # and https://github.com/actions/virtual-environments/issues/709#issuecomment-612569242 + - name: Free disk space + run: | + df --human-readable + sudo apt clean + for image in $(docker image ls --all --quiet); do + docker rmi "$image" + done + rm --recursive --force "$AGENT_TOOLSDIRECTORY" + df --human-readable + + - name: Restore ShenYu Maven Repos + uses: actions/cache/restore@v4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + + - uses: actions/setup-java@v4 + with: + java-version: 17 + distribution: "temurin" + + - name: Install mvnd + shell: bash + run: | + curl -sL "https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-linux-amd64.zip" -o mvnd.zip + unzip -q mvnd.zip + mkdir -p "$HOME/.local" + mv "maven-mvnd-${MVND_VERSION}-linux-amd64" "$HOME/.local/mvnd" + echo "$HOME/.local/mvnd/bin" >> "$GITHUB_PATH" + echo "MVND_HOME=$HOME/.local/mvnd" >> "$GITHUB_ENV" + + - name: Download prebuilt images + uses: actions/download-artifact@v4 + with: + name: ${{ env.IT_IMAGES_ARTIFACT }} + path: /tmp + + - name: Download local Maven artifacts + uses: actions/download-artifact@v4 + with: + name: ${{ env.IT_LOCAL_M2_ARTIFACT }} + path: /tmp + + - name: Restore local Maven artifacts + run: | + mkdir -p "$HOME/.m2/repository" + tar -C "$HOME/.m2/repository" -xzf /tmp/shenyu-it-local-m2.tar.gz + + - name: Load prebuilt images + run: docker load --input /tmp/shenyu-it-images.tar + - name: Start docker compose - if: steps.filter.outputs.integration == 'true' run: docker compose -f ./shenyu-integrated-test/${{ matrix.case }}/docker-compose.yml up -d + - name: Wait for docker compose start up completely - if: steps.filter.outputs.integration == 'true' run: bash ./shenyu-integrated-test/${{ matrix.case }}/script/healthcheck.sh + - name: Disk space info run: | df --human-readable + - name: Run test id: test - if: steps.filter.outputs.integration == 'true' shell: bash run: | if mvnd --version > /dev/null 2>&1; then @@ -176,18 +271,14 @@ jobs: mvnd test -Pit -f ./shenyu-integrated-test/${{ matrix.case }}/pom.xml else echo "Falling back to maven wrapper for tests" - if [[ "${{ runner.os }}" == "Windows" ]]; then - ./mvnw.cmd test -Pit -f ./shenyu-integrated-test/${{ matrix.case }}/pom.xml - else - ./mvnw test -Pit -f ./shenyu-integrated-test/${{ matrix.case }}/pom.xml - fi + ./mvnw test -Pit -f ./shenyu-integrated-test/${{ matrix.case }}/pom.xml fi continue-on-error: true + - name: Check test result - if: steps.filter.outputs.integration == 'true' run: | docker compose -f ./shenyu-integrated-test/${{ matrix.case }}/docker-compose.yml logs --tail="all" - if [[ ${{steps.test.outcome}} == "failure" ]]; then + if [[ ${{ steps.test.outcome }} == "failure" ]]; then echo "Test Failed" exit 1 else From 4f10590383f8b1497e1f2c273c5552cd76ee5fdb Mon Sep 17 00:00:00 2001 From: liuhy Date: Wed, 15 Apr 2026 12:17:51 +0800 Subject: [PATCH 7/7] Reduce integrated-test artifact transfer on the critical path The first prepare-once/run-many pass made integrated-test correct but slower in wall-clock because every matrix leg downloaded the same union image tar and the same broad local Maven snapshot bundle. This change splits the Docker transfer into a shared admin image plus per-case overlays and narrows the snapshot bundle by default to only jars and poms that Maven resolves during the test phase. Constraint: Preserve the 12-case matrix and existing docker-compose/test failure logging behavior Constraint: Keep the successful prepare-once/run-many topology instead of reintroducing per-case full rebuilds Rejected: Revert to per-case local image builds | likely improves wall-clock but restores the larger duplicated build path and changes the optimization direction Rejected: Keep a single shared all-images tar and only trim Maven metadata | does not address the dominant long-tail case download cost Confidence: medium Scope-risk: moderate Reversibility: clean Directive: If this still does not recover enough wall-clock, the next experiment should be hybridizing image preparation rather than broadening artifact scope again Tested: YAML parse; bash -n on helper scripts; actionlint on integrated-test.yml with repo-specific false-positive filter; git diff --check; dry-run counts for per-case image packaging and slim-vs-full Maven snapshot manifests Not-tested: End-to-end GitHub Actions execution for the second-pass integrated-test artifact layout --- .../package-integrated-test-local-images.sh | 28 ++- .../scripts/package-shenyu-maven-snapshots.sh | 25 ++- .github/workflows/integrated-test.yml | 185 ++++++++++++++++-- 3 files changed, 210 insertions(+), 28 deletions(-) diff --git a/.github/scripts/package-integrated-test-local-images.sh b/.github/scripts/package-integrated-test-local-images.sh index adf7a733b294..4e712a350ffa 100755 --- a/.github/scripts/package-integrated-test-local-images.sh +++ b/.github/scripts/package-integrated-test-local-images.sh @@ -12,7 +12,9 @@ matrix cases in .github/workflows/integrated-test.yml. Options: --workflow FILE Workflow to inspect. Default: .github/workflows/integrated-test.yml --compose-root DIR Compose root. Default: shenyu-integrated-test + --case NAME Package images for one workflow matrix case. Repeatable. --output FILE Output tar path. Default: ./artifacts/integrated-test-local-images.tar + --exclude-admin Exclude apache/shenyu-admin:latest. --exclude-image IMG Exclude a specific image. Repeatable. --exclude-file FILE Read excluded images from a file, one per line. --image-regex REGEX Local image regex. Default: ^(apache/shenyu-|shenyu-).+:latest$ @@ -48,6 +50,7 @@ output="$(repo_root)/artifacts/integrated-test-local-images.tar" image_regex='^(apache/shenyu-|shenyu-).+:latest$' dry_run=0 exclude_images=() +selected_cases=() while [ "$#" -gt 0 ]; do case "$1" in @@ -59,10 +62,18 @@ while [ "$#" -gt 0 ]; do compose_root="$2" shift 2 ;; + --case) + selected_cases+=("$2") + shift 2 + ;; --output) output="$2" shift 2 ;; + --exclude-admin) + exclude_images+=("apache/shenyu-admin:latest") + shift + ;; --exclude-image) exclude_images+=("$2") shift 2 @@ -104,8 +115,9 @@ command -v docker >/dev/null 2>&1 || die "docker is required" [ -d "$compose_root" ] || die "compose root not found: $compose_root" tmp_cases="$(mktemp "${TMPDIR:-/tmp}/shenyu-it-cases.XXXXXX")" +tmp_cases_selected="$(mktemp "${TMPDIR:-/tmp}/shenyu-it-cases-selected.XXXXXX")" tmp_images="$(mktemp "${TMPDIR:-/tmp}/shenyu-it-images.XXXXXX")" -trap 'rm -f "$tmp_cases" "$tmp_images"' EXIT +trap 'rm -f "$tmp_cases" "$tmp_cases_selected" "$tmp_images"' EXIT awk ' $1 == "case:" { in_case = 1; next } @@ -115,6 +127,18 @@ awk ' [ -s "$tmp_cases" ] || die "no matrix cases found in $workflow" +if [ "${#selected_cases[@]}" -gt 0 ]; then + for selected_case in "${selected_cases[@]}"; do + if grep -Fxq "$selected_case" "$tmp_cases"; then + printf '%s\n' "$selected_case" >> "$tmp_cases_selected" + else + die "matrix case not found in $workflow: $selected_case" + fi + done + sort -u "$tmp_cases_selected" -o "$tmp_cases_selected" + mv "$tmp_cases_selected" "$tmp_cases" +fi + while IFS= read -r case_name; do compose_file="${compose_root%/}/${case_name}/docker-compose.yml" [ -f "$compose_file" ] || die "compose file not found for ${case_name}: ${compose_file}" @@ -128,7 +152,7 @@ sort -u "$tmp_images" -o "$tmp_images" if [ "${#exclude_images[@]}" -gt 0 ]; then tmp_filtered="$(mktemp "${TMPDIR:-/tmp}/shenyu-it-images-filtered.XXXXXX")" - trap 'rm -f "$tmp_cases" "$tmp_images" "$tmp_filtered"' EXIT + trap 'rm -f "$tmp_cases" "$tmp_cases_selected" "$tmp_images" "$tmp_filtered"' EXIT while IFS= read -r image; do if contains_exact "$image" "${exclude_images[@]}"; then diff --git a/.github/scripts/package-shenyu-maven-snapshots.sh b/.github/scripts/package-shenyu-maven-snapshots.sh index 9e6b3a4efb95..de135328eb2b 100755 --- a/.github/scripts/package-shenyu-maven-snapshots.sh +++ b/.github/scripts/package-shenyu-maven-snapshots.sh @@ -14,6 +14,9 @@ Options: --group-path DIR Group path under the repository. Default: org/apache/shenyu --version VER Snapshot version to package. Default: parsed from ./pom.xml --output FILE Output tar.gz path. Default: ./artifacts/shenyu-maven-snapshots.tar.gz + --include-local-metadata + Include _remote.repositories and maven-metadata-local.xml + for compatibility fallback. Default: disabled --dry-run Print the files that would be packaged -h, --help Show this help EOF @@ -46,6 +49,7 @@ group_path="org/apache/shenyu" version="" output="" dry_run=0 +include_local_metadata=0 while [ "$#" -gt 0 ]; do case "$1" in @@ -65,6 +69,10 @@ while [ "$#" -gt 0 ]; do output="$2" shift 2 ;; + --include-local-metadata) + include_local_metadata=1 + shift + ;; --dry-run) dry_run=1 shift @@ -97,7 +105,7 @@ trap 'rm -f "$tmp_list"' EXIT find "$search_root" -type d -path "*/${version}" | while IFS= read -r version_dir; do find "$version_dir" -maxdepth 1 -type f \ - \( -name '*.pom' -o -name '*.jar' -o -name '_remote.repositories' \) \ + \( -name '*.pom' -o -name '*.jar' \) \ ! -name '*-sources.jar' \ ! -name '*-javadoc.jar' \ ! -name '*.lastUpdated' \ @@ -105,10 +113,17 @@ find "$search_root" -type d -path "*/${version}" | while IFS= read -r version_di printf '%s\n' "${artifact_file#${repo%/}/}" done - artifact_dir="$(dirname "$version_dir")" - metadata="${artifact_dir}/maven-metadata-local.xml" - if [ -f "$metadata" ]; then - printf '%s\n' "${metadata#${repo%/}/}" + if [ "$include_local_metadata" -eq 1 ]; then + metadata="${version_dir}/_remote.repositories" + if [ -f "$metadata" ]; then + printf '%s\n' "${metadata#${repo%/}/}" + fi + + artifact_dir="$(dirname "$version_dir")" + metadata="${artifact_dir}/maven-metadata-local.xml" + if [ -f "$metadata" ]; then + printf '%s\n' "${metadata#${repo%/}/}" + fi fi done | sort -u > "$tmp_list" diff --git a/.github/workflows/integrated-test.yml b/.github/workflows/integrated-test.yml index c2698595df53..9ebd962983c5 100644 --- a/.github/workflows/integrated-test.yml +++ b/.github/workflows/integrated-test.yml @@ -27,8 +27,10 @@ on: env: MVND_VERSION: 1.0.2 - IT_IMAGES_ARTIFACT: shenyu-it-images + IT_BASE_IMAGES_ARTIFACT: shenyu-it-images-base + IT_CASE_IMAGES_ARTIFACT_PREFIX: shenyu-it-images IT_LOCAL_M2_ARTIFACT: shenyu-it-local-m2 + IT_MVND_ARTIFACT: shenyu-it-mvnd jobs: changes: @@ -141,26 +143,156 @@ jobs: - name: Export prebuilt images run: | bash .github/scripts/package-integrated-test-local-images.sh \ - --output /tmp/shenyu-it-images.tar + --image-regex '^apache/shenyu-admin:latest$' \ + --output /tmp/shenyu-it-images-base.tar + + while read -r case_name; do + bash .github/scripts/package-integrated-test-local-images.sh \ + --case "$case_name" \ + --exclude-image apache/shenyu-admin:latest \ + --output "/tmp/shenyu-it-images-${case_name}.tar" + done <<'EOF' + shenyu-integrated-test-apache-dubbo + shenyu-integrated-test-grpc + shenyu-integrated-test-http + shenyu-integrated-test-https + shenyu-integrated-test-motan + shenyu-integrated-test-spring-cloud + shenyu-integrated-test-sofa + shenyu-integrated-test-websocket + shenyu-integrated-test-rewrite + shenyu-integrated-test-combination + shenyu-integrated-test-sdk-apache-dubbo + shenyu-integrated-test-sdk-http + EOF + + - name: Upload shared base image + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_BASE_IMAGES_ARTIFACT }} + path: /tmp/shenyu-it-images-base.tar + retention-days: 1 + compression-level: 0 + + - name: Upload case images for apache-dubbo + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_CASE_IMAGES_ARTIFACT_PREFIX }}-shenyu-integrated-test-apache-dubbo + path: /tmp/shenyu-it-images-shenyu-integrated-test-apache-dubbo.tar + retention-days: 1 + compression-level: 0 + + - name: Upload case images for grpc + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_CASE_IMAGES_ARTIFACT_PREFIX }}-shenyu-integrated-test-grpc + path: /tmp/shenyu-it-images-shenyu-integrated-test-grpc.tar + retention-days: 1 + compression-level: 0 + + - name: Upload case images for http + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_CASE_IMAGES_ARTIFACT_PREFIX }}-shenyu-integrated-test-http + path: /tmp/shenyu-it-images-shenyu-integrated-test-http.tar + retention-days: 1 + compression-level: 0 + + - name: Upload case images for https + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_CASE_IMAGES_ARTIFACT_PREFIX }}-shenyu-integrated-test-https + path: /tmp/shenyu-it-images-shenyu-integrated-test-https.tar + retention-days: 1 + compression-level: 0 + + - name: Upload case images for motan + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_CASE_IMAGES_ARTIFACT_PREFIX }}-shenyu-integrated-test-motan + path: /tmp/shenyu-it-images-shenyu-integrated-test-motan.tar + retention-days: 1 + compression-level: 0 + + - name: Upload case images for spring-cloud + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_CASE_IMAGES_ARTIFACT_PREFIX }}-shenyu-integrated-test-spring-cloud + path: /tmp/shenyu-it-images-shenyu-integrated-test-spring-cloud.tar + retention-days: 1 + compression-level: 0 + + - name: Upload case images for sofa + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_CASE_IMAGES_ARTIFACT_PREFIX }}-shenyu-integrated-test-sofa + path: /tmp/shenyu-it-images-shenyu-integrated-test-sofa.tar + retention-days: 1 + compression-level: 0 + + - name: Upload case images for websocket + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_CASE_IMAGES_ARTIFACT_PREFIX }}-shenyu-integrated-test-websocket + path: /tmp/shenyu-it-images-shenyu-integrated-test-websocket.tar + retention-days: 1 + compression-level: 0 + + - name: Upload case images for rewrite + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_CASE_IMAGES_ARTIFACT_PREFIX }}-shenyu-integrated-test-rewrite + path: /tmp/shenyu-it-images-shenyu-integrated-test-rewrite.tar + retention-days: 1 + compression-level: 0 + + - name: Upload case images for combination + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_CASE_IMAGES_ARTIFACT_PREFIX }}-shenyu-integrated-test-combination + path: /tmp/shenyu-it-images-shenyu-integrated-test-combination.tar + retention-days: 1 + compression-level: 0 + + - name: Upload case images for sdk-apache-dubbo + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_CASE_IMAGES_ARTIFACT_PREFIX }}-shenyu-integrated-test-sdk-apache-dubbo + path: /tmp/shenyu-it-images-shenyu-integrated-test-sdk-apache-dubbo.tar + retention-days: 1 + compression-level: 0 + + - name: Upload case images for sdk-http + uses: actions/upload-artifact@v4 + with: + name: ${{ env.IT_CASE_IMAGES_ARTIFACT_PREFIX }}-shenyu-integrated-test-sdk-http + path: /tmp/shenyu-it-images-shenyu-integrated-test-sdk-http.tar + retention-days: 1 + compression-level: 0 - name: Package local Maven artifacts run: | bash .github/scripts/package-shenyu-maven-snapshots.sh \ --output /tmp/shenyu-it-local-m2.tar.gz - - name: Upload prebuilt images + - name: Package mvnd + run: tar -C "$HOME/.local" -czf /tmp/shenyu-it-mvnd.tar.gz mvnd + + - name: Upload local Maven artifacts uses: actions/upload-artifact@v4 with: - name: ${{ env.IT_IMAGES_ARTIFACT }} - path: /tmp/shenyu-it-images.tar + name: ${{ env.IT_LOCAL_M2_ARTIFACT }} + path: | + /tmp/shenyu-it-local-m2.tar.gz + /tmp/shenyu-it-local-m2.tar.gz.* retention-days: 1 compression-level: 0 - - name: Upload local Maven artifacts + - name: Upload mvnd uses: actions/upload-artifact@v4 with: - name: ${{ env.IT_LOCAL_M2_ARTIFACT }} - path: /tmp/shenyu-it-local-m2.tar.gz + name: ${{ env.IT_MVND_ARTIFACT }} + path: /tmp/shenyu-it-mvnd.tar.gz retention-days: 1 compression-level: 0 @@ -222,20 +354,10 @@ jobs: java-version: 17 distribution: "temurin" - - name: Install mvnd - shell: bash - run: | - curl -sL "https://downloads.apache.org/maven/mvnd/${MVND_VERSION}/maven-mvnd-${MVND_VERSION}-linux-amd64.zip" -o mvnd.zip - unzip -q mvnd.zip - mkdir -p "$HOME/.local" - mv "maven-mvnd-${MVND_VERSION}-linux-amd64" "$HOME/.local/mvnd" - echo "$HOME/.local/mvnd/bin" >> "$GITHUB_PATH" - echo "MVND_HOME=$HOME/.local/mvnd" >> "$GITHUB_ENV" - - - name: Download prebuilt images + - name: Download shared build toolchain uses: actions/download-artifact@v4 with: - name: ${{ env.IT_IMAGES_ARTIFACT }} + name: ${{ env.IT_MVND_ARTIFACT }} path: /tmp - name: Download local Maven artifacts @@ -244,13 +366,34 @@ jobs: name: ${{ env.IT_LOCAL_M2_ARTIFACT }} path: /tmp + - name: Download shared base images + uses: actions/download-artifact@v4 + with: + name: ${{ env.IT_BASE_IMAGES_ARTIFACT }} + path: /tmp + + - name: Download current-case images + uses: actions/download-artifact@v4 + with: + name: ${{ format('{0}-{1}', env.IT_CASE_IMAGES_ARTIFACT_PREFIX, matrix.case) }} + path: /tmp + + - name: Restore mvnd + run: | + mkdir -p "$HOME/.local" + tar -C "$HOME/.local" -xzf /tmp/shenyu-it-mvnd.tar.gz + echo "$HOME/.local/mvnd/bin" >> "$GITHUB_PATH" + echo "MVND_HOME=$HOME/.local/mvnd" >> "$GITHUB_ENV" + - name: Restore local Maven artifacts run: | mkdir -p "$HOME/.m2/repository" tar -C "$HOME/.m2/repository" -xzf /tmp/shenyu-it-local-m2.tar.gz - name: Load prebuilt images - run: docker load --input /tmp/shenyu-it-images.tar + run: | + docker load --input /tmp/shenyu-it-images-base.tar + docker load --input /tmp/shenyu-it-images-${{ matrix.case }}.tar - name: Start docker compose run: docker compose -f ./shenyu-integrated-test/${{ matrix.case }}/docker-compose.yml up -d