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

jiadongb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git


The following commit(s) were added to refs/heads/main by this push:
     new 9fd356c3b9 feat(release): include container images and deployment 
artifacts in release (#4219)
9fd356c3b9 is described below

commit 9fd356c3b9bfbaa4a5ea7344767da19e005130af
Author: Jiadong Bai <[email protected]>
AuthorDate: Sun Feb 22 14:41:45 2026 -0800

    feat(release): include container images and deployment artifacts in release 
(#4219)
    
    ### What changes were proposed in this PR?
    
    This PR adds Docker Compose and Helm chart as signed binary release
    artifacts alongside the source tarball, following the [Apache Flink
    Kubernetes Operator release
    
model](https://dist.apache.org/repos/dist/release/flink/flink-kubernetes-operator-1.14.0/).
    This ensures the release contains everything a new user needs to get
    started.
    
    **After this change, the release directory will contain:**
    ```
    dist.apache.org/repos/dist/dev/incubator/texera/VERSION-RCN/
      apache-texera-VERSION-src.tar.gz              + .asc + .sha512   (source 
code)
      apache-texera-VERSION-docker-compose.tar.gz   + .asc + .sha512   (Docker 
Compose bundle)
      apache-texera-VERSION-helm.tgz                + .asc + .sha512   (Helm 
chart)
    ```
    Container images are published to `ghcr.io/apache/texera-*` as
    convenience binaries built from the voted-on source. The Docker Compose
    bundle and Helm chart reference these images with pinned version tags,
    so a new user can download one artifact and run `docker compose up -d`
    to get Texera running.
    
    **Key changes:**
    - Parameterize image references in `docker-compose.yml` and Helm
    `values.yaml` with `IMAGE_REGISTRY` / `IMAGE_TAG` variables (defaults to
    `ghcr.io/apache` / `latest`)
    - Update `build-and-push-images` workflow to support both ghcr.io (via
    `GITHUB_TOKEN`) and Docker Hub
    - Extend `create-release-candidate` workflow to produce three signed
    artifacts:
      - Source tarball (existing)
      - Docker Compose deployment bundle (new)
      - Helm chart package (new)
    - Update vote email template with container image references and
    deployment verification checklist
    
    ### Any related issues, documentation, discussions?
    
    Closes #4218
    
    ### How was this PR tested?
    
    - Verified all modified YAML files are syntactically valid
    - Verified with docker-compose command and running the actions on my own
    fork
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Yes, co-authored with Claude Code (Claude Opus 4.6).
    
    ---------
    
    Co-authored-by: Claude Opus 4.6 <[email protected]>
---
 .github/release/vote-email-template.md             |  24 +-
 .github/workflows/build-and-push-images.yml        |  72 +++--
 .github/workflows/create-release-candidate.yml     | 313 +++++++++++++++------
 bin/k8s/README.md                                  |  26 +-
 .../access-control-service-deployment.yaml         |   2 +-
 bin/k8s/templates/config-service-deployment.yaml   |   2 +-
 bin/k8s/templates/example-data-loader-job.yaml     |   2 +-
 bin/k8s/templates/file-service-deployment.yaml     |   2 +-
 bin/k8s/templates/webserver-deployment.yaml        |   2 +-
 .../workflow-compiling-service-deployment.yaml     |   2 +-
 ...workflow-computing-unit-manager-deployment.yaml |   4 +-
 ...ow-computing-unit-master-prepull-daemonset.yaml |   2 +-
 bin/k8s/values.yaml                                |  20 +-
 bin/single-node/.env                               |   5 +
 bin/single-node/docker-compose.yml                 |  18 +-
 15 files changed, 339 insertions(+), 157 deletions(-)

diff --git a/.github/release/vote-email-template.md 
b/.github/release/vote-email-template.md
index c9a8d7713c..f3dd942a1d 100644
--- a/.github/release/vote-email-template.md
+++ b/.github/release/vote-email-template.md
@@ -9,9 +9,23 @@ This is a call for vote to release Apache Texera (incubating) 
${VERSION}.
 https://dist.apache.org/repos/dist/dev/incubator/texera/${VERSION}-RC${RC_NUM}/
 
 The directory contains:
-- Source tarball (.tar.gz)
-- GPG signature (.asc)
-- SHA512 checksum (.sha512)
+- Source tarball (.tar.gz) with GPG signature (.asc) and SHA512 checksum 
(.sha512)
+- Docker Compose deployment bundle with GPG signature and SHA512 checksum
+- Helm chart package with GPG signature and SHA512 checksum
+
+== Container Images ==
+
+Container images are available at:
+  ${IMAGE_REGISTRY}/texera-dashboard-service:${VERSION}
+  ${IMAGE_REGISTRY}/texera-workflow-execution-coordinator:${VERSION}
+  ${IMAGE_REGISTRY}/texera-workflow-compiling-service:${VERSION}
+  ${IMAGE_REGISTRY}/texera-file-service:${VERSION}
+  ${IMAGE_REGISTRY}/texera-config-service:${VERSION}
+  ${IMAGE_REGISTRY}/texera-access-control-service:${VERSION}
+  ${IMAGE_REGISTRY}/texera-workflow-computing-unit-managing-service:${VERSION}
+
+These images are built from the source tarball included in this release.
+The Dockerfiles are included in the source for audit and verification.
 
 == Git Tag ==
 
@@ -39,7 +53,9 @@ The vote will be open for at least 72 hours.
 [ ] No unexpected binary files
 [ ] Source tarball matches the Git tag
 [ ] Can compile from source successfully
+[ ] Docker Compose bundle deploys successfully with the published images
+[ ] Helm chart deploys successfully (if applicable)
 
 Thanks,
 [Your Name]
-Apache Texera (incubating) PPMC
\ No newline at end of file
+Apache Texera (incubating) PPMC
diff --git a/.github/workflows/build-and-push-images.yml 
b/.github/workflows/build-and-push-images.yml
index c7fa0f9d04..94011e036f 100644
--- a/.github/workflows/build-and-push-images.yml
+++ b/.github/workflows/build-and-push-images.yml
@@ -26,14 +26,14 @@ on:
         default: 'main'
         type: string
       image_tag:
-        description: 'Docker image tag to use (e.g., latest, v1.0.0)'
-        required: true
-        default: 'latest'
+        description: 'Docker image tag (e.g., latest, v1.0.0). Leave empty to 
use the short commit hash of the branch.'
+        required: false
+        default: ''
         type: string
       docker_registry:
-        description: 'Docker registry namespace (e.g., apache, myorg)'
+        description: 'Full image registry prefix (e.g., ghcr.io/apache, 
docker.io/apache)'
         required: false
-        default: 'apache'
+        default: 'ghcr.io/apache'
         type: string
       services:
         description: 'Services to build (comma-separated, "*" for all)'
@@ -58,13 +58,14 @@ on:
     # Run nightly at 2:00 AM UTC
     - cron: '0 2 * * *'
 
+permissions:
+  contents: read
+  packages: write  # Required for pushing to ghcr.io
+
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}-${{ 
github.event.inputs.image_tag || 'nightly' }}
   cancel-in-progress: false
 
-env:
-  DOCKER_REGISTRY: apache  # Will be overridden by job-level env if needed
-
 jobs:
   # Step 0: Set runtime parameters (handles both manual and scheduled runs)
   set-parameters:
@@ -79,21 +80,33 @@ jobs:
     steps:
       - name: Set build parameters
         id: set-params
+        env:
+          GH_TOKEN: ${{ github.token }}
         run: |
           # Detect if this is a scheduled run
           if [[ "${{ github.event_name }}" == "schedule" ]]; then
             echo "Nightly build detected - using nightly defaults"
             echo "branch=main" >> $GITHUB_OUTPUT
             echo "image_tag=nightly" >> $GITHUB_OUTPUT
-            echo "docker_registry=apache" >> $GITHUB_OUTPUT
+            echo "docker_registry=ghcr.io/apache" >> $GITHUB_OUTPUT
             echo "services=*" >> $GITHUB_OUTPUT
             echo "platforms=both" >> $GITHUB_OUTPUT
             echo "with_r_support=false" >> $GITHUB_OUTPUT
           else
             echo "Manual workflow_dispatch - using user inputs"
-            echo "branch=${{ github.event.inputs.branch || 'main' }}" >> 
$GITHUB_OUTPUT
-            echo "image_tag=${{ github.event.inputs.image_tag }}" >> 
$GITHUB_OUTPUT
-            echo "docker_registry=${{ github.event.inputs.docker_registry || 
'apache' }}" >> $GITHUB_OUTPUT
+            BRANCH="${{ github.event.inputs.branch || 'main' }}"
+            IMAGE_TAG="${{ github.event.inputs.image_tag }}"
+
+            # If image_tag is empty, resolve to the short commit hash of the 
branch
+            if [[ -z "$IMAGE_TAG" ]]; then
+              COMMIT_SHORT=$(gh api "repos/${{ github.repository 
}}/commits/${BRANCH}" --jq '.sha[:7]')
+              IMAGE_TAG="$COMMIT_SHORT"
+              echo "No image tag specified - using short commit hash: 
$IMAGE_TAG"
+            fi
+
+            echo "branch=$BRANCH" >> $GITHUB_OUTPUT
+            echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
+            echo "docker_registry=${{ github.event.inputs.docker_registry || 
'ghcr.io/apache' }}" >> $GITHUB_OUTPUT
             echo "services=${{ github.event.inputs.services || '*' }}" >> 
$GITHUB_OUTPUT
             echo "platforms=${{ github.event.inputs.platforms || 'both' }}" >> 
$GITHUB_OUTPUT
             echo "with_r_support=${{ github.event.inputs.with_r_support || 
'false' }}" >> $GITHUB_OUTPUT
@@ -342,7 +355,16 @@ jobs:
       - name: Set up Docker Buildx
         uses: 
docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
 
+      - name: Log in to GitHub Container Registry
+        if: startsWith(needs.set-parameters.outputs.docker_registry, 
'ghcr.io/')
+        uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # 
v3.6.0
+        with:
+          registry: ghcr.io
+          username: ${{ github.actor }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+
       - name: Log in to Docker Hub
+        if: ${{ !startsWith(needs.set-parameters.outputs.docker_registry, 
'ghcr.io/') }}
         uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # 
v3.6.0
         with:
           username: ${{ secrets.DOCKERHUB_USERNAME }}
@@ -421,7 +443,16 @@ jobs:
       - name: Set up Docker Buildx
         uses: 
docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
 
+      - name: Log in to GitHub Container Registry
+        if: startsWith(needs.set-parameters.outputs.docker_registry, 
'ghcr.io/')
+        uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # 
v3.6.0
+        with:
+          registry: ghcr.io
+          username: ${{ github.actor }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+
       - name: Log in to Docker Hub
+        if: ${{ !startsWith(needs.set-parameters.outputs.docker_registry, 
'ghcr.io/') }}
         uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # 
v3.6.0
         with:
           username: ${{ secrets.DOCKERHUB_USERNAME }}
@@ -456,7 +487,16 @@ jobs:
       DOCKER_REGISTRY: ${{ needs.set-parameters.outputs.docker_registry }}
 
     steps:
+      - name: Log in to GitHub Container Registry
+        if: startsWith(needs.set-parameters.outputs.docker_registry, 
'ghcr.io/')
+        uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # 
v3.6.0
+        with:
+          registry: ghcr.io
+          username: ${{ github.actor }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+
       - name: Log in to Docker Hub
+        if: ${{ !startsWith(needs.set-parameters.outputs.docker_registry, 
'ghcr.io/') }}
         uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # 
v3.6.0
         with:
           username: ${{ secrets.DOCKERHUB_USERNAME }}
@@ -470,14 +510,6 @@ jobs:
             ${{ env.DOCKER_REGISTRY }}/${{ matrix.image_name }}:${{ 
needs.set-parameters.outputs.image_tag }}-amd64 \
             ${{ env.DOCKER_REGISTRY }}/${{ matrix.image_name }}:${{ 
needs.set-parameters.outputs.image_tag }}-arm64
 
-          # Also tag as 'latest' if requested
-          if [[ "${{ needs.set-parameters.outputs.image_tag }}" == "latest" 
]]; then
-            docker buildx imagetools create -t \
-              ${{ env.DOCKER_REGISTRY }}/${{ matrix.image_name }}:latest \
-              ${{ env.DOCKER_REGISTRY }}/${{ matrix.image_name }}:latest-amd64 
\
-              ${{ env.DOCKER_REGISTRY }}/${{ matrix.image_name }}:latest-arm64
-          fi
-
       - name: Inspect multi-arch manifest
         run: |
           docker buildx imagetools inspect ${{ env.DOCKER_REGISTRY }}/${{ 
matrix.image_name }}:${{ needs.set-parameters.outputs.image_tag }}
diff --git a/.github/workflows/create-release-candidate.yml 
b/.github/workflows/create-release-candidate.yml
index 8ed4849b41..d15f415a90 100644
--- a/.github/workflows/create-release-candidate.yml
+++ b/.github/workflows/create-release-candidate.yml
@@ -29,6 +29,11 @@ on:
         required: true
         type: string
         default: '1'
+      image_registry:
+        description: 'Container image registry prefix (e.g., ghcr.io/apache, 
docker.io/apache)'
+        required: false
+        type: string
+        default: 'ghcr.io/apache'
 
 jobs:
   create-rc:
@@ -38,7 +43,10 @@ jobs:
       rc_num: ${{ steps.vars.outputs.rc_num }}
       tag_name: ${{ steps.vars.outputs.tag_name }}
       rc_dir: ${{ steps.vars.outputs.rc_dir }}
-      tarball_name: ${{ steps.vars.outputs.tarball_name }}
+      commit_hash: ${{ steps.vars.outputs.commit_hash }}
+      src_tarball: ${{ steps.vars.outputs.src_tarball }}
+      compose_tarball: ${{ steps.vars.outputs.compose_tarball }}
+      helm_tarball: ${{ steps.vars.outputs.helm_tarball }}
 
     steps:
       - name: Checkout code
@@ -65,6 +73,7 @@ jobs:
         run: |
           TAG_NAME="${{ github.event.inputs.tag }}"
           RC_NUM="${{ github.event.inputs.rc_number }}"
+          IMAGE_REGISTRY="${{ github.event.inputs.image_registry }}"
 
           # Parse version from tag (format: v1.1.0-incubating or 
v1.1.0-incubating-rcN)
           # Both formats are accepted, but we use the input rc_number for 
artifacts
@@ -75,85 +84,187 @@ jobs:
             exit 1
           fi
 
+          COMMIT_HASH=$(git rev-parse "$TAG_NAME")
+          COMMIT_SHORT=$(git rev-parse --short "$TAG_NAME")
           RC_DIR="${VERSION}-RC${RC_NUM}"
-          TARBALL_NAME="apache-texera-${VERSION}-src.tar.gz"
+          SRC_TARBALL="apache-texera-${VERSION}-src.tar.gz"
+          COMPOSE_TARBALL="apache-texera-${VERSION}-docker-compose.tar.gz"
+          HELM_TARBALL="apache-texera-${VERSION}-helm.tgz"
 
           echo "version=$VERSION" >> $GITHUB_OUTPUT
           echo "rc_num=$RC_NUM" >> $GITHUB_OUTPUT
           echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT
           echo "rc_dir=$RC_DIR" >> $GITHUB_OUTPUT
-          echo "tarball_name=$TARBALL_NAME" >> $GITHUB_OUTPUT
+          echo "commit_hash=$COMMIT_HASH" >> $GITHUB_OUTPUT
+          echo "commit_short=$COMMIT_SHORT" >> $GITHUB_OUTPUT
+          echo "image_registry=$IMAGE_REGISTRY" >> $GITHUB_OUTPUT
+          echo "src_tarball=$SRC_TARBALL" >> $GITHUB_OUTPUT
+          echo "compose_tarball=$COMPOSE_TARBALL" >> $GITHUB_OUTPUT
+          echo "helm_tarball=$HELM_TARBALL" >> $GITHUB_OUTPUT
 
           echo "Release Candidate: $TAG_NAME"
           echo "Version: $VERSION"
           echo "RC Number: $RC_NUM"
-          echo "Tarball: $TARBALL_NAME"
+          echo "Commit: $COMMIT_HASH ($COMMIT_SHORT)"
+          echo "Image Registry: $IMAGE_REGISTRY"
           echo "Staging directory: dist/dev/incubator/texera/$RC_DIR"
 
       - name: Create source tarball
         run: |
           TAG_NAME="${{ steps.vars.outputs.tag_name }}"
-          TARBALL_NAME="${{ steps.vars.outputs.tarball_name }}"
+          SRC_TARBALL="${{ steps.vars.outputs.src_tarball }}"
           VERSION="${{ steps.vars.outputs.version }}"
 
-          # Create a temporary directory for the archive
           TEMP_DIR=$(mktemp -d)
-          ARCHIVE_DIR="$TEMP_DIR/apache-texera-${VERSION}-src"
-
-          echo "Creating source archive in $ARCHIVE_DIR"
 
           # Export the git repository at the tag
           git archive --format=tar --prefix="apache-texera-${VERSION}-src/" 
"$TAG_NAME" | tar -x -C "$TEMP_DIR"
 
           # Create tarball
           cd "$TEMP_DIR"
-          tar -czf "$GITHUB_WORKSPACE/$TARBALL_NAME" 
"apache-texera-${VERSION}-src"
+          tar -czf "$GITHUB_WORKSPACE/$SRC_TARBALL" 
"apache-texera-${VERSION}-src"
 
           cd "$GITHUB_WORKSPACE"
 
           # Verify tarball was created
-          if [[ ! -f "$TARBALL_NAME" ]]; then
-            echo "Error: Tarball was not created"
+          if [[ ! -f "$SRC_TARBALL" ]]; then
+            echo "Error: Source tarball was not created"
             exit 1
           fi
 
           # Show tarball info
-          ls -lh "$TARBALL_NAME"
-          echo "✓ Created tarball: $TARBALL_NAME"
+          ls -lh "$SRC_TARBALL"
+          echo "✓ Created source tarball: $SRC_TARBALL"
 
-      - name: Import GPG key
+      - name: Create Docker Compose deployment bundle
         run: |
-          echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --batch --import
+          VERSION="${{ steps.vars.outputs.version }}"
+          TAG_NAME="${{ steps.vars.outputs.tag_name }}"
+          IMAGE_REGISTRY="${{ steps.vars.outputs.image_registry }}"
+          COMMIT_SHORT="${{ steps.vars.outputs.commit_short }}"
+          COMPOSE_TARBALL="${{ steps.vars.outputs.compose_tarball }}"
 
-          # List imported keys
-          gpg --list-secret-keys
+          TEMP_DIR=$(mktemp -d)
+          BUNDLE_DIR="$TEMP_DIR/apache-texera-${VERSION}-docker-compose"
+          mkdir -p "$BUNDLE_DIR"
+
+          # Export the single-node directory from the tagged source
+          mkdir -p "$TEMP_DIR/_raw"
+          git archive --format=tar "$TAG_NAME" -- bin/single-node/ sql/ | tar 
-x -C "$TEMP_DIR/_raw"
+
+          # Copy deployment files
+          cp "$TEMP_DIR/_raw/bin/single-node/docker-compose.yml" "$BUNDLE_DIR/"
+          cp "$TEMP_DIR/_raw/bin/single-node/nginx.conf" "$BUNDLE_DIR/"
+          cp -r "$TEMP_DIR/_raw/sql" "$BUNDLE_DIR/"
+
+          # Patch the SQL mount path for the self-contained bundle layout
+          # In the repo it's ../../sql (relative to bin/single-node/), in the 
bundle it's ./sql
+          sed -i 's|../../sql|./sql|g' "$BUNDLE_DIR/docker-compose.yml"
+
+          # Generate a release-pinned .env file with the version tag
+          # Start from the source .env and ensure IMAGE_REGISTRY and IMAGE_TAG 
are set
+          cp "$TEMP_DIR/_raw/bin/single-node/.env" "$BUNDLE_DIR/.env"
+          # Replace if line exists, otherwise append
+          if grep -q '^IMAGE_REGISTRY=' "$BUNDLE_DIR/.env"; then
+            sed -i "s|^IMAGE_REGISTRY=.*|IMAGE_REGISTRY=${IMAGE_REGISTRY}|" 
"$BUNDLE_DIR/.env"
+          else
+            echo "IMAGE_REGISTRY=${IMAGE_REGISTRY}" >> "$BUNDLE_DIR/.env"
+          fi
+          if grep -q '^IMAGE_TAG=' "$BUNDLE_DIR/.env"; then
+            sed -i "s|^IMAGE_TAG=.*|IMAGE_TAG=${COMMIT_SHORT}|" 
"$BUNDLE_DIR/.env"
+          else
+            echo "IMAGE_TAG=${COMMIT_SHORT}" >> "$BUNDLE_DIR/.env"
+          fi
 
-          echo "✓ GPG key imported successfully"
+          # Include the README from the repo
+          cp "$TEMP_DIR/_raw/bin/single-node/README.md" "$BUNDLE_DIR/"
+
+          # Create tarball
+          cd "$TEMP_DIR"
+          tar -czf "$GITHUB_WORKSPACE/$COMPOSE_TARBALL" 
"apache-texera-${VERSION}-docker-compose"
+
+          cd "$GITHUB_WORKSPACE"
+          ls -lh "$COMPOSE_TARBALL"
+          echo "✓ Created Docker Compose bundle: $COMPOSE_TARBALL"
 
-      - name: Create GPG signature (.asc)
+      - name: Create Helm chart package
         run: |
-          TARBALL_NAME="${{ steps.vars.outputs.tarball_name }}"
+          VERSION="${{ steps.vars.outputs.version }}"
+          TAG_NAME="${{ steps.vars.outputs.tag_name }}"
+          COMMIT_SHORT="${{ steps.vars.outputs.commit_short }}"
+          IMAGE_REGISTRY="${{ steps.vars.outputs.image_registry }}"
+          HELM_TARBALL="${{ steps.vars.outputs.helm_tarball }}"
 
-          # Sign the tarball
-          echo "${{ secrets.GPG_PASSPHRASE }}" | gpg --batch --yes 
--pinentry-mode loopback --passphrase-fd 0 \
-            --armor --detach-sign --output "${TARBALL_NAME}.asc" 
"$TARBALL_NAME"
+          # Install Helm
+          curl 
https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
 
-          # Verify signature
-          gpg --verify "${TARBALL_NAME}.asc" "$TARBALL_NAME"
+          # Export the Helm chart from the tagged source
+          # Include sql/ because bin/k8s/files/ has symlinks to ../../../sql/
+          TEMP_DIR=$(mktemp -d)
+          git archive --format=tar "$TAG_NAME" -- bin/k8s/ sql/ | tar -x -C 
"$TEMP_DIR"
+
+          CHART_DIR="$TEMP_DIR/bin/k8s"
+
+          # Resolve symlinks in the chart so it packages as a self-contained 
artifact
+          find "$CHART_DIR" -type l | while read -r link; do
+            target=$(readlink -f "$link")
+            rm "$link"
+            cp "$target" "$link"
+          done
+
+          # Update Chart.yaml with release version
+          sed -i "s/^version:.*/version: ${VERSION}/" "$CHART_DIR/Chart.yaml"
+          sed -i "s/^appVersion:.*/appVersion: \"${VERSION}\"/" 
"$CHART_DIR/Chart.yaml"
+
+          # Update values.yaml with release image registry and tag
+          sed -i "s|imageRegistry:.*|imageRegistry: ${IMAGE_REGISTRY}|" 
"$CHART_DIR/values.yaml"
+          sed -i "s|imageTag:.*|imageTag: ${COMMIT_SHORT}|" 
"$CHART_DIR/values.yaml"
+
+          # Download chart dependencies declared in Chart.yaml
+          # These tarballs are .gitignored so they're not in git archive
+          helm dependency build "$CHART_DIR"
+
+          # Package the Helm chart
+          helm package "$CHART_DIR" \
+            --version "$VERSION" \
+            --app-version "$VERSION" \
+            --destination "$GITHUB_WORKSPACE"
+
+          # Rename to our expected artifact name
+          HELM_PKG=$(ls "$GITHUB_WORKSPACE"/texera-helm-*.tgz 2>/dev/null | 
head -1)
+          if [[ -n "$HELM_PKG" && "$HELM_PKG" != 
"$GITHUB_WORKSPACE/$HELM_TARBALL" ]]; then
+            mv "$HELM_PKG" "$GITHUB_WORKSPACE/$HELM_TARBALL"
+          fi
 
-          echo "✓ Created GPG signature: ${TARBALL_NAME}.asc"
+          ls -lh "$GITHUB_WORKSPACE/$HELM_TARBALL"
+          echo "✓ Created Helm chart package: $HELM_TARBALL"
 
-      - name: Create SHA512 checksum
+      - name: Import GPG key
         run: |
-          TARBALL_NAME="${{ steps.vars.outputs.tarball_name }}"
+          echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --batch --import
 
-          # Create SHA512 checksum
-          sha512sum "$TARBALL_NAME" > "${TARBALL_NAME}.sha512"
+          # List imported keys
+          gpg --list-secret-keys
 
-          # Display checksum
-          cat "${TARBALL_NAME}.sha512"
+          echo "✓ GPG key imported successfully"
 
-          echo "✓ Created SHA512 checksum: ${TARBALL_NAME}.sha512"
+      - name: Sign and checksum all artifacts
+        run: |
+          for artifact in \
+            "${{ steps.vars.outputs.src_tarball }}" \
+            "${{ steps.vars.outputs.compose_tarball }}" \
+            "${{ steps.vars.outputs.helm_tarball }}"; do
+
+            # GPG signature
+            echo "${{ secrets.GPG_PASSPHRASE }}" | gpg --batch --yes 
--pinentry-mode loopback --passphrase-fd 0 \
+              --armor --detach-sign --output "${artifact}.asc" "$artifact"
+            gpg --verify "${artifact}.asc" "$artifact"
+            echo "✓ Signed: ${artifact}"
+
+            # SHA512 checksum
+            sha512sum "$artifact" > "${artifact}.sha512"
+            echo "✓ Checksum: ${artifact}.sha512"
+          done
 
       - name: Generate vote email template
         id: vote_email
@@ -162,9 +273,8 @@ jobs:
           RC_NUM="${{ steps.vars.outputs.rc_num }}"
           TAG_NAME="${{ steps.vars.outputs.tag_name }}"
           RC_DIR="${{ steps.vars.outputs.rc_dir }}"
-
-          # Get commit hash for the tag
-          COMMIT_HASH=$(git rev-parse "$TAG_NAME")
+          COMMIT_HASH="${{ steps.vars.outputs.commit_hash }}"
+          IMAGE_REGISTRY="${{ steps.vars.outputs.image_registry }}"
 
           # Get GPG key ID from the imported key
           GPG_KEY_ID=$(gpg --list-secret-keys --keyid-format LONG | grep 'sec' 
| head -n1 | awk '{print $2}' | cut -d'/' -f2)
@@ -174,13 +284,14 @@ jobs:
           cp .github/release/vote-email-template.md vote-email.txt
 
           # Substitute variables in the template
-          sed -i "s/\${VERSION}/${VERSION}/g" vote-email.txt
-          sed -i "s/\${RC_NUM}/${RC_NUM}/g" vote-email.txt
-          sed -i "s/\${RC_DIR}/${RC_DIR}/g" vote-email.txt
-          sed -i "s/\${TAG_NAME}/${TAG_NAME}/g" vote-email.txt
-          sed -i "s/\${COMMIT_HASH}/${COMMIT_HASH}/g" vote-email.txt
-          sed -i "s/\${GPG_KEY_ID}/${GPG_KEY_ID}/g" vote-email.txt
-          sed -i "s/\${GPG_EMAIL}/${GPG_EMAIL}/g" vote-email.txt
+          sed -i "s|\${VERSION}|${VERSION}|g" vote-email.txt
+          sed -i "s|\${RC_NUM}|${RC_NUM}|g" vote-email.txt
+          sed -i "s|\${RC_DIR}|${RC_DIR}|g" vote-email.txt
+          sed -i "s|\${TAG_NAME}|${TAG_NAME}|g" vote-email.txt
+          sed -i "s|\${COMMIT_HASH}|${COMMIT_HASH}|g" vote-email.txt
+          sed -i "s|\${GPG_KEY_ID}|${GPG_KEY_ID}|g" vote-email.txt
+          sed -i "s|\${GPG_EMAIL}|${GPG_EMAIL}|g" vote-email.txt
+          sed -i "s|\${IMAGE_REGISTRY}|${IMAGE_REGISTRY}|g" vote-email.txt
 
           echo "✓ Vote email template generated!"
 
@@ -189,9 +300,15 @@ jobs:
         with:
           name: rc-artifacts
           path: |
-            ${{ steps.vars.outputs.tarball_name }}
-            ${{ steps.vars.outputs.tarball_name }}.asc
-            ${{ steps.vars.outputs.tarball_name }}.sha512
+            ${{ steps.vars.outputs.src_tarball }}
+            ${{ steps.vars.outputs.src_tarball }}.asc
+            ${{ steps.vars.outputs.src_tarball }}.sha512
+            ${{ steps.vars.outputs.compose_tarball }}
+            ${{ steps.vars.outputs.compose_tarball }}.asc
+            ${{ steps.vars.outputs.compose_tarball }}.sha512
+            ${{ steps.vars.outputs.helm_tarball }}
+            ${{ steps.vars.outputs.helm_tarball }}.asc
+            ${{ steps.vars.outputs.helm_tarball }}.sha512
             vote-email.txt
           retention-days: 7
 
@@ -207,14 +324,19 @@ jobs:
 
       - name: Verify downloaded artifacts
         run: |
-          TARBALL_NAME="${{ needs.create-rc.outputs.tarball_name }}"
+          SRC_TARBALL="${{ needs.create-rc.outputs.src_tarball }}"
+          COMPOSE_TARBALL="${{ needs.create-rc.outputs.compose_tarball }}"
+          HELM_TARBALL="${{ needs.create-rc.outputs.helm_tarball }}"
+
           echo "Verifying downloaded artifacts..."
           ls -lh
 
-          if [[ ! -f "$TARBALL_NAME" ]] || [[ ! -f "${TARBALL_NAME}.asc" ]] || 
[[ ! -f "${TARBALL_NAME}.sha512" ]]; then
-            echo "Error: Missing required artifacts"
-            exit 1
-          fi
+          for artifact in "$SRC_TARBALL" "$COMPOSE_TARBALL" "$HELM_TARBALL"; do
+            if [[ ! -f "$artifact" ]] || [[ ! -f "${artifact}.asc" ]] || [[ ! 
-f "${artifact}.sha512" ]]; then
+              echo "Error: Missing artifact or signature/checksum for: 
$artifact"
+              exit 1
+            fi
+          done
 
           echo "✓ All artifacts downloaded successfully"
 
@@ -236,35 +358,52 @@ jobs:
 
           cd svn-texera
 
-          # Create RC directory if it doesn't exist
-          if ! svn info "$RC_DIR" >/dev/null 2>&1; then
+          # Check if RC directory already exists on the remote
+          SVN_BASE="https://dist.apache.org/repos/dist/dev/incubator/texera";
+          if svn info "$SVN_BASE/$RC_DIR" >/dev/null 2>&1; then
+            # Directory exists remotely — update (checkout) it into the 
working copy
+            svn update --depth=infinity "$RC_DIR" \
+              --username "${{ secrets.SVN_USERNAME }}" \
+              --password "${{ secrets.SVN_PASSWORD }}" \
+              --no-auth-cache || true
+            # If update didn't bring it down (empty parent checkout), do a 
sparse checkout
+            if [[ ! -d "$RC_DIR" ]]; then
+              svn update --set-depth=infinity "$RC_DIR" \
+                --username "${{ secrets.SVN_USERNAME }}" \
+                --password "${{ secrets.SVN_PASSWORD }}" \
+                --no-auth-cache
+            fi
+            echo "✓ RC directory already exists remotely, checked out: $RC_DIR"
+          else
+            # Directory doesn't exist remotely — create and add it
             mkdir -p "$RC_DIR"
             svn add "$RC_DIR"
             echo "✓ Created new RC directory: $RC_DIR"
-          else
-            svn update "$RC_DIR"
-            echo "✓ RC directory already exists: $RC_DIR"
           fi
 
       - name: Stage artifacts to SVN
         run: |
-          TARBALL_NAME="${{ needs.create-rc.outputs.tarball_name }}"
+          SRC_TARBALL="${{ needs.create-rc.outputs.src_tarball }}"
+          COMPOSE_TARBALL="${{ needs.create-rc.outputs.compose_tarball }}"
+          HELM_TARBALL="${{ needs.create-rc.outputs.helm_tarball }}"
           RC_DIR="${{ needs.create-rc.outputs.rc_dir }}"
 
           cd svn-texera/"$RC_DIR"
 
-          # Copy artifacts
-          cp "$GITHUB_WORKSPACE/$TARBALL_NAME" .
-          cp "$GITHUB_WORKSPACE/${TARBALL_NAME}.asc" .
-          cp "$GITHUB_WORKSPACE/${TARBALL_NAME}.sha512" .
+          # Copy all artifacts
+          for artifact in "$SRC_TARBALL" "$COMPOSE_TARBALL" "$HELM_TARBALL"; do
+            cp "$GITHUB_WORKSPACE/$artifact" .
+            cp "$GITHUB_WORKSPACE/${artifact}.asc" .
+            cp "$GITHUB_WORKSPACE/${artifact}.sha512" .
+          done
 
           # Add files to SVN
-          svn add "$TARBALL_NAME" "${TARBALL_NAME}.asc" 
"${TARBALL_NAME}.sha512" --force
+          svn add * --force
 
           # Check status
           svn status
 
-          echo "✓ Staged artifacts to SVN"
+          echo "✓ Staged all artifacts to SVN"
 
       - name: Commit artifacts to dist/dev
         run: |
@@ -275,7 +414,7 @@ jobs:
           cd svn-texera
 
           # Commit with descriptive message
-          svn commit -m "Add Apache Texera ${VERSION} RC${RC_NUM} artifacts" \
+          svn commit -m "Add Apache Texera ${VERSION} RC${RC_NUM} artifacts 
(source + docker-compose + helm)" \
             --username "${{ secrets.SVN_USERNAME }}" \
             --password "${{ secrets.SVN_PASSWORD }}" \
             --no-auth-cache
@@ -288,40 +427,48 @@ jobs:
           RC_NUM="${{ needs.create-rc.outputs.rc_num }}"
           TAG_NAME="${{ needs.create-rc.outputs.tag_name }}"
           RC_DIR="${{ needs.create-rc.outputs.rc_dir }}"
-          TARBALL_NAME="${{ needs.create-rc.outputs.tarball_name }}"
+          COMMIT_HASH="${{ needs.create-rc.outputs.commit_hash }}"
+          SRC_TARBALL="${{ needs.create-rc.outputs.src_tarball }}"
+          COMPOSE_TARBALL="${{ needs.create-rc.outputs.compose_tarball }}"
+          HELM_TARBALL="${{ needs.create-rc.outputs.helm_tarball }}"
 
-          echo "## Release Candidate Created Successfully! 🎉" >> 
$GITHUB_STEP_SUMMARY
+          echo "## Release Candidate Created Successfully!" >> 
$GITHUB_STEP_SUMMARY
           echo "" >> $GITHUB_STEP_SUMMARY
           echo "### Release Information" >> $GITHUB_STEP_SUMMARY
           echo "- **Version:** ${VERSION}" >> $GITHUB_STEP_SUMMARY
           echo "- **RC Number:** RC${RC_NUM}" >> $GITHUB_STEP_SUMMARY
           echo "- **Git Tag:** \`${TAG_NAME}\`" >> $GITHUB_STEP_SUMMARY
+          echo "- **Commit:** \`${COMMIT_HASH}\`" >> $GITHUB_STEP_SUMMARY
           echo "" >> $GITHUB_STEP_SUMMARY
           echo "### Artifacts Location" >> $GITHUB_STEP_SUMMARY
-          echo "📦 **Staging Directory:** 
https://dist.apache.org/repos/dist/dev/incubator/texera/${RC_DIR}/"; >> 
$GITHUB_STEP_SUMMARY
+          echo "**Staging Directory:** 
https://dist.apache.org/repos/dist/dev/incubator/texera/${RC_DIR}/"; >> 
$GITHUB_STEP_SUMMARY
           echo "" >> $GITHUB_STEP_SUMMARY
           echo "### Artifacts Created" >> $GITHUB_STEP_SUMMARY
-          echo "- \`${TARBALL_NAME}\`" >> $GITHUB_STEP_SUMMARY
-          echo "- \`${TARBALL_NAME}.asc\` (GPG signature)" >> 
$GITHUB_STEP_SUMMARY
-          echo "- \`${TARBALL_NAME}.sha512\` (SHA512 checksum)" >> 
$GITHUB_STEP_SUMMARY
+          echo "| Artifact | Description |" >> $GITHUB_STEP_SUMMARY
+          echo "|----------|-------------|" >> $GITHUB_STEP_SUMMARY
+          echo "| \`${SRC_TARBALL}\` | Source code |" >> $GITHUB_STEP_SUMMARY
+          echo "| \`${COMPOSE_TARBALL}\` | Docker Compose deployment bundle |" 
>> $GITHUB_STEP_SUMMARY
+          echo "| \`${HELM_TARBALL}\` | Helm chart for Kubernetes deployment 
|" >> $GITHUB_STEP_SUMMARY
+          echo "" >> $GITHUB_STEP_SUMMARY
+          echo "Each artifact has a corresponding \`.asc\` (GPG signature) and 
\`.sha512\` (checksum) file." >> $GITHUB_STEP_SUMMARY
           echo "" >> $GITHUB_STEP_SUMMARY
           echo "### Next Steps" >> $GITHUB_STEP_SUMMARY
-          echo "1. Verify the artifacts at the staging directory" >> 
$GITHUB_STEP_SUMMARY
-          echo "2. Send [VOTE] email to [email protected]" >> 
$GITHUB_STEP_SUMMARY
-          echo "3. Include links to:" >> $GITHUB_STEP_SUMMARY
-          echo "   - Tag: https://github.com/${{ github.repository 
}}/releases/tag/${TAG_NAME}" >> $GITHUB_STEP_SUMMARY
-          echo "   - Artifacts: 
https://dist.apache.org/repos/dist/dev/incubator/texera/${RC_DIR}/"; >> 
$GITHUB_STEP_SUMMARY
+          echo "1. Build and push container images using the \`Build and push 
images\` workflow with tag \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
+          echo "2. Verify the artifacts at the staging directory" >> 
$GITHUB_STEP_SUMMARY
+          echo "3. Send [VOTE] email to [email protected]" >> 
$GITHUB_STEP_SUMMARY
           echo "" >> $GITHUB_STEP_SUMMARY
           echo "### Verification" >> $GITHUB_STEP_SUMMARY
-          echo "" >> $GITHUB_STEP_SUMMARY
-          echo "Download artifacts from the staging directory and verify:" >> 
$GITHUB_STEP_SUMMARY
           echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
-          echo "# Import KEYS and verify signature" >> $GITHUB_STEP_SUMMARY
+          echo "# Import KEYS and verify signatures" >> $GITHUB_STEP_SUMMARY
           echo "gpg --import KEYS" >> $GITHUB_STEP_SUMMARY
-          echo "gpg --verify ${TARBALL_NAME}.asc ${TARBALL_NAME}" >> 
$GITHUB_STEP_SUMMARY
+          echo "gpg --verify ${SRC_TARBALL}.asc ${SRC_TARBALL}" >> 
$GITHUB_STEP_SUMMARY
+          echo "gpg --verify ${COMPOSE_TARBALL}.asc ${COMPOSE_TARBALL}" >> 
$GITHUB_STEP_SUMMARY
+          echo "gpg --verify ${HELM_TARBALL}.asc ${HELM_TARBALL}" >> 
$GITHUB_STEP_SUMMARY
           echo "" >> $GITHUB_STEP_SUMMARY
-          echo "# Verify SHA512 checksum" >> $GITHUB_STEP_SUMMARY
-          echo "sha512sum -c ${TARBALL_NAME}.sha512" >> $GITHUB_STEP_SUMMARY
+          echo "# Verify SHA512 checksums" >> $GITHUB_STEP_SUMMARY
+          echo "sha512sum -c ${SRC_TARBALL}.sha512" >> $GITHUB_STEP_SUMMARY
+          echo "sha512sum -c ${COMPOSE_TARBALL}.sha512" >> $GITHUB_STEP_SUMMARY
+          echo "sha512sum -c ${HELM_TARBALL}.sha512" >> $GITHUB_STEP_SUMMARY
           echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
           echo "" >> $GITHUB_STEP_SUMMARY
           echo "**KEYS file:** 
https://downloads.apache.org/incubator/texera/KEYS"; >> $GITHUB_STEP_SUMMARY
@@ -330,7 +477,7 @@ jobs:
 
       - name: Display vote email template
         run: |
-          echo "## 📧 Vote Email Template" >> $GITHUB_STEP_SUMMARY
+          echo "## Vote Email Template" >> $GITHUB_STEP_SUMMARY
           echo "" >> $GITHUB_STEP_SUMMARY
           echo "Copy the content below to send to [email protected]:" >> 
$GITHUB_STEP_SUMMARY
           echo "" >> $GITHUB_STEP_SUMMARY
diff --git a/bin/k8s/README.md b/bin/k8s/README.md
index ffb1378116..95d6cb7bb4 100644
--- a/bin/k8s/README.md
+++ b/bin/k8s/README.md
@@ -1,25 +1,3 @@
-# Texera Kubernetes Deployment
+# Kubernetes Deployment
 
-## Prerequisites
-- A running Kubernetes cluster
-- Port `30080` is available
-
-## Launch the whole stack
-Run the following command in current directory :
-```shell
-helm install texera texera-helmchart --namespace texera-dev --create-namespace
-```
-This will create a release named `texera`, a namespace named `texera-dev` and 
all the deployments and services under the namespace `texera-dev`.
-
-**Please wait for around 1 minute for all the pods to be ready**. Once all the 
pods are ready, the service should be accessible
-
-## Access the service
-
-Access `http://localhost:30080`.
-
-## Terminate the whole stack
-
-Run the following command:
-```shell
- helm uninstall texera --namespace texera-dev
-```
\ No newline at end of file
+Refer to https://github.com/Texera/texera/wiki/Install-Texera for details.
diff --git a/bin/k8s/templates/access-control-service-deployment.yaml 
b/bin/k8s/templates/access-control-service-deployment.yaml
index 9da05bfd26..adeca0b8bb 100644
--- a/bin/k8s/templates/access-control-service-deployment.yaml
+++ b/bin/k8s/templates/access-control-service-deployment.yaml
@@ -34,7 +34,7 @@ spec:
     spec:
       containers:
         - name: {{ .Values.accessControlService.name }}
-          image: {{ .Values.accessControlService.imageName }}
+          image: {{ .Values.global.imageRegistry }}/{{ 
.Values.accessControlService.imageName }}:{{ .Values.global.imageTag }}
           imagePullPolicy: {{ .Values.texeraImages.pullPolicy }}
           ports:
             - containerPort: {{ .Values.accessControlService.service.port }}
diff --git a/bin/k8s/templates/config-service-deployment.yaml 
b/bin/k8s/templates/config-service-deployment.yaml
index c003e34ec6..45f081b11d 100644
--- a/bin/k8s/templates/config-service-deployment.yaml
+++ b/bin/k8s/templates/config-service-deployment.yaml
@@ -34,7 +34,7 @@ spec:
     spec:
       containers:
         - name: {{ .Values.configService.name }}
-          image: {{ .Values.configService.imageName }}
+          image: {{ .Values.global.imageRegistry }}/{{ 
.Values.configService.imageName }}:{{ .Values.global.imageTag }}
           imagePullPolicy: {{ .Values.texeraImages.pullPolicy }}
           ports:
             - containerPort: {{ .Values.configService.service.port }}
diff --git a/bin/k8s/templates/example-data-loader-job.yaml 
b/bin/k8s/templates/example-data-loader-job.yaml
index d6d5a584fb..9c5e049138 100644
--- a/bin/k8s/templates/example-data-loader-job.yaml
+++ b/bin/k8s/templates/example-data-loader-job.yaml
@@ -30,7 +30,7 @@ spec:
       restartPolicy: Never
       containers:
         - name: example-data-loader
-          image: {{ .Values.exampleDataLoader.image }}
+          image: {{ .Values.global.imageRegistry }}/{{ 
.Values.exampleDataLoader.imageName }}:{{ .Values.global.imageTag }}
           env:
             - name: TEXERA_EXAMPLE_USERNAME
               value: {{ .Values.exampleDataLoader.username }}
diff --git a/bin/k8s/templates/file-service-deployment.yaml 
b/bin/k8s/templates/file-service-deployment.yaml
index cb009aabe8..d7cfb7c199 100644
--- a/bin/k8s/templates/file-service-deployment.yaml
+++ b/bin/k8s/templates/file-service-deployment.yaml
@@ -34,7 +34,7 @@ spec:
     spec:
       containers:
         - name: {{ .Values.fileService.name }}
-          image: {{ .Values.fileService.imageName }}
+          image: {{ .Values.global.imageRegistry }}/{{ 
.Values.fileService.imageName }}:{{ .Values.global.imageTag }}
           imagePullPolicy: {{ .Values.texeraImages.pullPolicy }}
           ports:
             - containerPort: {{ .Values.fileService.service.port }}
diff --git a/bin/k8s/templates/webserver-deployment.yaml 
b/bin/k8s/templates/webserver-deployment.yaml
index 65b8605d60..0c8656bfe8 100644
--- a/bin/k8s/templates/webserver-deployment.yaml
+++ b/bin/k8s/templates/webserver-deployment.yaml
@@ -34,7 +34,7 @@ spec:
     spec:
       containers:
         - name: {{ .Values.webserver.name }}
-          image: {{ .Values.webserver.imageName }}
+          image: {{ .Values.global.imageRegistry }}/{{ 
.Values.webserver.imageName }}:{{ .Values.global.imageTag }}
           imagePullPolicy: {{ .Values.texeraImages.pullPolicy }}
           ports:
             - containerPort: {{ .Values.webserver.service.port }}
diff --git a/bin/k8s/templates/workflow-compiling-service-deployment.yaml 
b/bin/k8s/templates/workflow-compiling-service-deployment.yaml
index eb73f68d7b..4ab10e3f9b 100644
--- a/bin/k8s/templates/workflow-compiling-service-deployment.yaml
+++ b/bin/k8s/templates/workflow-compiling-service-deployment.yaml
@@ -34,7 +34,7 @@ spec:
     spec:
       containers:
         - name: {{ .Values.workflowCompilingService.name }}
-          image: {{ .Values.workflowCompilingService.imageName }}
+          image: {{ .Values.global.imageRegistry }}/{{ 
.Values.workflowCompilingService.imageName }}:{{ .Values.global.imageTag }}
           imagePullPolicy: {{ .Values.texeraImages.pullPolicy }}
           ports:
             - containerPort: {{ .Values.workflowCompilingService.service.port 
}}
diff --git a/bin/k8s/templates/workflow-computing-unit-manager-deployment.yaml 
b/bin/k8s/templates/workflow-computing-unit-manager-deployment.yaml
index 60ddbcc913..75e5e76b30 100644
--- a/bin/k8s/templates/workflow-computing-unit-manager-deployment.yaml
+++ b/bin/k8s/templates/workflow-computing-unit-manager-deployment.yaml
@@ -35,7 +35,7 @@ spec:
       serviceAccountName: {{ 
.Values.workflowComputingUnitManager.serviceAccountName }}
       containers:
         - name: {{ .Values.workflowComputingUnitManager.name }}
-          image: {{ .Values.workflowComputingUnitManager.imageName }}
+          image: {{ .Values.global.imageRegistry }}/{{ 
.Values.workflowComputingUnitManager.imageName }}:{{ .Values.global.imageTag }}
           imagePullPolicy: {{ .Values.texeraImages.pullPolicy }}
           ports:
             - containerPort: {{ 
.Values.workflowComputingUnitManager.service.port }}
@@ -46,7 +46,7 @@ spec:
             - name: KUBERNETES_COMPUTE_UNIT_SERVICE_NAME
               value: {{ .Values.workflowComputingUnitPool.name }}-svc
             - name: KUBERNETES_IMAGE_NAME
-              value: {{ .Values.workflowComputingUnitPool.imageName }}
+              value: {{ .Values.global.imageRegistry }}/{{ 
.Values.workflowComputingUnitPool.imageName }}:{{ .Values.global.imageTag }}
             # TexeraDB Access
             - name: STORAGE_JDBC_URL
               value: jdbc:postgresql://{{ .Release.Name 
}}-postgresql:5432/texera_db?currentSchema=texera_db,public
diff --git 
a/bin/k8s/templates/workflow-computing-unit-master-prepull-daemonset.yaml 
b/bin/k8s/templates/workflow-computing-unit-master-prepull-daemonset.yaml
index e59e8b7add..b4a8d6634d 100644
--- a/bin/k8s/templates/workflow-computing-unit-master-prepull-daemonset.yaml
+++ b/bin/k8s/templates/workflow-computing-unit-master-prepull-daemonset.yaml
@@ -36,7 +36,7 @@ spec:
         - operator: "Exists"
       initContainers:
         - name: prepuller
-          image: {{ .Values.workflowComputingUnitPool.imageName }}
+          image: {{ .Values.global.imageRegistry }}/{{ 
.Values.workflowComputingUnitPool.imageName }}:{{ .Values.global.imageTag }}
           imagePullPolicy: Always
           command: ["sh", "-c", "true"]
       containers:
diff --git a/bin/k8s/values.yaml b/bin/k8s/values.yaml
index ee0de26e20..3e612ef40f 100644
--- a/bin/k8s/values.yaml
+++ b/bin/k8s/values.yaml
@@ -16,6 +16,10 @@
 # under the License.
 
 global:
+  # Container image registry and tag for all Texera services
+  # Override these to use a different registry or version
+  imageRegistry: ghcr.io/apache
+  imageTag: latest
   security:
     allowInsecureImages: true # for custom postgres image
 
@@ -110,7 +114,7 @@ texeraImages:
 # Example data loader configuration
 exampleDataLoader:
   enabled: true
-  image: apache/texera-example-data-loader:1.1.0-incubating
+  imageName: texera-example-data-loader
   username: texera
   password: texera
   datasetDir: datasets
@@ -119,7 +123,7 @@ exampleDataLoader:
 webserver:
   name: webserver
   numOfPods: 1  # Number of pods for the Texera deployment
-  imageName: apache/texera-dashboard-service:1.1.0-incubating # image name of 
the texera
+  imageName: texera-dashboard-service
   service:
     type: ClusterIP
     port: 8080
@@ -128,7 +132,7 @@ workflowComputingUnitManager:
   name: workflow-computing-unit-manager
   numOfPods: 1
   serviceAccountName: workflow-computing-unit-manager-service-account
-  imageName: 
apache/texera-workflow-computing-unit-managing-service:1.1.0-incubating
+  imageName: texera-workflow-computing-unit-managing-service
   service:
     type: ClusterIP
     port: 8888
@@ -136,7 +140,7 @@ workflowComputingUnitManager:
 workflowCompilingService:
   name: workflow-compiling-service
   numOfPods: 1
-  imageName: apache/texera-workflow-compiling-service:1.1.0-incubating
+  imageName: texera-workflow-compiling-service
   service:
     type: ClusterIP
     port: 9090
@@ -144,7 +148,7 @@ workflowCompilingService:
 fileService:
   name: file-service
   numOfPods: 1
-  imageName: apache/texera-file-service:1.1.0-incubating
+  imageName: texera-file-service
   service:
     type: ClusterIP
     port: 9092
@@ -152,7 +156,7 @@ fileService:
 configService:
   name: config-service
   numOfPods: 1
-  imageName: apache/texera-config-service:1.1.0-incubating
+  imageName: texera-config-service
   service:
     type: ClusterIP
     port: 9094
@@ -160,7 +164,7 @@ configService:
 accessControlService:
   name: access-control-service
   numOfPods: 1
-  imageName: apache/texera-access-control-service:1.1.0-incubating
+  imageName: texera-access-control-service
   service:
     type: ClusterIP
     port: 9096
@@ -177,7 +181,7 @@ workflowComputingUnitPool:
     cpu: 100
     memory: 100Gi
     nvidiaGpu: 5
-  imageName: apache/texera-workflow-execution-coordinator:1.1.0-incubating
+  imageName: texera-workflow-execution-coordinator
   service:
     port: 8085
     targetPort: 8085
diff --git a/bin/single-node/.env b/bin/single-node/.env
index f7a0d349bf..0b9c4916af 100644
--- a/bin/single-node/.env
+++ b/bin/single-node/.env
@@ -17,6 +17,11 @@
 
 TEXERA_HOST=http://localhost
 
+# Container image configuration
+# Override these to use a different registry or image version
+IMAGE_REGISTRY=ghcr.io/apache
+IMAGE_TAG=latest
+
 POSTGRES_USER=texera
 POSTGRES_PASSWORD=password
 
diff --git a/bin/single-node/docker-compose.yml 
b/bin/single-node/docker-compose.yml
index 470053e8f7..dd7425c345 100644
--- a/bin/single-node/docker-compose.yml
+++ b/bin/single-node/docker-compose.yml
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-name: texera-single-node-release-1-1-0-incubating
+name: texera-single-node
 services:
   # Part1: Specification of the storage services used by Texera
   # MinIO is an S3-compatible object storage used to store datasets and files.
@@ -78,7 +78,7 @@ services:
   # Part2: Specification of Texera's micro-services
   # FileService provides endpoints for Texera's dataset management
   file-service:
-    image: apache/texera-file-service:1.1.0-incubating
+    image: 
${IMAGE_REGISTRY:-ghcr.io/apache}/texera-file-service:${IMAGE_TAG:-latest}
     container_name: texera-file-service
     restart: always
     depends_on:
@@ -96,7 +96,7 @@ services:
 
   # ConfigService provides endpoints for configuration management
   config-service:
-    image: apache/texera-config-service:1.1.0-incubating
+    image: 
${IMAGE_REGISTRY:-ghcr.io/apache}/texera-config-service:${IMAGE_TAG:-latest}
     container_name: texera-config-service
     restart: always
     depends_on:
@@ -112,7 +112,7 @@ services:
 
   # AccessControlService handles user permissions and access control
   access-control-service:
-    image: apache/texera-access-control-service:1.1.0-incubating
+    image: 
${IMAGE_REGISTRY:-ghcr.io/apache}/texera-access-control-service:${IMAGE_TAG:-latest}
     container_name: texera-access-control-service
     restart: always
     depends_on:
@@ -128,7 +128,7 @@ services:
 
   # WorkflowComputingUnitManagingService provides endpoints for managing 
computing units
   workflow-computing-unit-managing-service:
-    image: 
apache/texera-workflow-computing-unit-managing-service:1.1.0-incubating
+    image: 
${IMAGE_REGISTRY:-ghcr.io/apache}/texera-workflow-computing-unit-managing-service:${IMAGE_TAG:-latest}
     container_name: texera-workflow-computing-unit-managing-service
     restart: always
     depends_on:
@@ -144,7 +144,7 @@ services:
 
   # WorkflowCompilingService provides endpoints for sanity check and schema 
propagation while workflows are being edited
   workflow-compiling-service:
-    image: apache/texera-workflow-compiling-service:1.1.0-incubating
+    image: 
${IMAGE_REGISTRY:-ghcr.io/apache}/texera-workflow-compiling-service:${IMAGE_TAG:-latest}
     container_name: texera-workflow-compiling-service
     restart: always
     depends_on:
@@ -161,7 +161,7 @@ services:
   # ComputingUnitMaster provides endpoints for executing workflows and 
interactions during executions.
   computing-unit-master:
     # to enable R operators, change the image tag to 
single-node-release-1-1-0-incubating-R
-    image: apache/texera-workflow-execution-coordinator:1.1.0-incubating
+    image: 
${IMAGE_REGISTRY:-ghcr.io/apache}/texera-workflow-execution-coordinator:${IMAGE_TAG:-latest}
     container_name: texera-computing-unit-master
     restart: always
     depends_on:
@@ -174,7 +174,7 @@ services:
 
   # TexeraWebApplication provides endpoints for hub resource management.
   texera-web-application:
-    image: apache/texera-dashboard-service:1.1.0-incubating
+    image: 
${IMAGE_REGISTRY:-ghcr.io/apache}/texera-dashboard-service:${IMAGE_TAG:-latest}
     container_name: texera-web-application
     restart: always
     depends_on:
@@ -213,7 +213,7 @@ services:
 
 networks:
   default:
-    name: texera-single-node-release-1-1-0-incubating
+    name: texera-single-node
 
 # persistent volumes
 volumes:

Reply via email to