This is an automated email from the ASF dual-hosted git repository.

terrymanu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new f6e3a5732e9 Unify E2E artifact preparation and restoration (#40109)
f6e3a5732e9 is described below

commit f6e3a5732e92462b9f00498b6b1839ff25f25aaf
Author: Liang Zhang <[email protected]>
AuthorDate: Fri Oct 9 12:54:25 2026 +0800

    Unify E2E artifact preparation and restoration (#40109)
    
    * Fix CI defaults for fork pull requests
    
    * Unify E2E artifact preparation and restoration
---
 .github/actions/download-e2e-artifacts/action.yml  | 111 +++++++---
 .github/actions/prepare-e2e-docker/action.yml      | 233 +++++++++++++++++++++
 .github/actions/save-maven-cache/action.yml        |  10 +-
 .github/actions/setup-build-environment/action.yml |  49 ++++-
 .github/actions/upload-e2e-artifacts/action.yml    |  95 ++++++---
 .github/workflows/e2e-agent.yml                    |  96 ++++++---
 .github/workflows/e2e-mcp.yml                      | 134 +++++++-----
 .github/workflows/e2e-operation.yml                |  54 +++--
 .github/workflows/e2e-sql.yml                      |  73 ++++---
 .github/workflows/nightly-e2e-operation.yml        |  54 +++--
 .github/workflows/nightly-e2e-sql.yml              |  45 ++--
 test/e2e/agent/engine/pom.xml                      |   3 -
 test/e2e/fixture/pom.xml                           |   5 +-
 .../test/resources/docker/conformance/Dockerfile   |  27 +--
 14 files changed, 739 insertions(+), 250 deletions(-)

diff --git a/.github/actions/download-e2e-artifacts/action.yml 
b/.github/actions/download-e2e-artifacts/action.yml
index 81b814db447..f8d35ce3155 100644
--- a/.github/actions/download-e2e-artifacts/action.yml
+++ b/.github/actions/download-e2e-artifacts/action.yml
@@ -19,51 +19,114 @@ name: 'Download E2E Artifacts'
 description: 'Download and restore E2E build artifacts including Maven 
repository and Docker image'
 
 inputs:
-  artifact-name:
-    description: 'Downloaded artifact name'
-    required: false
-    default: 'build-outputs'
-  artifact-dir:
-    description: 'Directory used to download packaged artifacts'
-    required: false
-    default: '/tmp/e2e-build-artifacts'
+  artifact-id:
+    description: 'Artifact ID returned by the producing job'
+    required: true
   restore-maven-repository:
     description: 'Whether to restore the ShardingSphere Maven repository 
output'
     required: false
     default: 'true'
+  maven-repository-dir:
+    description: 'Maven repository directory, defaulting to ~/.m2/repository'
+    required: false
+    default: ''
   load-docker-image:
     description: 'Whether to load the Docker image after download'
     required: false
     default: 'true'
-  docker-image-archives:
-    description: 'Docker image archive file names to load from artifact-dir, 
one per line'
+  restore-distribution:
+    description: 'Whether to restore the MCP distribution home'
     required: false
-    default: 'apache-shardingsphere-proxy-test.tar'
+    default: 'false'
+
+outputs:
+  image:
+    description: 'Private image reference restored for this consumer'
+    value: ${{ steps.load-image.outputs.image }}
 
 runs:
   using: composite
   steps:
+    - name: Prepare E2E Artifact Download
+      id: staging
+      shell: bash
+      env:
+        ARTIFACT_ID: ${{ inputs.artifact-id }}
+      run: |
+        set -euo pipefail
+        if [[ -z "$ARTIFACT_ID" ]]; then
+          echo '::error::The artifact ID is required.'
+          exit 1
+        fi
+        artifact_dir="$(mktemp -d 
"/tmp/shardingsphere-e2e-${GITHUB_SHA}.XXXXXX")"
+        echo "artifact-dir=$artifact_dir" >> "$GITHUB_OUTPUT"
     - name: Download Build Artifacts
       uses: actions/download-artifact@v8
       with:
-        name: ${{ inputs.artifact-name }}
-        path: ${{ inputs.artifact-dir }}
+        artifact-ids: ${{ inputs.artifact-id }}
+        path: ${{ steps.staging.outputs.artifact-dir }}
+    - name: Verify E2E Build Identity
+      shell: bash
+      env:
+        ARTIFACT_DIR: ${{ steps.staging.outputs.artifact-dir }}
+        RESTORE_MAVEN_REPOSITORY: ${{ inputs.restore-maven-repository }}
+        RESTORE_DISTRIBUTION: ${{ inputs.restore-distribution }}
+        LOAD_DOCKER_IMAGE: ${{ inputs.load-docker-image }}
+      run: |
+        set -euo pipefail
+        required_files=(build-identity.json)
+        if [[ "$RESTORE_MAVEN_REPOSITORY" == 'true' ]]; then
+          required_files+=(maven-repo-output.tar.gz)
+        fi
+        if [[ "$RESTORE_DISTRIBUTION" == 'true' ]]; then
+          required_files+=(mcp-distribution-home.tar.gz)
+        fi
+        if [[ "$LOAD_DOCKER_IMAGE" == 'true' ]]; then
+          required_files+=(image.tar image.tar.json)
+        fi
+        for file in "${required_files[@]}"; do
+          if [[ ! -f "$ARTIFACT_DIR/$file" ]]; then
+            echo "::error::The downloaded artifact is missing $file."
+            exit 1
+          fi
+        done
+        if ! jq -e --arg source_sha "$GITHUB_SHA" \
+          '.source_sha == $source_sha' "$ARTIFACT_DIR/build-identity.json"; 
then
+          echo '::error::The downloaded artifact does not match the source 
commit.'
+          exit 1
+        fi
     - name: Restore shardingsphere Maven Repository
       if: inputs.restore-maven-repository == 'true'
       shell: bash
+      env:
+        ARTIFACT_DIR: ${{ steps.staging.outputs.artifact-dir }}
+        MAVEN_REPOSITORY_DIR: ${{ inputs.maven-repository-dir }}
       run: |
-        mkdir -p ~/.m2/repository
-        tar -xzf "${{ inputs.artifact-dir }}/maven-repo-output.tar.gz" -C 
~/.m2/repository
-    - name: Load E2E Images
-      if: inputs.load-docker-image == 'true'
+        set -euo pipefail
+        repository_dir="${MAVEN_REPOSITORY_DIR:-$HOME/.m2/repository}"
+        mkdir -p "$repository_dir"
+        tar -xzf "$ARTIFACT_DIR/maven-repo-output.tar.gz" -C "$repository_dir"
+    - name: Restore MCP Distribution
+      if: inputs.restore-distribution == 'true'
       shell: bash
       env:
-        E2E_DOCKER_IMAGE_ARCHIVES: ${{ inputs.docker-image-archives }}
+        ARTIFACT_DIR: ${{ steps.staging.outputs.artifact-dir }}
       run: |
         set -euo pipefail
-        while IFS= read -r each; do
-          if [[ -z "${each}" ]]; then
-            continue
-          fi
-          docker load -i "${{ inputs.artifact-dir }}/${each}"
-        done <<< "${E2E_DOCKER_IMAGE_ARCHIVES}"
+        mkdir -p distribution/mcp/target
+        tar -xzf "$ARTIFACT_DIR/mcp-distribution-home.tar.gz" -C 
distribution/mcp/target
+    - name: Load E2E Image
+      id: load-image
+      if: inputs.load-docker-image == 'true'
+      uses: ./.github/actions/prepare-e2e-docker
+      with:
+        type: source
+        operation: load
+        archive: ${{ steps.staging.outputs.artifact-dir }}/image.tar
+        source-revision: ${{ github.sha }}
+    - name: Clean E2E Artifact Staging
+      if: always() && steps.staging.outputs.artifact-dir != ''
+      shell: bash
+      env:
+        ARTIFACT_DIR: ${{ steps.staging.outputs.artifact-dir }}
+      run: rm -rf -- "$ARTIFACT_DIR"
diff --git a/.github/actions/prepare-e2e-docker/action.yml 
b/.github/actions/prepare-e2e-docker/action.yml
new file mode 100644
index 00000000000..7d8ee383809
--- /dev/null
+++ b/.github/actions/prepare-e2e-docker/action.yml
@@ -0,0 +1,233 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+name: 'Prepare E2E Docker'
+description: 'Cache source and tool images and pull standard images or models'
+
+inputs:
+  type:
+    description: 'Artifact type: source, standard or tool'
+    required: true
+  operation:
+    description: 'Source image operation: restore, save or load'
+    required: false
+    default: 'restore'
+  image:
+    description: 'Image repository, or the built image reference for source 
save'
+    required: false
+  archive:
+    description: 'Image archive to load for a source consumer'
+    required: false
+  source-revision:
+    description: 'Fixed Tool commit or expected commit for source load'
+    required: false
+  kind:
+    description: 'Standard artifact kind: image or model'
+    required: false
+    default: 'image'
+  reference:
+    description: 'Standard image or model reference including its version'
+    required: false
+  dockerfile:
+    description: 'Tool Dockerfile with a fixed base image digest'
+    required: false
+  context:
+    description: 'Tool build context checked out at source-revision'
+    required: false
+
+outputs:
+  image:
+    description: 'Prepared image reference for this job, or the standard 
artifact reference'
+    value: ${{ inputs.type == 'standard' && inputs.reference || 
steps.identity.outputs.image }}
+  cache-hit:
+    description: 'Whether the exact image cache was restored'
+    value: ${{ steps.restore.outputs.cache-hit || 'false' }}
+  archive:
+    description: 'Image archive available until the upload action consumes it'
+    value: ${{ steps.identity.outputs.archive }}
+
+runs:
+  using: composite
+  steps:
+    - name: Check Docker Artifact Type
+      shell: bash
+      env:
+        TYPE: ${{ inputs.type }}
+        OPERATION: ${{ inputs.operation }}
+        KIND: ${{ inputs.kind }}
+      run: |
+        case "$TYPE:$OPERATION:$KIND" in
+          
source:restore:*|source:save:*|source:load:*|standard:*:image|standard:*:model|tool:*:*)
 ;;
+          *) echo '::error::Unsupported Docker artifact type, source operation 
or standard kind.'; exit 1 ;;
+        esac
+    - name: Pull Standard Artifact
+      if: inputs.type == 'standard'
+      shell: bash
+      env:
+        KIND: ${{ inputs.kind }}
+        REFERENCE: ${{ inputs.reference }}
+      run: |
+        set -euo pipefail
+        if [[ "$KIND" == 'model' ]]; then
+          docker model pull "$REFERENCE"
+        else
+          docker pull "$REFERENCE"
+        fi
+    - name: Identify Docker Artifact
+      if: inputs.type != 'standard'
+      id: identity
+      shell: bash
+      env:
+        TYPE: ${{ inputs.type }}
+        OPERATION: ${{ inputs.operation }}
+        IMAGE: ${{ inputs.image }}
+        ARCHIVE: ${{ inputs.archive }}
+        SOURCE_REVISION: ${{ inputs.source-revision }}
+        DOCKERFILE: ${{ inputs.dockerfile }}
+      run: |
+        set -euo pipefail
+        PLATFORM="$(docker version --format '{{.Server.Os}}/{{.Server.Arch}}')"
+        repository="$IMAGE"
+        source_sha="$SOURCE_REVISION"
+        if [[ "$TYPE" == 'source' ]]; then
+          if [[ "$OPERATION" == 'load' ]]; then
+            if [[ -z "$source_sha" || ! -s "$ARCHIVE" || ! -s "$ARCHIVE.json" 
]]; then
+              echo '::error::Source image load requires the expected commit, 
archive and identity.'
+              exit 1
+            fi
+            repository="$(jq -er '.image_repository' "$ARCHIVE.json")"
+          else
+            source_sha="$(git rev-parse HEAD)"
+            if [[ "$OPERATION" == 'save' ]]; then
+              repository="${IMAGE%:*}"
+            fi
+          fi
+          fingerprint="$(printf '%s\0' "$repository" "$source_sha" "$PLATFORM" 
| shasum -a 256 | awk '{print $1}')"
+        else
+          if [[ -z "$source_sha" ]]; then
+            echo '::error::Tool image preparation requires a fixed source 
commit.'
+            exit 1
+          fi
+          fingerprint="$({ printf '%s\0' "$repository" "$source_sha" 
"$PLATFORM"; cat "$DOCKERFILE"; } | shasum -a 256 | awk '{print $1}')"
+        fi
+        if [[ -z "$repository" ]]; then
+          echo '::error::Docker image repository is required.'
+          exit 1
+        fi
+        cache_key="e2e-docker-$TYPE-v3-$fingerprint"
+        cache_path=".e2e-cache/docker/$TYPE/$repository"
+        if [[ "$TYPE" != 'source' || "$OPERATION" != 'save' ]]; then
+          image_identity="$fingerprint"
+          if [[ "$TYPE" == 'source' ]]; then
+            image_identity="$source_sha"
+          fi
+          staging_dir="$(mktemp -d "/tmp/$image_identity-XXXXXX")"
+          trap 'rmdir "$staging_dir"' EXIT
+          IMAGE="$repository:${staging_dir##*/}"
+        fi
+        if [[ "$TYPE" != 'source' || "$OPERATION" != 'load' ]]; then
+          ARCHIVE="$GITHUB_WORKSPACE/$cache_path/image.tar"
+        fi
+        if [[ "$TYPE" == 'tool' || "$OPERATION" == 'restore' ]]; then
+          rm -rf "$GITHUB_WORKSPACE/$cache_path"
+        fi
+        printf 
'image=%s\nsource-sha=%s\nplatform=%s\narchive=%s\ncache-key=%s\ncache-path=%s\nrepository=%s\n'
 \
+          "$IMAGE" "$source_sha" "$PLATFORM" "$ARCHIVE" "$cache_key" 
"$cache_path" "$repository" >> "$GITHUB_OUTPUT"
+    - name: Restore Docker Image Cache
+      if: inputs.type == 'tool' || (inputs.type == 'source' && 
inputs.operation == 'restore')
+      id: restore
+      uses: actions/cache/[email protected]
+      with:
+        path: |
+          ${{ steps.identity.outputs.cache-path }}/image.tar
+          ${{ steps.identity.outputs.cache-path }}/image.tar.json
+        key: ${{ steps.identity.outputs.cache-key }}
+    - name: Load Docker Image
+      if: (inputs.type == 'source' && inputs.operation == 'load') || 
steps.restore.outputs.cache-hit == 'true'
+      shell: bash
+      env:
+        ARCHIVE: ${{ steps.identity.outputs.archive }}
+        IMAGE: ${{ steps.identity.outputs.image }}
+        SOURCE_SHA: ${{ steps.identity.outputs.source-sha }}
+        REPOSITORY: ${{ steps.identity.outputs.repository }}
+        PLATFORM: ${{ steps.identity.outputs.platform }}
+        CACHE_KEY: ${{ steps.identity.outputs.cache-key }}
+      run: |
+        set -euo pipefail
+        if [[ ! -s "$ARCHIVE" || ! -s "$ARCHIVE.json" ]]; then
+          echo '::error::Missing Docker image archive or identity.'
+          exit 1
+        fi
+        if ! jq -e --arg source_sha "$SOURCE_SHA" --arg repository 
"$REPOSITORY" --arg platform "$PLATFORM" --arg cache_key "$CACHE_KEY" \
+          '.source_sha == $source_sha and .image_repository == $repository and 
.platform == $platform and .cache_key == $cache_key' "$ARCHIVE.json" 
>/dev/null; then
+          echo '::error::Docker image archive does not match the expected 
source, repository, platform and cache key.'
+          exit 1
+        fi
+        archive_sha256="$(jq -er '.archive_sha256' "$ARCHIVE.json")"
+        if [[ "$(shasum -a 256 "$ARCHIVE" | awk '{print $1}')" != 
"$archive_sha256" ]]; then
+          echo '::error::Docker image archive checksum mismatch.'
+          exit 1
+        fi
+        image_id="$(jq -er '.image_id' "$ARCHIVE.json")"
+        docker load -i "$ARCHIVE"
+        if [[ "$(docker image inspect --format '{{.Id}}' "$image_id")" != 
"$image_id" ]]; then
+          echo '::error::Docker image identity mismatch.'
+          exit 1
+        fi
+        docker tag "$image_id" "$IMAGE"
+    - name: Build Tool Image
+      if: inputs.type == 'tool' && steps.restore.outputs.cache-hit != 'true'
+      shell: bash
+      env:
+        IMAGE: ${{ steps.identity.outputs.image }}
+        PLATFORM: ${{ steps.identity.outputs.platform }}
+        DOCKERFILE: ${{ inputs.dockerfile }}
+        BUILD_CONTEXT: ${{ inputs.context }}
+      run: |
+        set -euo pipefail
+        docker build --platform "$PLATFORM" -f "$DOCKERFILE" -t "$IMAGE" 
"$BUILD_CONTEXT"
+    - name: Save Docker Image
+      if: (inputs.type == 'source' && inputs.operation == 'save') || 
(inputs.type == 'tool' && steps.restore.outputs.cache-hit != 'true')
+      shell: bash
+      env:
+        IMAGE: ${{ steps.identity.outputs.image }}
+        SOURCE_SHA: ${{ steps.identity.outputs.source-sha }}
+        REPOSITORY: ${{ steps.identity.outputs.repository }}
+        PLATFORM: ${{ steps.identity.outputs.platform }}
+        CACHE_KEY: ${{ steps.identity.outputs.cache-key }}
+        CACHE_PATH: ${{ steps.identity.outputs.cache-path }}
+      run: |
+        set -euo pipefail
+        staging_dir="$(mktemp -d "/tmp/$SOURCE_SHA-XXXXXX")"
+        trap 'rm -rf "$staging_dir"' EXIT
+        image_id="$(docker image inspect --format '{{.Id}}' "$IMAGE")"
+        docker save -o "$staging_dir/image.tar" "$image_id"
+        archive_sha256="$(shasum -a 256 "$staging_dir/image.tar" | awk '{print 
$1}')"
+        jq -n --arg source_sha "$SOURCE_SHA" --arg repository "$REPOSITORY" 
--arg image_id "$image_id" \
+          --arg platform "$PLATFORM" --arg cache_key "$CACHE_KEY" --arg 
archive_sha256 "$archive_sha256" \
+          '{source_sha: $source_sha, image_repository: $repository, image_id: 
$image_id, platform: $platform, cache_key: $cache_key, archive_sha256: 
$archive_sha256}' \
+          > "$staging_dir/image.tar.json"
+        mkdir -p "$GITHUB_WORKSPACE/$CACHE_PATH"
+        mv "$staging_dir/image.tar" "$staging_dir/image.tar.json" 
"$GITHUB_WORKSPACE/$CACHE_PATH/"
+    - name: Save Docker Image Cache
+      if: (inputs.type == 'source' && inputs.operation == 'save') || 
(inputs.type == 'tool' && steps.restore.outputs.cache-hit != 'true')
+      uses: actions/cache/[email protected]
+      with:
+        path: |
+          ${{ steps.identity.outputs.cache-path }}/image.tar
+          ${{ steps.identity.outputs.cache-path }}/image.tar.json
+        key: ${{ steps.identity.outputs.cache-key }}
diff --git a/.github/actions/save-maven-cache/action.yml 
b/.github/actions/save-maven-cache/action.yml
index 9d4c4ff2d3a..177c95c27dd 100644
--- a/.github/actions/save-maven-cache/action.yml
+++ b/.github/actions/save-maven-cache/action.yml
@@ -29,6 +29,10 @@ inputs:
     description: 'Whether to enable cache save'
     required: false
     default: 'true'
+  maven-repository-dir:
+    description: 'Maven repository directory used by the restore step; empty 
keeps the default repository'
+    required: false
+    default: ''
 
 runs:
   using: composite
@@ -38,7 +42,7 @@ runs:
       uses: actions/cache/[email protected]
       with:
         path: |
-          ~/.m2/repository
-          !~/.m2/repository/org/apache/shardingsphere
-          ~/.m2/repository/org/apache/shardingsphere/elasticjob
+          ${{ inputs.maven-repository-dir || '~/.m2/repository' }}
+          !${{ inputs.maven-repository-dir || '~/.m2/repository' 
}}/org/apache/shardingsphere
+          ${{ inputs.maven-repository-dir || '~/.m2/repository' 
}}/org/apache/shardingsphere/elasticjob
         key: ${{ inputs.cache-primary-key }}
diff --git a/.github/actions/setup-build-environment/action.yml 
b/.github/actions/setup-build-environment/action.yml
index 28b36cc8047..6bdfa6f9f74 100644
--- a/.github/actions/setup-build-environment/action.yml
+++ b/.github/actions/setup-build-environment/action.yml
@@ -62,6 +62,10 @@ inputs:
     description: 'Whether to save Maven cache in this action (default: true)'
     required: false
     default: 'true'
+  maven-repository-dir:
+    description: 'Runner-specific Maven repository directory; empty keeps the 
default repository'
+    required: false
+    default: ''
   github-token:
     description: 'GitHub token for authenticated GraalVM Community downloads 
(optional when distribution is graalvm)'
     required: false
@@ -101,26 +105,59 @@ runs:
         set -euo pipefail
         docker version
         docker compose version
+    - name: Prepare E2E Maven Repository
+      if: inputs.maven-repository-dir != ''
+      shell: bash
+      env:
+        MAVEN_REPOSITORY_DIR: ${{ inputs.maven-repository-dir }}
+      run: |
+        set -euo pipefail
+        mkdir -p "$MAVEN_REPOSITORY_DIR"
+        repository="$(cd "$MAVEN_REPOSITORY_DIR" && pwd -P)"
+        if [[ "$repository" == / ]]; then
+          echo '::error::The Maven repository must not be the filesystem root.'
+          exit 1
+        fi
+        echo "E2E_MAVEN_REPOSITORY=$repository" >> "$GITHUB_ENV"
     - name: Restore Maven Cache
       id: restore-maven-cache
       uses: actions/cache/[email protected]
       with:
         path: |
-          ~/.m2/repository
-          !~/.m2/repository/org/apache/shardingsphere
-          ~/.m2/repository/org/apache/shardingsphere/elasticjob
+          ${{ inputs.maven-repository-dir || '~/.m2/repository' }}
+          !${{ inputs.maven-repository-dir || '~/.m2/repository' 
}}/org/apache/shardingsphere
+          ${{ inputs.maven-repository-dir || '~/.m2/repository' 
}}/org/apache/shardingsphere/elasticjob
         key: ${{ inputs.cache-prefix }}-maven-${{ inputs.cache-suffix }}-${{ 
hashFiles('**/pom.xml') }}
         restore-keys: |
           ${{ inputs.cache-prefix }}-maven-${{ inputs.cache-suffix }}-
           ${{ inputs.cache-prefix }}-maven-full-
           ${{ inputs.cache-prefix }}-maven-
           ${{ inputs.cache-prefix }}-
+    - name: Remove Previous E2E Maven Artifacts
+      if: inputs.maven-repository-dir != ''
+      shell: bash
+      run: |
+        set -euo pipefail
+        group_dir="$E2E_MAVEN_REPOSITORY"
+        for directory in org apache shardingsphere; do
+          group_dir="$group_dir/$directory"
+          if [[ -e "$group_dir" || -L "$group_dir" ]]; then
+            group_dir="$(cd "$group_dir" && pwd -P)"
+            if [[ "$group_dir" != "$E2E_MAVEN_REPOSITORY/"* ]]; then
+              echo '::error::The ShardingSphere Maven directory must remain 
inside the configured repository.'
+              exit 1
+            fi
+          fi
+        done
+        if [[ -d "$group_dir" ]]; then
+          find "$group_dir" -mindepth 1 -maxdepth 1 ! -name elasticjob -exec 
rm -rf -- {} +
+        fi
     - name: Save Maven Cache
       if: inputs.cache-save-enabled == 'true' && github.event_name != 
'pull_request' && steps.restore-maven-cache.outputs.cache-hit != 'true'
       uses: actions/cache/[email protected]
       with:
         path: |
-          ~/.m2/repository
-          !~/.m2/repository/org/apache/shardingsphere
-          ~/.m2/repository/org/apache/shardingsphere/elasticjob
+          ${{ inputs.maven-repository-dir || '~/.m2/repository' }}
+          !${{ inputs.maven-repository-dir || '~/.m2/repository' 
}}/org/apache/shardingsphere
+          ${{ inputs.maven-repository-dir || '~/.m2/repository' 
}}/org/apache/shardingsphere/elasticjob
         key: ${{ inputs.cache-prefix }}-maven-${{ inputs.cache-suffix }}-${{ 
hashFiles('**/pom.xml') }}
diff --git a/.github/actions/upload-e2e-artifacts/action.yml 
b/.github/actions/upload-e2e-artifacts/action.yml
index 249c380b62f..c75e14cb1af 100644
--- a/.github/actions/upload-e2e-artifacts/action.yml
+++ b/.github/actions/upload-e2e-artifacts/action.yml
@@ -23,48 +23,95 @@ inputs:
     description: 'Uploaded artifact name'
     required: false
     default: 'build-outputs'
-  artifact-dir:
-    description: 'Directory used to stage packaged artifacts'
-    required: false
-    default: '/tmp/e2e-build-artifacts'
   include-maven-repository:
     description: 'Whether to package the ShardingSphere Maven repository 
output'
     required: false
     default: 'true'
-  docker-images:
-    description: 'Docker images to save, one per line as 
image=archive-file-name'
+  maven-repository-dir:
+    description: 'Maven repository directory, defaulting to ~/.m2/repository'
+    required: false
+    default: ''
+  image-archive:
+    description: 'Docker archive returned by Prepare E2E Docker after saving 
its cache'
+    required: false
+    default: ''
+  include-distribution:
+    description: 'Whether to package the MCP distribution home'
     required: false
-    default: 
'apache/shardingsphere-proxy-test:latest=apache-shardingsphere-proxy-test.tar'
+    default: 'false'
+
+outputs:
+  artifact-id:
+    description: 'ID of the uploaded artifact'
+    value: ${{ steps.upload.outputs.artifact-id }}
 
 runs:
   using: composite
   steps:
-    - name: Prepare E2E Artifact Directory
+    - name: Record E2E Build Identity
+      id: identity
       shell: bash
       run: |
-        mkdir -p "${{ inputs.artifact-dir }}"
-    - name: Package shardingsphere Maven Repository
-      if: inputs.include-maven-repository == 'true'
+        set -euo pipefail
+        source_sha="$(git rev-parse HEAD)"
+        if [[ "$source_sha" != "$GITHUB_SHA" ]]; then
+          echo '::error::The checked-out commit does not match the workflow 
commit.'
+          exit 1
+        fi
+        artifact_dir="$(mktemp -d 
"/tmp/shardingsphere-e2e-${source_sha}.XXXXXX")"
+        echo "artifact-dir=$artifact_dir" >> "$GITHUB_OUTPUT"
+        jq -n --arg source_sha "$source_sha" '{source_sha: $source_sha}' \
+          > "$artifact_dir/build-identity.json"
+    - name: Package E2E Build Outputs
       shell: bash
+      env:
+        ARTIFACT_DIR: ${{ steps.identity.outputs.artifact-dir }}
+        INCLUDE_MAVEN_REPOSITORY: ${{ inputs.include-maven-repository }}
+        MAVEN_REPOSITORY_DIR: ${{ inputs.maven-repository-dir }}
+        INCLUDE_DISTRIBUTION: ${{ inputs.include-distribution }}
       run: |
-        tar -czf "${{ inputs.artifact-dir }}/maven-repo-output.tar.gz" -C 
~/.m2/repository org/apache/shardingsphere
-    - name: Save E2E Images
+        set -euo pipefail
+        if [[ "$INCLUDE_MAVEN_REPOSITORY" == 'true' ]]; then
+          tar -czf "$ARTIFACT_DIR/maven-repo-output.tar.gz" -C 
"${MAVEN_REPOSITORY_DIR:-$HOME/.m2/repository}" org/apache/shardingsphere
+        fi
+        if [[ "$INCLUDE_DISTRIBUTION" == 'true' ]]; then
+          distribution_homes=()
+          for directory in 
distribution/mcp/target/apache-shardingsphere-mcp-*; do
+            if [[ -d "$directory" ]]; then
+              distribution_homes+=("$directory")
+            fi
+          done
+          if [[ "${#distribution_homes[@]}" != 1 ]]; then
+            echo '::error::Expected exactly one built MCP distribution home.'
+            exit 1
+          fi
+          tar -czf "$ARTIFACT_DIR/mcp-distribution-home.tar.gz" -C 
distribution/mcp/target "${distribution_homes[0]##*/}"
+        fi
+    - name: Stage E2E Image
+      if: inputs.image-archive != ''
       shell: bash
       env:
-        E2E_DOCKER_IMAGES: ${{ inputs.docker-images }}
+        ARTIFACT_DIR: ${{ steps.identity.outputs.artifact-dir }}
+        IMAGE_ARCHIVE: ${{ inputs.image-archive }}
       run: |
         set -euo pipefail
-        while IFS= read -r each; do
-          if [[ -z "${each}" ]]; then
-            continue
-          fi
-          image="${each%%=*}"
-          archive_name="${each#*=}"
-          docker save -o "${{ inputs.artifact-dir }}/${archive_name}" 
"${image}"
-        done <<< "${E2E_DOCKER_IMAGES}"
+        if [[ ! -f "$IMAGE_ARCHIVE" ]] || ! jq -e --arg source_sha 
"$GITHUB_SHA" '.source_sha == $source_sha' "$IMAGE_ARCHIVE.json"; then
+          echo '::error::The Docker archive is missing or does not match the 
source commit.'
+          exit 1
+        fi
+        mv "$IMAGE_ARCHIVE" "$ARTIFACT_DIR/image.tar"
+        mv "$IMAGE_ARCHIVE.json" "$ARTIFACT_DIR/image.tar.json"
     - name: Upload Build Artifacts
+      id: upload
       uses: actions/upload-artifact@v6
       with:
-        name: ${{ inputs.artifact-name }}
-        path: ${{ inputs.artifact-dir }}/*
+        name: ${{ inputs.artifact-name }}-${{ github.run_id }}-${{ github.job 
}}-${{ github.run_attempt }}
+        path: ${{ steps.identity.outputs.artifact-dir }}/*
+        if-no-files-found: error
         retention-days: 3
+    - name: Clean E2E Artifact Staging
+      if: always() && steps.identity.outputs.artifact-dir != ''
+      shell: bash
+      env:
+        ARTIFACT_DIR: ${{ steps.identity.outputs.artifact-dir }}
+      run: rm -rf -- "$ARTIFACT_DIR"
diff --git a/.github/workflows/e2e-agent.yml b/.github/workflows/e2e-agent.yml
index 98ee2558de9..cc076edfb6f 100644
--- a/.github/workflows/e2e-agent.yml
+++ b/.github/workflows/e2e-agent.yml
@@ -47,6 +47,7 @@ permissions:
 
 env:
   MAVEN_OPTS: -Dhttp.keepAlive=false
+  MAVEN_REPOSITORY_DIR: ../.e2e-maven/repository
 
 jobs:
   global-environment:
@@ -59,39 +60,79 @@ jobs:
     needs: global-environment
     runs-on: ${{ needs.global-environment.outputs.GLOBAL_RUNS_ON }}
     timeout-minutes: 40
+    outputs:
+      proxy-artifact-id: ${{ steps.upload-proxy-image.outputs.artifact-id }}
+      jdbc-artifact-id: ${{ steps.upload-jdbc-image.outputs.artifact-id }}
     steps:
       - uses: actions/[email protected]
       - id: setup-build-environment
         uses: ./.github/actions/setup-build-environment
         with:
           java-version: 21
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-suffix: 'e2e-agent'
           cache-save-enabled: 'false'
           enable-docker-setup: 'true'
+      - name: Restore Proxy E2E Image Cache
+        id: prepare-proxy-image
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          image: apache/shardingsphere-proxy-agent-test
+      - name: Restore JDBC E2E Image Cache
+        id: prepare-jdbc-image
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          image: apache/shardingsphere-jdbc-agent-test
       - name: Build Project
-        run: ./mvnw -B clean install -DskipTests -Prelease,default-dep
+        if: steps.prepare-proxy-image.outputs.cache-hit != 'true' || 
steps.prepare-jdbc-image.outputs.cache-hit != 'true'
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -B clean 
install -DskipTests -Prelease,default-dep
       - name: Build Proxy E2E Image
-        run: ./mvnw install -DskipTests -Pe2e.env.proxy -f 
test/e2e/agent/engine/pom.xml
-      - name: Save Proxy E2E Image
-        run: docker save -o /tmp/apache-shardingsphere-proxy-agent-test.tar 
apache/shardingsphere-proxy-agent-test:latest
-      - uses: actions/upload-artifact@v6
+        if: steps.prepare-proxy-image.outputs.cache-hit != 'true'
+        shell: bash
+        env:
+          PROXY_IMAGE: ${{ steps.prepare-proxy-image.outputs.image }}
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" install 
-DskipTests -Pe2e.env.proxy -Ddockerfile.tag="${PROXY_IMAGE##*:}" -f 
test/e2e/agent/engine/pom.xml
+      - name: Save Proxy E2E Image Cache
+        if: steps.prepare-proxy-image.outputs.cache-hit != 'true'
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          operation: save
+          image: ${{ steps.prepare-proxy-image.outputs.image }}
+      - name: Upload Proxy E2E Image
+        id: upload-proxy-image
+        uses: ./.github/actions/upload-e2e-artifacts
         with:
-          name: proxy-e2e-image
-          path: /tmp/apache-shardingsphere-proxy-agent-test.tar
-          retention-days: 10
+          artifact-name: proxy-e2e-image
+          include-maven-repository: 'false'
+          image-archive: ${{ steps.prepare-proxy-image.outputs.archive }}
       - name: Build JDBC E2E Image
-        run: ./mvnw install -DskipTests -Pe2e.env.jdbc -f 
test/e2e/agent/engine/pom.xml
+        if: steps.prepare-jdbc-image.outputs.cache-hit != 'true'
+        shell: bash
+        env:
+          JDBC_IMAGE: ${{ steps.prepare-jdbc-image.outputs.image }}
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" install 
-DskipTests -Pe2e.env.jdbc -Ddockerfile.tag="${JDBC_IMAGE##*:}" -f 
test/e2e/agent/engine/pom.xml
+      - name: Save JDBC E2E Image Cache
+        if: steps.prepare-jdbc-image.outputs.cache-hit != 'true'
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          operation: save
+          image: ${{ steps.prepare-jdbc-image.outputs.image }}
       - uses: ./.github/actions/save-maven-cache
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-hit: ${{ steps.setup-build-environment.outputs.cache-hit }}
           cache-primary-key: ${{ 
steps.setup-build-environment.outputs.cache-primary-key }}
-      - name: Save JDBC E2E Image
-        run: docker save -o /tmp/apache-shardingsphere-jdbc-agent-test.tar 
apache/shardingsphere-jdbc-agent-test:latest
-      - uses: actions/upload-artifact@v6
+      - name: Upload JDBC E2E Image
+        id: upload-jdbc-image
+        uses: ./.github/actions/upload-e2e-artifacts
         with:
-          name: jdbc-e2e-image
-          path: /tmp/apache-shardingsphere-jdbc-agent-test.tar
-          retention-days: 10
+          artifact-name: jdbc-e2e-image
+          include-maven-repository: 'false'
+          image-archive: ${{ steps.prepare-jdbc-image.outputs.archive }}
 
   agent-mysql:
     name: E2E - Agent with MySQL
@@ -126,29 +167,26 @@ jobs:
       - uses: actions/[email protected]
       - uses: ./.github/actions/setup-build-environment
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           java-version: 21
           cache-suffix: 'e2e-agent'
           cache-save-enabled: 'false'
           enable-docker-setup: 'true'
       - name: Download Proxy E2E Image
+        id: download-proxy-image
         if: matrix.adapter == 'proxy'
-        uses: actions/download-artifact@v8
+        uses: ./.github/actions/download-e2e-artifacts
         with:
-          name: proxy-e2e-image
-          path: /tmp/
-      - name: Load Proxy E2E Image
-        if: matrix.adapter == 'proxy'
-        run: docker load -i /tmp/apache-shardingsphere-proxy-agent-test.tar
+          artifact-id: ${{ needs.build-e2e-image.outputs.proxy-artifact-id }}
+          restore-maven-repository: 'false'
       - name: Download JDBC E2E Image
+        id: download-jdbc-image
         if: matrix.adapter == 'jdbc'
-        uses: actions/download-artifact@v8
+        uses: ./.github/actions/download-e2e-artifacts
         with:
-          name: jdbc-e2e-image
-          path: /tmp/
-      - name: Load JDBC E2E Image
-        if: matrix.adapter == 'jdbc'
-        run: docker load -i /tmp/apache-shardingsphere-jdbc-agent-test.tar
+          artifact-id: ${{ needs.build-e2e-image.outputs.jdbc-artifact-id }}
+          restore-maven-repository: 'false'
       - name: Build Project
-        run: ./mvnw -B clean install -am -pl test/e2e/agent/plugins/${{ 
matrix.feature }}/${{ matrix.plugin }} -DskipTests
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -B clean 
install -am -pl test/e2e/agent/plugins/${{ matrix.feature }}/${{ matrix.plugin 
}} -DskipTests
       - name: Run E2E Test
-        run: ./mvnw -nsu -B install -f test/e2e/agent/plugins/${{ 
matrix.feature }}/${{ matrix.plugin }}/pom.xml -De2e.run.type=DOCKER 
-De2e.env.adapter=${{ matrix.adapter }} -De2e.env.plugin=${{ matrix.plugin }}
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -nsu -B install 
-f test/e2e/agent/plugins/${{ matrix.feature }}/${{ matrix.plugin }}/pom.xml 
-De2e.run.type=DOCKER -De2e.env.adapter=${{ matrix.adapter }} 
-De2e.env.plugin=${{ matrix.plugin }} -Dproxy.image="${{ 
steps.download-proxy-image.outputs.image }}" -Djdbc.project.image="${{ 
steps.download-jdbc-image.outputs.image }}"
diff --git a/.github/workflows/e2e-mcp.yml b/.github/workflows/e2e-mcp.yml
index 560760c8df9..7e2da3ffe6b 100644
--- a/.github/workflows/e2e-mcp.yml
+++ b/.github/workflows/e2e-mcp.yml
@@ -43,7 +43,8 @@ permissions:
 
 env:
   MAVEN_OPTS: -Dhttp.keepAlive=false
-  MCP_DISTRIBUTION_IMAGE: apache/shardingsphere-mcp-e2e:local
+  MAVEN_REPOSITORY_DIR: ../.e2e-maven/repository
+  MCP_CONFORMANCE_REF: 21a9a2febd7100d7c17ac1021ee7f2ed9f66a1e0
 
 jobs:
   global-environment:
@@ -56,53 +57,61 @@ jobs:
     needs: global-environment
     runs-on: ${{ needs.global-environment.outputs.GLOBAL_RUNS_ON }}
     timeout-minutes: 60
+    outputs:
+      maven-artifact-id: ${{ steps.upload-maven.outputs.artifact-id }}
+      distribution-artifact-id: ${{ 
steps.upload-distribution.outputs.artifact-id }}
     steps:
       - uses: actions/[email protected]
       - uses: ./.github/actions/setup-build-environment
         with:
           java-version: '21'
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-suffix: 'e2e-mcp'
           cache-save-enabled: 'false'
           enable-docker-setup: 'true'
+      - name: Restore MCP Distribution Image Cache
+        id: prepare-image
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          image: apache/shardingsphere-mcp-e2e
       - name: Check Docker Environment
         run: |
           docker version
           docker system df
       - name: Build MCP E2E Test Dependencies and Distribution
-        run: ./mvnw -pl test/e2e/mcp,distribution/mcp -am install -DskipTests 
-DskipITs -Dspotless.skip=true -B -ntp
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -pl 
test/e2e/mcp,distribution/mcp -am install -DskipTests -DskipITs 
-Dspotless.skip=true -B -ntp
       - name: Build MCP Distribution Image
+        if: steps.prepare-image.outputs.cache-hit != 'true'
+        env:
+          MCP_DISTRIBUTION_IMAGE: ${{ steps.prepare-image.outputs.image }}
         run: |
           docker build \
             --platform "$(docker version --format 
'{{.Server.Os}}/{{.Server.Arch}}')" \
             -f distribution/mcp/Dockerfile \
             -t "${MCP_DISTRIBUTION_IMAGE}" \
             distribution/mcp/target
-      - name: Package MCP Distribution Home
-        shell: bash
-        run: |
-          set -euo pipefail
-          artifact_dir="${RUNNER_TEMP}/mcp-e2e-distribution"
-          mkdir -p "${artifact_dir}"
-          distribution_home="$(find distribution/mcp/target -maxdepth 1 -type 
d -name 'apache-shardingsphere-mcp-*' | head -n 1)"
-          if [[ -z "${distribution_home}" ]]; then
-            echo "Packaged MCP distribution was not found." 1>&2
-            exit 1
-          fi
-          tar -czf "${artifact_dir}/mcp-distribution-home.tar.gz" -C 
distribution/mcp/target "$(basename "${distribution_home}")"
+      - name: Save E2E Image Cache
+        if: steps.prepare-image.outputs.cache-hit != 'true'
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          operation: save
+          image: ${{ steps.prepare-image.outputs.image }}
       - name: Upload MCP Maven Repository
+        id: upload-maven
         uses: ./.github/actions/upload-e2e-artifacts
         with:
           artifact-name: mcp-e2e-maven-repository
-          artifact-dir: ${{ runner.temp }}/mcp-e2e-maven-repository
-          docker-images: ''
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
       - name: Upload MCP Distribution
+        id: upload-distribution
         uses: ./.github/actions/upload-e2e-artifacts
         with:
           artifact-name: mcp-e2e-distribution
-          artifact-dir: ${{ runner.temp }}/mcp-e2e-distribution
           include-maven-repository: 'false'
-          docker-images: |
-            ${{ env.MCP_DISTRIBUTION_IMAGE }}=mcp-distribution-image.tar
+          include-distribution: 'true'
+          image-archive: ${{ steps.prepare-image.outputs.archive }}
 
   e2e-mcp-functionality:
     name: E2E - MCP Functionality
@@ -114,6 +123,7 @@ jobs:
       - uses: actions/[email protected]
       - uses: ./.github/actions/setup-build-environment
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           java-version: '21'
           cache-suffix: 'e2e-mcp'
           cache-save-enabled: 'false'
@@ -121,24 +131,18 @@ jobs:
       - name: Download MCP Maven Repository
         uses: ./.github/actions/download-e2e-artifacts
         with:
-          artifact-name: mcp-e2e-maven-repository
-          artifact-dir: ${{ runner.temp }}/mcp-e2e-maven-repository
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
+          artifact-id: ${{ 
needs.e2e-mcp-build-images.outputs.maven-artifact-id }}
           load-docker-image: 'false'
       - name: Download MCP Distribution
+        id: download-distribution
         uses: ./.github/actions/download-e2e-artifacts
         with:
-          artifact-name: mcp-e2e-distribution
-          artifact-dir: ${{ runner.temp }}/mcp-e2e-distribution
+          artifact-id: ${{ 
needs.e2e-mcp-build-images.outputs.distribution-artifact-id }}
           restore-maven-repository: 'false'
-          docker-image-archives: mcp-distribution-image.tar
-      - name: Restore MCP Distribution Home
-        shell: bash
-        run: |
-          set -euo pipefail
-          mkdir -p distribution/mcp/target
-          tar -xzf 
"${RUNNER_TEMP}/mcp-e2e-distribution/mcp-distribution-home.tar.gz" -C 
distribution/mcp/target
+          restore-distribution: 'true'
       - name: Run MCP Functionality E2E
-        run: ./mvnw -pl test/e2e/mcp verify -Pe2e.mcp.functionality 
-De2e.run.type=DOCKER -Dmcp.e2e.container.image=${{ env.MCP_DISTRIBUTION_IMAGE 
}} -Dmcp.e2e.artifact-root="${{ github.workspace 
}}/test/e2e/mcp/target/functionality-e2e" -Dspotless.skip=true -B -ntp
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -pl 
test/e2e/mcp verify -Pe2e.mcp.functionality -De2e.run.type=DOCKER 
-Dmcp.e2e.container.image="${{ steps.download-distribution.outputs.image }}" 
-Dmcp.e2e.artifact-root="${{ github.workspace 
}}/test/e2e/mcp/target/functionality-e2e" -Dspotless.skip=true -B -ntp
       - name: Upload MCP Functionality E2E Artifacts
         if: always()
         uses: actions/upload-artifact@v6
@@ -158,30 +162,31 @@ jobs:
     steps:
       - uses: actions/[email protected]
       - name: Download MCP Distribution
+        id: download-distribution
         uses: ./.github/actions/download-e2e-artifacts
         with:
-          artifact-name: mcp-e2e-distribution
-          artifact-dir: ${{ runner.temp }}/mcp-e2e-distribution
+          artifact-id: ${{ 
needs.e2e-mcp-build-images.outputs.distribution-artifact-id }}
           restore-maven-repository: 'false'
-          docker-image-archives: mcp-distribution-image.tar
       - name: Checkout Pinned MCP Conformance Runner
         uses: actions/[email protected]
         with:
           repository: modelcontextprotocol/conformance
-          ref: 21a9a2febd7100d7c17ac1021ee7f2ed9f66a1e0
+          ref: ${{ env.MCP_CONFORMANCE_REF }}
           path: .mcp-conformance
-      - uses: actions/setup-node@v6
+      - name: Prepare MCP Conformance Runner
+        id: prepare-conformance
+        uses: ./.github/actions/prepare-e2e-docker
         with:
-          node-version: '22'
-          cache: npm
-          cache-dependency-path: .mcp-conformance/package-lock.json
-      - name: Build MCP Conformance Runner
-        working-directory: .mcp-conformance
-        run: |
-          npm ci --ignore-scripts
-          npm run build
+          type: tool
+          image: apache/shardingsphere-mcp-conformance
+          dockerfile: 
test/e2e/mcp/src/test/resources/docker/conformance/Dockerfile
+          context: .mcp-conformance
+          source-revision: ${{ env.MCP_CONFORMANCE_REF }}
       - name: Run MCP 2025-11-25 Conformance Scenarios
         shell: bash
+        env:
+          CONFORMANCE_IMAGE: ${{ steps.prepare-conformance.outputs.image }}
+          MCP_DISTRIBUTION_IMAGE: ${{ 
steps.download-distribution.outputs.image }}
         run: |
           set -euo pipefail
           generic_scenarios=(
@@ -193,9 +198,11 @@ jobs:
             prompts-list
             dns-rebinding-protection
           )
-          container_name="shardingsphere-mcp-conformance"
+          
container_name="shardingsphere-mcp-conformance-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
+          runner_name="${container_name}-runner"
           cleanup() {
             docker logs "${container_name}" 
>"${RUNNER_TEMP}/mcp-conformance-server.log" 2>&1 || true
+            docker rm -f "${runner_name}" >/dev/null 2>&1 || true
             docker rm -f "${container_name}" >/dev/null 2>&1 || true
           }
           trap cleanup EXIT
@@ -212,7 +219,8 @@ jobs:
           results_root="${RUNNER_TEMP}/mcp-conformance-results"
           mkdir -p "${results_root}"
           version_scenarios="$(
-            node .mcp-conformance/dist/index.js list --server --spec-version 
2025-11-25 \
+            docker run --rm --name "${runner_name}" --network host --user 
"$(id -u):$(id -g)" \
+              "${CONFORMANCE_IMAGE}" list --server --spec-version 2025-11-25 \
               | sed -nE 's/^[[:space:]]+- ([^ ]+).*/\1/p'
           )"
           for scenario in "${generic_scenarios[@]}"; do
@@ -220,10 +228,12 @@ jobs:
               echo "MCP conformance scenario '${scenario}' is unavailable for 
protocol version 2025-11-25." >&2
               exit 1
             fi
-            node .mcp-conformance/dist/index.js server \
+            docker run --rm --name "${runner_name}" --network host --user 
"$(id -u):$(id -g)" \
+              --mount "type=bind,src=${results_root},dst=/results" \
+              "${CONFORMANCE_IMAGE}" server \
               --url http://127.0.0.1:18088/mcp \
               --scenario "${scenario}" \
-              --output-dir "${results_root}/${scenario}"
+              --output-dir "/results/${scenario}"
             checks_file="$(find "${results_root}/${scenario}" -type f -name 
checks.json -print -quit 2>/dev/null || true)"
             if [[ -z "${checks_file}" ]] || ! jq -e 'type == "array" and 
length > 0' "${checks_file}" >/dev/null; then
               echo "MCP conformance scenario '${scenario}' produced no 
checks." >&2
@@ -265,6 +275,7 @@ jobs:
       - uses: actions/[email protected]
       - uses: ./.github/actions/setup-build-environment
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           java-version: '21'
           cache-suffix: 'e2e-mcp'
           cache-save-enabled: 'false'
@@ -272,10 +283,11 @@ jobs:
       - name: Download MCP Maven Repository
         uses: ./.github/actions/download-e2e-artifacts
         with:
-          artifact-name: mcp-e2e-maven-repository
-          artifact-dir: ${{ runner.temp }}/mcp-e2e-maven-repository
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
+          artifact-id: ${{ 
needs.e2e-mcp-build-images.outputs.maven-artifact-id }}
           load-docker-image: 'false'
-      - name: Prepare MCP LLM with Docker Model Runner
+      - name: Install Docker Model Runner
+        id: install-model-runner
         shell: bash
         env:
           MODEL_RUNNER_CONTROLLER_VERSION: 
v1.2.8@sha256:5bdc2bac71c1b70453f7dec5b527031bc6d8d99b8d1b2a10a8bcca073ae257a3
@@ -292,15 +304,27 @@ jobs:
           sudo apt-get install -y 
"docker-model-plugin=1.2.6-1~ubuntu.${VERSION_ID}~${UBUNTU_CODENAME:-$VERSION_CODENAME}"
           docker model install-runner --gpu none
           model="$(awk -F= '$1 == "mcp.llm.model" {print $2}' 
test/e2e/mcp/src/test/resources/env/e2e-env.properties)"
-          docker model pull "${model}"
-          docker model configure --context-size 8192 "${model}" -- \
+          echo "model=${model}" >> "${GITHUB_OUTPUT}"
+      - name: Pull MCP LLM
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: standard
+          kind: model
+          reference: ${{ steps.install-model-runner.outputs.model }}
+      - name: Configure MCP LLM
+        shell: bash
+        env:
+          MCP_LLM_MODEL: ${{ steps.install-model-runner.outputs.model }}
+        run: |
+          set -euo pipefail
+          docker model configure --context-size 8192 "${MCP_LLM_MODEL}" -- \
             --jinja --reasoning-budget 0 --reasoning-format deepseek 
--chat-template-kwargs '{"enable_thinking":false}' \
             --parallel 1 -b 256 -ub 128 --cache-ram 0 --no-cache-prompt
-          docker model run --detach "${model}"
+          docker model run --detach "${MCP_LLM_MODEL}"
       - name: Run MCP LLM E2E
         env:
           TESTCONTAINERS_RYUK_DISABLED: 'true'
-        run: ./mvnw -pl test/e2e/mcp verify -Pe2e.mcp.llm 
-De2e.run.type=DOCKER -Dspotless.skip=true -Dit.test='${{ matrix.test }}' 
-Dmcp.llm.artifact-root="${{ github.workspace }}/test/e2e/mcp/target/llm-e2e" 
-Dmcp.llm.run-id=gha-${{ github.run_id }}-${{ github.run_attempt }}-${{ 
matrix.id }} -B -ntp
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -pl 
test/e2e/mcp verify -Pe2e.mcp.llm -De2e.run.type=DOCKER -Dspotless.skip=true 
-Dit.test='${{ matrix.test }}' -Dmcp.llm.artifact-root="${{ github.workspace 
}}/test/e2e/mcp/target/llm-e2e" -Dmcp.llm.run-id=gha-${{ github.run_id }}-${{ 
github.run_attempt }}-${{ matrix.id }} -B -ntp
       - name: Upload MCP LLM E2E Artifacts
         if: always()
         uses: actions/upload-artifact@v6
diff --git a/.github/workflows/e2e-operation.yml 
b/.github/workflows/e2e-operation.yml
index 041f91cdf17..8bbd21f4ed5 100644
--- a/.github/workflows/e2e-operation.yml
+++ b/.github/workflows/e2e-operation.yml
@@ -33,6 +33,7 @@ permissions:
 
 env:
   MAVEN_OPTS: -Dhttp.keepAlive=false -Dfailsafe.skipAfterFailureCount=1 
-Dio.netty.leakDetectionLevel=advanced
+  MAVEN_REPOSITORY_DIR: ../.e2e-maven/repository
 
 jobs:
   global-environment:
@@ -61,28 +62,42 @@ jobs:
     needs: [ global-environment, detect-changed-files ]
     runs-on: ${{ needs.global-environment.outputs.GLOBAL_RUNS_ON }}
     timeout-minutes: 40
+    outputs:
+      artifact-id: ${{ steps.upload-e2e-artifacts.outputs.artifact-id }}
     steps:
       - uses: actions/[email protected]
       - id: setup-build-environment
         uses: ./.github/actions/setup-build-environment
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-suffix: 'e2e-operation'
           cache-save-enabled: 'false'
           enable-docker-setup: 'true'
-      - name: Maven Install
-        env:
-          PREFIX: "test/e2e/operation/"
-          MODULE_LIST: "transaction,pipeline,showprocesslist"
-        run: |
-          FORMATTED_PL=$(echo "$MODULE_LIST" | sed "s|,|,$PREFIX|g" | sed 
"s|^|$PREFIX|")
-          echo "Ready to build: $FORMATTED_PL"
-          ./mvnw -B clean install -am -pl "$FORMATTED_PL" -Pe2e.env.docker 
-DskipTests
+      - name: Restore E2E Image Cache
+        id: prepare-image
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          image: apache/shardingsphere-proxy-test
+      - name: Build E2E Image
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -B clean 
install -am -pl 
test/e2e/operation/transaction,test/e2e/operation/pipeline,test/e2e/operation/showprocesslist
 -Pe2e.env.docker -DskipTests -Ddocker.image.name="${{ 
steps.prepare-image.outputs.image }}" -Dexec.skip=${{ 
steps.prepare-image.outputs.cache-hit == 'true' }}
+      - name: Save E2E Image Cache
+        if: steps.prepare-image.outputs.cache-hit != 'true'
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          operation: save
+          image: ${{ steps.prepare-image.outputs.image }}
       - uses: ./.github/actions/save-maven-cache
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-hit: ${{ steps.setup-build-environment.outputs.cache-hit }}
           cache-primary-key: ${{ 
steps.setup-build-environment.outputs.cache-primary-key }}
-      - uses: ./.github/actions/upload-source-snapshot
-      - uses: ./.github/actions/upload-e2e-artifacts
+      - id: upload-e2e-artifacts
+        uses: ./.github/actions/upload-e2e-artifacts
+        with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
+          image-archive: ${{ steps.prepare-image.outputs.archive }}
 
   e2e-operation:
     name: E2E - ${{ matrix.operation }} on ${{ matrix.image.version }}
@@ -116,20 +131,19 @@ jobs:
           echo "runner.temp=${{ runner.temp }}"
           echo "RUNNER_TEMP=$RUNNER_TEMP"
           echo "GITHUB_WORKSPACE=$GITHUB_WORKSPACE"
-      - name: Download Source Snapshot
-        uses: actions/download-artifact@v8
+      - uses: actions/[email protected]
         with:
-          name: source-snapshot
-          path: ${{ runner.temp }}/source-snapshot
-      - name: Restore Source Snapshot
-        run: |
-          find "$GITHUB_WORKSPACE" -mindepth 1 -delete 2>/dev/null || true
-          tar -xzf "$RUNNER_TEMP/source-snapshot/source-snapshot.tar.gz" -C 
"$GITHUB_WORKSPACE"
+          ref: ${{ github.sha }}
       - uses: ./.github/actions/setup-build-environment
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-suffix: 'e2e-operation'
           cache-save-enabled: 'false'
           enable-docker-setup: 'true'
-      - uses: ./.github/actions/download-e2e-artifacts
+      - id: download-e2e-artifacts
+        uses: ./.github/actions/download-e2e-artifacts
+        with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
+          artifact-id: ${{ needs.prepare-e2e-artifacts.outputs.artifact-id }}
       - name: Run ${{ matrix.operation }} on ${{ matrix.image.version }}
-        run: ./mvnw -nsu -B install -f test/e2e/operation/${{ matrix.operation 
}}/pom.xml -De2e.run.type=docker -D${{ matrix.image.type }}=${{ 
matrix.image.version }}
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -nsu -B install 
-f test/e2e/operation/${{ matrix.operation }}/pom.xml -De2e.run.type=docker 
-D${{ matrix.image.type }}=${{ matrix.image.version }} 
-De2e.docker.proxy.image="${{ steps.download-e2e-artifacts.outputs.image }}"
diff --git a/.github/workflows/e2e-sql.yml b/.github/workflows/e2e-sql.yml
index f715f4872b8..decd1c0bfff 100644
--- a/.github/workflows/e2e-sql.yml
+++ b/.github/workflows/e2e-sql.yml
@@ -43,6 +43,7 @@ permissions:
 
 env:
   MAVEN_OPTS: -Dhttp.keepAlive=false
+  MAVEN_REPOSITORY_DIR: ../.e2e-maven/repository
   SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
 
 jobs:
@@ -134,22 +135,42 @@ jobs:
     needs: [ global-environment, detect-and-generate-matrix ]
     runs-on: ${{ needs.global-environment.outputs.GLOBAL_RUNS_ON }}
     timeout-minutes: 40
+    outputs:
+      artifact-id: ${{ steps.upload-e2e-artifacts.outputs.artifact-id }}
     steps:
       - uses: actions/[email protected]
       - id: setup-build-environment
         uses: ./.github/actions/setup-build-environment
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-suffix: 'e2e-sql'
           cache-save-enabled: 'false'
           enable-docker-setup: 'true'
+      - name: Restore E2E Image Cache
+        id: prepare-image
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          image: apache/shardingsphere-proxy-test
       - name: Build E2E Image
-        run: ./mvnw -B clean install -am -pl test/e2e/sql -Pe2e.env.docker 
-DskipTests
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -B clean 
install -am -pl test/e2e/sql -Pe2e.env.docker -DskipTests 
-Ddocker.image.name="${{ steps.prepare-image.outputs.image }}" -Dexec.skip=${{ 
steps.prepare-image.outputs.cache-hit == 'true' }}
+      - name: Save E2E Image Cache
+        if: steps.prepare-image.outputs.cache-hit != 'true'
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          operation: save
+          image: ${{ steps.prepare-image.outputs.image }}
       - uses: ./.github/actions/save-maven-cache
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-hit: ${{ steps.setup-build-environment.outputs.cache-hit }}
           cache-primary-key: ${{ 
steps.setup-build-environment.outputs.cache-primary-key }}
-      - uses: ./.github/actions/upload-source-snapshot
-      - uses: ./.github/actions/upload-e2e-artifacts
+      - id: upload-e2e-artifacts
+        uses: ./.github/actions/upload-e2e-artifacts
+        with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
+          image-archive: ${{ steps.prepare-image.outputs.archive }}
 
   e2e-sql-smoke:
     name: E2E - SQL (Smoke)
@@ -167,25 +188,23 @@ jobs:
           echo "runner.temp=${{ runner.temp }}"
           echo "RUNNER_TEMP=$RUNNER_TEMP"
           echo "GITHUB_WORKSPACE=$GITHUB_WORKSPACE"
-      - name: Download Source Snapshot
-        uses: actions/download-artifact@v8
+      - uses: actions/[email protected]
         with:
-          name: source-snapshot
-          path: ${{ runner.temp }}/source-snapshot
-      - name: Restore Source Snapshot
-        run: |
-          find "$GITHUB_WORKSPACE" -mindepth 1 -delete 2>/dev/null || true
-          tar -xzf "$RUNNER_TEMP/source-snapshot/source-snapshot.tar.gz" -C 
"$GITHUB_WORKSPACE"
+          ref: ${{ github.sha }}
       - uses: ./.github/actions/setup-build-environment
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-suffix: 'e2e-sql'
           cache-save-enabled: 'false'
           enable-docker-setup: 'true'
-      - uses: ./.github/actions/download-e2e-artifacts
+      - id: download-e2e-artifacts
+        uses: ./.github/actions/download-e2e-artifacts
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
+          artifact-id: ${{ needs.prepare-e2e-artifacts.outputs.artifact-id }}
           load-docker-image: ${{ matrix.adapter == 'proxy' }}
       - name: Run E2E Test
-        run: ./mvnw -nsu -B install -f test/e2e/sql/pom.xml 
-De2e.run.type=DOCKER -De2e.artifact.modes=${{ matrix.mode }} 
-De2e.artifact.adapters=${{ matrix.adapter }} -De2e.run.additional.cases=false 
-De2e.scenarios=${{ matrix.scenario }} -De2e.artifact.databases=${{ 
matrix.database }} ${{ matrix.additional-options }}
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -nsu -B install 
-f test/e2e/sql/pom.xml -De2e.run.type=DOCKER -De2e.artifact.modes=${{ 
matrix.mode }} -De2e.artifact.adapters=${{ matrix.adapter }} 
-De2e.run.additional.cases=false -De2e.scenarios=${{ matrix.scenario }} 
-De2e.artifact.databases=${{ matrix.database }} ${{ matrix.additional-options 
}} -De2e.docker.proxy.image="${{ steps.download-e2e-artifacts.outputs.image }}"
 
   detect-remaining-matrix:
     name: Detect Remaining Matrix
@@ -200,15 +219,9 @@ jobs:
       matrix: ${{ steps.generate.outputs.matrix }}
       has-remaining-jobs: ${{ steps.generate.outputs.has-remaining-jobs }}
     steps:
-      - name: Download Source Snapshot
-        uses: actions/download-artifact@v8
+      - uses: actions/[email protected]
         with:
-          name: source-snapshot
-          path: ${{ runner.temp }}/source-snapshot
-      - name: Restore Source Snapshot
-        run: |
-          find "$GITHUB_WORKSPACE" -mindepth 1 -delete 2>/dev/null || true
-          tar -xzf "$RUNNER_TEMP/source-snapshot/source-snapshot.tar.gz" -C 
"$GITHUB_WORKSPACE"
+          ref: ${{ github.sha }}
       - name: Detect Remaining Matrix
         id: generate
         env:
@@ -240,22 +253,20 @@ jobs:
       fail-fast: false
       matrix: ${{ fromJSON(needs.detect-remaining-matrix.outputs.matrix) }}
     steps:
-      - name: Download Source Snapshot
-        uses: actions/download-artifact@v8
+      - uses: actions/[email protected]
         with:
-          name: source-snapshot
-          path: ${{ runner.temp }}/source-snapshot
-      - name: Restore Source Snapshot
-        run: |
-          find "$GITHUB_WORKSPACE" -mindepth 1 -delete 2>/dev/null || true
-          tar -xzf "$RUNNER_TEMP/source-snapshot/source-snapshot.tar.gz" -C 
"$GITHUB_WORKSPACE"
+          ref: ${{ github.sha }}
       - uses: ./.github/actions/setup-build-environment
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-suffix: 'e2e-sql'
           cache-save-enabled: 'false'
           enable-docker-setup: 'true'
-      - uses: ./.github/actions/download-e2e-artifacts
+      - id: download-e2e-artifacts
+        uses: ./.github/actions/download-e2e-artifacts
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
+          artifact-id: ${{ needs.prepare-e2e-artifacts.outputs.artifact-id }}
           load-docker-image: ${{ matrix.adapter == 'proxy' }}
       - name: Run E2E Test
-        run: ./mvnw -nsu -B install -f test/e2e/sql/pom.xml 
-De2e.run.type=DOCKER -De2e.artifact.modes=${{ matrix.mode }} 
-De2e.artifact.adapters=${{ matrix.adapter }} -De2e.run.additional.cases=false 
-De2e.scenarios=${{ matrix.scenario }} -De2e.artifact.databases=${{ 
matrix.database }} ${{ matrix.additional-options }}
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -nsu -B install 
-f test/e2e/sql/pom.xml -De2e.run.type=DOCKER -De2e.artifact.modes=${{ 
matrix.mode }} -De2e.artifact.adapters=${{ matrix.adapter }} 
-De2e.run.additional.cases=false -De2e.scenarios=${{ matrix.scenario }} 
-De2e.artifact.databases=${{ matrix.database }} ${{ matrix.additional-options 
}} -De2e.docker.proxy.image="${{ steps.download-e2e-artifacts.outputs.image }}"
diff --git a/.github/workflows/nightly-e2e-operation.yml 
b/.github/workflows/nightly-e2e-operation.yml
index f81ff2771ac..6f6f491d0f6 100644
--- a/.github/workflows/nightly-e2e-operation.yml
+++ b/.github/workflows/nightly-e2e-operation.yml
@@ -40,6 +40,7 @@ permissions:
 
 env:
   MAVEN_OPTS: -Dhttp.keepAlive=false -Dfailsafe.skipAfterFailureCount=1 
-Dio.netty.leakDetectionLevel=advanced
+  MAVEN_REPOSITORY_DIR: ../.e2e-maven/repository
 
 jobs:
   global-environment:
@@ -84,28 +85,42 @@ jobs:
     needs: global-environment
     runs-on: ${{ needs.global-environment.outputs.GLOBAL_RUNS_ON }}
     timeout-minutes: 40
+    outputs:
+      artifact-id: ${{ steps.upload-e2e-artifacts.outputs.artifact-id }}
     steps:
       - uses: actions/[email protected]
       - id: setup-build-environment
         uses: ./.github/actions/setup-build-environment
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-suffix: 'e2e-operation'
           cache-save-enabled: 'false'
           enable-docker-setup: 'true'
-      - name: Maven Install
-        env:
-          PREFIX: "test/e2e/operation/"
-          MODULE_LIST: "transaction,pipeline,showprocesslist"
-        run: |
-          FORMATTED_PL=$(echo "$MODULE_LIST" | sed "s|,|,$PREFIX|g" | sed 
"s|^|$PREFIX|")
-          echo "Ready to build: $FORMATTED_PL"
-          ./mvnw -B clean install -am -pl "$FORMATTED_PL" -Pe2e.env.docker 
-DskipTests
+      - name: Restore E2E Image Cache
+        id: prepare-image
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          image: apache/shardingsphere-proxy-test
+      - name: Build E2E Image
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -B clean 
install -am -pl 
test/e2e/operation/transaction,test/e2e/operation/pipeline,test/e2e/operation/showprocesslist
 -Pe2e.env.docker -DskipTests -Ddocker.image.name="${{ 
steps.prepare-image.outputs.image }}" -Dexec.skip=${{ 
steps.prepare-image.outputs.cache-hit == 'true' }}
+      - name: Save E2E Image Cache
+        if: steps.prepare-image.outputs.cache-hit != 'true'
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          operation: save
+          image: ${{ steps.prepare-image.outputs.image }}
       - uses: ./.github/actions/save-maven-cache
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-hit: ${{ steps.setup-build-environment.outputs.cache-hit }}
           cache-primary-key: ${{ 
steps.setup-build-environment.outputs.cache-primary-key }}
-      - uses: ./.github/actions/upload-source-snapshot
-      - uses: ./.github/actions/upload-e2e-artifacts
+      - id: upload-e2e-artifacts
+        uses: ./.github/actions/upload-e2e-artifacts
+        with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
+          image-archive: ${{ steps.prepare-image.outputs.archive }}
 
   e2e-operation-job:
     if: ${{ needs.global-environment.outputs.GLOBAL_JOB_ENABLED == 'true' }}
@@ -141,22 +156,21 @@ jobs:
           echo "runner.temp=${{ runner.temp }}"
           echo "RUNNER_TEMP=$RUNNER_TEMP"
           echo "GITHUB_WORKSPACE=$GITHUB_WORKSPACE"
-      - name: Download Source Snapshot
-        uses: actions/download-artifact@v8
+      - uses: actions/[email protected]
         with:
-          name: source-snapshot
-          path: ${{ runner.temp }}/source-snapshot
-      - name: Restore Source Snapshot
-        run: |
-          find "$GITHUB_WORKSPACE" -mindepth 1 -delete 2>/dev/null || true
-          tar -xzf "$RUNNER_TEMP/source-snapshot/source-snapshot.tar.gz" -C 
"$GITHUB_WORKSPACE"
+          ref: ${{ github.sha }}
       - uses: ./.github/actions/setup-build-environment
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           java-version: ${{ matrix.java-version }}
           cache-suffix: 'e2e-operation'
           cache-save-enabled: 'false'
           enable-docker-setup: 'true'
-      - uses: ./.github/actions/download-e2e-artifacts
+      - id: download-e2e-artifacts
+        uses: ./.github/actions/download-e2e-artifacts
+        with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
+          artifact-id: ${{ needs.prepare-e2e-artifacts.outputs.artifact-id }}
       - name: Run ${{ matrix.operation }} on ${{ matrix.image }}
         env:
           DOCKER_IMAGE: ${{ matrix.image }}
@@ -179,4 +193,4 @@ jobs:
               exit 1
               ;;
           esac
-          ./mvnw -nsu -B install -f test/e2e/operation/${{ matrix.operation 
}}/pom.xml -De2e.run.type=docker -D${DOCKER_IMAGE_PROPERTY}=${DOCKER_IMAGE}
+          ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -nsu -B install -f 
test/e2e/operation/${{ matrix.operation }}/pom.xml -De2e.run.type=docker 
-D${DOCKER_IMAGE_PROPERTY}=${DOCKER_IMAGE} -De2e.docker.proxy.image="${{ 
steps.download-e2e-artifacts.outputs.image }}"
diff --git a/.github/workflows/nightly-e2e-sql.yml 
b/.github/workflows/nightly-e2e-sql.yml
index 3206b8f5c5b..424fe627516 100644
--- a/.github/workflows/nightly-e2e-sql.yml
+++ b/.github/workflows/nightly-e2e-sql.yml
@@ -31,6 +31,7 @@ permissions:
 
 env:
   MAVEN_OPTS: -Dhttp.keepAlive=false
+  MAVEN_REPOSITORY_DIR: ../.e2e-maven/repository
   SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
 
 jobs:
@@ -44,23 +45,43 @@ jobs:
     if: ${{ needs.global-environment.outputs.GLOBAL_JOB_ENABLED == 'true' }}
     runs-on: ${{ needs.global-environment.outputs.GLOBAL_RUNS_ON }}
     timeout-minutes: 40
+    outputs:
+      artifact-id: ${{ steps.upload-e2e-artifacts.outputs.artifact-id }}
     steps:
       - uses: actions/[email protected]
       - id: setup-build-environment
         uses: ./.github/actions/setup-build-environment
         with:
           java-version: 21
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-suffix: 'e2e-sql'
           cache-save-enabled: 'false'
           enable-docker-setup: 'true'
+      - name: Restore E2E Image Cache
+        id: prepare-image
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          image: apache/shardingsphere-proxy-test
       - name: Build E2E Image
-        run: ./mvnw -B clean install -am -pl test/e2e/sql -Pe2e.env.docker 
-DskipTests
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -B clean 
install -am -pl test/e2e/sql -Pe2e.env.docker -DskipTests 
-Ddocker.image.name="${{ steps.prepare-image.outputs.image }}" -Dexec.skip=${{ 
steps.prepare-image.outputs.cache-hit == 'true' }}
+      - name: Save E2E Image Cache
+        if: steps.prepare-image.outputs.cache-hit != 'true'
+        uses: ./.github/actions/prepare-e2e-docker
+        with:
+          type: source
+          operation: save
+          image: ${{ steps.prepare-image.outputs.image }}
       - uses: ./.github/actions/save-maven-cache
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           cache-hit: ${{ steps.setup-build-environment.outputs.cache-hit }}
           cache-primary-key: ${{ 
steps.setup-build-environment.outputs.cache-primary-key }}
-      - uses: ./.github/actions/upload-source-snapshot
-      - uses: ./.github/actions/upload-e2e-artifacts
+      - id: upload-e2e-artifacts
+        uses: ./.github/actions/upload-e2e-artifacts
+        with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
+          image-archive: ${{ steps.prepare-image.outputs.archive }}
 
   e2e-sql:
     name: E2E - SQL
@@ -111,23 +132,21 @@ jobs:
           echo "runner.temp=${{ runner.temp }}"
           echo "RUNNER_TEMP=$RUNNER_TEMP"
           echo "GITHUB_WORKSPACE=$GITHUB_WORKSPACE"
-      - name: Download Source Snapshot
-        uses: actions/download-artifact@v8
+      - uses: actions/[email protected]
         with:
-          name: source-snapshot
-          path: ${{ runner.temp }}/source-snapshot
-      - name: Restore Source Snapshot
-        run: |
-          find "$GITHUB_WORKSPACE" -mindepth 1 -delete 2>/dev/null || true
-          tar -xzf "$RUNNER_TEMP/source-snapshot/source-snapshot.tar.gz" -C 
"$GITHUB_WORKSPACE"
+          ref: ${{ github.sha }}
       - uses: ./.github/actions/setup-build-environment
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
           java-version: 21
           cache-suffix: 'e2e-sql'
           cache-save-enabled: 'false'
           enable-docker-setup: 'true'
-      - uses: ./.github/actions/download-e2e-artifacts
+      - id: download-e2e-artifacts
+        uses: ./.github/actions/download-e2e-artifacts
         with:
+          maven-repository-dir: ${{ env.MAVEN_REPOSITORY_DIR }}
+          artifact-id: ${{ needs.prepare-e2e-artifacts.outputs.artifact-id }}
           load-docker-image: ${{ matrix.adapter == 'proxy' }}
       - name: Run E2E Test
-        run: ./mvnw -nsu -B install -f test/e2e/sql/pom.xml 
-De2e.run.type=DOCKER -De2e.artifact.modes=${{ matrix.mode }} 
-De2e.artifact.adapters=${{ matrix.adapter }} -De2e.run.additional.cases=false 
-De2e.scenarios=${{ matrix.scenario }} -De2e.artifact.databases=${{ 
matrix.database }} ${{ matrix.additional-options }}
+        run: ./mvnw -Dmaven.repo.local="$E2E_MAVEN_REPOSITORY" -nsu -B install 
-f test/e2e/sql/pom.xml -De2e.run.type=DOCKER -De2e.artifact.modes=${{ 
matrix.mode }} -De2e.artifact.adapters=${{ matrix.adapter }} 
-De2e.run.additional.cases=false -De2e.scenarios=${{ matrix.scenario }} 
-De2e.artifact.databases=${{ matrix.database }} ${{ matrix.additional-options 
}} -De2e.docker.proxy.image="${{ steps.download-e2e-artifacts.outputs.image }}"
diff --git a/test/e2e/agent/engine/pom.xml b/test/e2e/agent/engine/pom.xml
index 8f458ee3ee3..d6cbb51ebff 100644
--- a/test/e2e/agent/engine/pom.xml
+++ b/test/e2e/agent/engine/pom.xml
@@ -108,8 +108,6 @@
                         <artifactId>dockerfile-maven-plugin</artifactId>
                         <configuration>
                             <repository>${docker.proxy.image.name}</repository>
-                            <tag>${project.version}</tag>
-                            <tag>latest</tag>
                             <buildArgs>
                                 
<APP_NAME>${docker.proxy.distribution.name}</APP_NAME>
                             </buildArgs>
@@ -200,7 +198,6 @@
                         <artifactId>dockerfile-maven-plugin</artifactId>
                         <configuration>
                             <repository>${docker.jdbc.image.name}</repository>
-                            <tag>latest</tag>
                             
<contextDirectory>${docker.jdbc.context.directory}</contextDirectory>
                             
<dockerfile>${docker.jdbc.context.directory}/Dockerfile</dockerfile>
                         </configuration>
diff --git a/test/e2e/fixture/pom.xml b/test/e2e/fixture/pom.xml
index 87df9a565a6..f0e7cc53a19 100644
--- a/test/e2e/fixture/pom.xml
+++ b/test/e2e/fixture/pom.xml
@@ -29,6 +29,7 @@
     <properties>
         <maven.deploy.skip>true</maven.deploy.skip>
         <dockerfile.skip.build>true</dockerfile.skip.build>
+        
<docker.image.name>apache/shardingsphere-proxy-test:latest</docker.image.name>
     </properties>
     
     <dependencies>
@@ -321,9 +322,7 @@
                                         
<argument>APP_NAME=${project.build.finalName}</argument>
                                         <argument>.</argument>
                                         <argument>-t</argument>
-                                        
<argument>apache/shardingsphere-proxy-test:${project.version}</argument>
-                                        <argument>-t</argument>
-                                        
<argument>apache/shardingsphere-proxy-test:latest</argument>
+                                        
<argument>${docker.image.name}</argument>
                                     </arguments>
                                 </configuration>
                             </execution>
diff --git a/.github/actions/upload-source-snapshot/action.yml 
b/test/e2e/mcp/src/test/resources/docker/conformance/Dockerfile
similarity index 55%
rename from .github/actions/upload-source-snapshot/action.yml
rename to test/e2e/mcp/src/test/resources/docker/conformance/Dockerfile
index cfe4d71ed70..8b9fceea907 100644
--- a/.github/actions/upload-source-snapshot/action.yml
+++ b/test/e2e/mcp/src/test/resources/docker/conformance/Dockerfile
@@ -15,23 +15,12 @@
 # limitations under the License.
 #
 
-name: 'Upload Source Snapshot'
-description: 'Create and upload source snapshot to avoid repeated checkout'
+FROM 
node:22.23.3-bookworm-slim@sha256:c3de60bf2f9dd0ac6370e6117950ff62d6e339527e7472301c9c78a017978392
 
-runs:
-  using: composite
-  steps:
-    - name: Logs
-      shell: bash
-      run: |
-        echo "runner.temp=${{ runner.temp }}"
-        echo "RUNNER_TEMP=$RUNNER_TEMP"
-    - name: Create Source Snapshot
-      shell: bash
-      run: git archive --format=tar.gz 
--output="$RUNNER_TEMP/source-snapshot.tar.gz" HEAD -- . ':(exclude)docs'
-    - name: Upload Source Snapshot
-      uses: actions/upload-artifact@v6
-      with:
-        name: source-snapshot
-        path: ${{ runner.temp }}/source-snapshot.tar.gz
-        retention-days: 3
+WORKDIR /opt/mcp-conformance
+
+COPY package.json package-lock.json tsconfig.json LICENSE ./
+COPY src ./src
+RUN npm ci --ignore-scripts && npm run build
+
+ENTRYPOINT ["node", "/opt/mcp-conformance/dist/index.js"]

Reply via email to