name: Push Test Images to Docker Hub and GitHub Container Registry

concurrency:
  group: test-release
  cancel-in-progress: true

on:
  push:
    branches:
      - "master"

permissions:
  contents: write
  packages: write

jobs:
  generate-build-number:
    runs-on: ubuntu-latest
    outputs:
      build_number: ${{ steps.buildnumber.outputs.build_number }}
    steps:
      - name: Generate build number
        id: buildnumber
        uses: onyxmueller/build-tag-number@v1.0.2
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
      - run: echo "Build number is ${{ steps.buildnumber.outputs.build_number }}"

  read-version:
    runs-on: ubuntu-latest
    outputs:
      major_minor: ${{ steps.determine.outputs.semver_base }}
      semver_base: ${{ steps.determine.outputs.semver_base }}
      major: ${{ steps.determine.outputs.major }}
      minor: ${{ steps.determine.outputs.minor }}
      patch: ${{ steps.determine.outputs.patch }}
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}
      - name: Determine semver base
        id: determine
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          REPOSITORY: ${{ github.repository }}
        run: |
          set -euo pipefail

          VERSION_RAW="$(tr -d ' \n' < VERSION)"
          if [[ -z "$VERSION_RAW" ]]; then
            echo "VERSION is empty" >&2
            exit 1
          fi

          IFS='.' read -r major minor patch <<< "$VERSION_RAW"
          if [[ -z "$minor" ]]; then
            echo "VERSION must contain major and minor components" >&2
            exit 1
          fi
          patch="${patch:-0}"

          for part_name in major minor patch; do
            part="${!part_name}"
            if ! [[ "$part" =~ ^[0-9]+$ ]]; then
              echo "Invalid ${part_name} component '$part' in VERSION" >&2
              exit 1
            fi
          done

          target_patch="$patch"
          latest_tag="$(gh release view --repo "$REPOSITORY" --json tagName --jq '.tagName' 2>/dev/null || echo "")"

          if [[ -n "$latest_tag" ]]; then
            latest_tag="${latest_tag#v}"
            latest_tag_core="${latest_tag%%+*}"
            latest_tag_core="${latest_tag_core%%-*}"
            IFS='.' read -r rel_major rel_minor rel_patch _ <<< "$latest_tag_core"
            rel_patch="${rel_patch:-0}"
            if [[ "$rel_major" =~ ^[0-9]+$ && "$rel_minor" =~ ^[0-9]+$ && "$rel_patch" =~ ^[0-9]+$ ]]; then
              if [[ "$rel_major" == "$major" && "$rel_minor" == "$minor" ]]; then
                target_patch=$((rel_patch + 1))
              fi
            fi
          fi

          new_version="${major}.${minor}.${target_patch}"

          echo "semver_base=${new_version}" >> "$GITHUB_OUTPUT"
          echo "major=${major}" >> "$GITHUB_OUTPUT"
          echo "minor=${minor}" >> "$GITHUB_OUTPUT"
          echo "patch=${target_patch}" >> "$GITHUB_OUTPUT"
          echo "Using version base: ${new_version}"

  # ─── Docker image build jobs (per-arch matrix) ───────────────────────

  nginx-docker-image-build:
    needs: [read-version, generate-build-number]
    strategy:
      matrix:
        include:
          - platform: linux/amd64
            runner: ubuntu-latest
          - platform: linux/arm64
            runner: ubuntu-24.04-arm
    runs-on: ${{ matrix.runner }}
    steps:
      - name: Free Disk Space (Ubuntu)
        if: matrix.platform == 'linux/amd64'
        uses: jlumbroso/free-disk-space@main
        with:
          tool-cache: false
          android: true
          dotnet: true
          haskell: true
          large-packages: true
          docker-images: true
          swap-storage: true

      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - uses: actions/setup-node@v4
        with:
          node-version: latest

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Generate Dockerfile from Dockerfile.tpl
        run: npm run prerun

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        run: |
          bash ./Scripts/GHA/build_docker_images.sh \
            --image nginx \
            --version "${{needs.read-version.outputs.major_minor}}-test" \
            --dockerfile ./Nginx/Dockerfile \
            --context . \
            --platforms ${{ matrix.platform }} \
            --git-sha "${{ github.sha }}" \
            --extra-tags test \
            --extra-enterprise-tags enterprise-test

  nginx-docker-image-merge:
    needs: [nginx-docker-image-build, read-version]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Merge multi-arch manifests
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}-test"
          SANITIZED_VERSION="${VERSION//+/-}"
          bash ./Scripts/GHA/merge_docker_manifests.sh \
            --image nginx \
            --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test"


  e2e-docker-image-build:
    needs: [read-version, generate-build-number]
    strategy:
      matrix:
        include:
          - platform: linux/amd64
            runner: ubuntu-latest
          - platform: linux/arm64
            runner: ubuntu-24.04-arm
    runs-on: ${{ matrix.runner }}
    steps:
      - name: Free Disk Space (Ubuntu)
        if: matrix.platform == 'linux/amd64'
        uses: jlumbroso/free-disk-space@main
        with:
          tool-cache: false
          android: true
          dotnet: true
          haskell: true
          large-packages: true
          docker-images: true
          swap-storage: true

      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - uses: actions/setup-node@v4
        with:
          node-version: latest

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Generate Dockerfile from Dockerfile.tpl
        run: npm run prerun

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        run: |
          bash ./Scripts/GHA/build_docker_images.sh \
            --image e2e \
            --version "${{needs.read-version.outputs.major_minor}}-test" \
            --dockerfile ./E2E/Dockerfile \
            --context . \
            --platforms ${{ matrix.platform }} \
            --git-sha "${{ github.sha }}" \
            --extra-tags test \
            --extra-enterprise-tags enterprise-test

  e2e-docker-image-merge:
    needs: [e2e-docker-image-build, read-version]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Merge multi-arch manifests
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}-test"
          SANITIZED_VERSION="${VERSION//+/-}"
          bash ./Scripts/GHA/merge_docker_manifests.sh \
            --image e2e \
            --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test"

  test-server-docker-image-build:
    needs: [read-version, generate-build-number]
    strategy:
      matrix:
        include:
          - platform: linux/amd64
            runner: ubuntu-latest
          - platform: linux/arm64
            runner: ubuntu-24.04-arm
    runs-on: ${{ matrix.runner }}
    steps:
      - name: Free Disk Space (Ubuntu)
        if: matrix.platform == 'linux/amd64'
        uses: jlumbroso/free-disk-space@main
        with:
          tool-cache: false
          android: true
          dotnet: true
          haskell: true
          large-packages: true
          docker-images: true
          swap-storage: true

      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - uses: actions/setup-node@v4
        with:
          node-version: latest

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Generate Dockerfile from Dockerfile.tpl
        run: npm run prerun

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        run: |
          bash ./Scripts/GHA/build_docker_images.sh \
            --image test-server \
            --version "${{needs.read-version.outputs.major_minor}}-test" \
            --dockerfile ./TestServer/Dockerfile \
            --context . \
            --platforms ${{ matrix.platform }} \
            --git-sha "${{ github.sha }}" \
            --extra-tags test \
            --extra-enterprise-tags enterprise-test

  test-server-docker-image-merge:
    needs: [test-server-docker-image-build, read-version]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Merge multi-arch manifests
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}-test"
          SANITIZED_VERSION="${VERSION//+/-}"
          bash ./Scripts/GHA/merge_docker_manifests.sh \
            --image test-server \
            --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test"

  home-docker-image-build:
    needs: [read-version, generate-build-number]
    strategy:
      matrix:
        include:
          - platform: linux/amd64
            runner: ubuntu-latest
          - platform: linux/arm64
            runner: ubuntu-24.04-arm
    runs-on: ${{ matrix.runner }}
    steps:
      - name: Free Disk Space (Ubuntu)
        if: matrix.platform == 'linux/amd64'
        uses: jlumbroso/free-disk-space@main
        with:
          tool-cache: false
          android: true
          dotnet: true
          haskell: true
          large-packages: true
          docker-images: true
          swap-storage: true

      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - uses: actions/setup-node@v4
        with:
          node-version: latest

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Generate Dockerfile from Dockerfile.tpl
        run: npm run prerun

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        run: |
          bash ./Scripts/GHA/build_docker_images.sh \
            --image home \
            --version "${{needs.read-version.outputs.major_minor}}-test" \
            --dockerfile ./Home/Dockerfile \
            --context . \
            --platforms ${{ matrix.platform }} \
            --git-sha "${{ github.sha }}" \
            --extra-tags test \
            --extra-enterprise-tags enterprise-test

  home-docker-image-merge:
    needs: [home-docker-image-build, read-version]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Merge multi-arch manifests
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}-test"
          SANITIZED_VERSION="${VERSION//+/-}"
          bash ./Scripts/GHA/merge_docker_manifests.sh \
            --image home \
            --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test"

  test-docker-image-build:
    needs: [read-version, generate-build-number]
    strategy:
      matrix:
        include:
          - platform: linux/amd64
            runner: ubuntu-latest
          - platform: linux/arm64
            runner: ubuntu-24.04-arm
    runs-on: ${{ matrix.runner }}
    steps:
      - name: Free Disk Space (Ubuntu)
        if: matrix.platform == 'linux/amd64'
        uses: jlumbroso/free-disk-space@main
        with:
          tool-cache: false
          android: true
          dotnet: true
          haskell: true
          large-packages: true
          docker-images: true
          swap-storage: true

      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - uses: actions/setup-node@v4
        with:
          node-version: latest

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Generate Dockerfile from Dockerfile.tpl
        run: npm run prerun

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        run: |
          bash ./Scripts/GHA/build_docker_images.sh \
            --image test \
            --version "${{needs.read-version.outputs.major_minor}}-test" \
            --dockerfile ./Tests/Dockerfile \
            --context . \
            --platforms ${{ matrix.platform }} \
            --git-sha "${{ github.sha }}" \
            --extra-tags test \
            --extra-enterprise-tags enterprise-test

  test-docker-image-merge:
    needs: [test-docker-image-build, read-version]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Merge multi-arch manifests
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}-test"
          SANITIZED_VERSION="${VERSION//+/-}"
          bash ./Scripts/GHA/merge_docker_manifests.sh \
            --image test \
            --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test"

  probe-docker-image-build:
    needs: [read-version, generate-build-number]
    strategy:
      matrix:
        include:
          - platform: linux/amd64
            runner: ubuntu-latest
          - platform: linux/arm64
            runner: ubuntu-24.04-arm
    runs-on: ${{ matrix.runner }}
    steps:
      - name: Free Disk Space (Ubuntu)
        if: matrix.platform == 'linux/amd64'
        uses: jlumbroso/free-disk-space@main
        with:
          tool-cache: false
          android: true
          dotnet: true
          haskell: true
          large-packages: true
          docker-images: true
          swap-storage: true

      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - uses: actions/setup-node@v4
        with:
          node-version: latest

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Generate Dockerfile from Dockerfile.tpl
        run: npm run prerun

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        run: |
          bash ./Scripts/GHA/build_docker_images.sh \
            --image probe \
            --version "${{needs.read-version.outputs.major_minor}}-test" \
            --dockerfile ./Probe/Dockerfile \
            --context . \
            --platforms ${{ matrix.platform }} \
            --git-sha "${{ github.sha }}" \
            --extra-tags test \
            --extra-enterprise-tags enterprise-test

  probe-docker-image-merge:
    needs: [probe-docker-image-build, read-version]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Merge multi-arch manifests
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}-test"
          SANITIZED_VERSION="${VERSION//+/-}"
          bash ./Scripts/GHA/merge_docker_manifests.sh \
            --image probe \
            --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test"

  app-docker-image-build:
    needs: [read-version, generate-build-number]
    strategy:
      matrix:
        include:
          - platform: linux/amd64
            runner: ubuntu-latest
          - platform: linux/arm64
            runner: ubuntu-24.04-arm
    runs-on: ${{ matrix.runner }}
    steps:
      - name: Free Disk Space (Ubuntu)
        if: matrix.platform == 'linux/amd64'
        uses: jlumbroso/free-disk-space@main
        with:
          tool-cache: false
          android: true
          dotnet: true
          haskell: true
          large-packages: true
          docker-images: true
          swap-storage: true

      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - uses: actions/setup-node@v4
        with:
          node-version: latest

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Generate Dockerfile from Dockerfile.tpl
        run: npm run prerun

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        run: |
          bash ./Scripts/GHA/build_docker_images.sh \
            --image app \
            --version "${{needs.read-version.outputs.major_minor}}-test" \
            --dockerfile ./App/Dockerfile \
            --context . \
            --platforms ${{ matrix.platform }} \
            --git-sha "${{ github.sha }}" \
            --extra-tags test \
            --extra-enterprise-tags enterprise-test

  app-docker-image-merge:
    needs: [app-docker-image-build, read-version]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Merge multi-arch manifests
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}-test"
          SANITIZED_VERSION="${VERSION//+/-}"
          bash ./Scripts/GHA/merge_docker_manifests.sh \
            --image app \
            --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test"

  ai-agent-docker-image-build:
    needs: [read-version, generate-build-number]
    strategy:
      matrix:
        include:
          - platform: linux/amd64
            runner: ubuntu-latest
          - platform: linux/arm64
            runner: ubuntu-24.04-arm
    runs-on: ${{ matrix.runner }}
    steps:
      - name: Free Disk Space (Ubuntu)
        if: matrix.platform == 'linux/amd64'
        uses: jlumbroso/free-disk-space@main
        with:
          tool-cache: false
          android: true
          dotnet: true
          haskell: true
          large-packages: true
          docker-images: true
          swap-storage: true

      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - uses: actions/setup-node@v4
        with:
          node-version: latest

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Generate Dockerfile from Dockerfile.tpl
        run: npm run prerun

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        run: |
          bash ./Scripts/GHA/build_docker_images.sh \
            --image ai-agent \
            --version "${{needs.read-version.outputs.major_minor}}-test" \
            --dockerfile ./AIAgent/Dockerfile \
            --context . \
            --platforms ${{ matrix.platform }} \
            --git-sha "${{ github.sha }}" \
            --extra-tags test \
            --extra-enterprise-tags enterprise-test

  ai-agent-docker-image-merge:
    needs: [ai-agent-docker-image-build, read-version]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        run: |
          echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        run: |
          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Merge multi-arch manifests
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}-test"
          SANITIZED_VERSION="${VERSION//+/-}"
          bash ./Scripts/GHA/merge_docker_manifests.sh \
            --image ai-agent \
            --tags "${SANITIZED_VERSION},test,enterprise-${SANITIZED_VERSION},enterprise-test"

  # ─── Non-Docker jobs (unchanged) ─────────────────────────────────────

  publish-terraform-provider:
    runs-on: ubuntu-latest
    needs: [read-version, generate-build-number]
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}
      - name: Skip Terraform provider publish for test release
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}-test"
          echo "Skipping Terraform provider publish for test release $VERSION"


  test-helm-chart:
    runs-on: ubuntu-latest
    needs: [infrastructure-agent-deploy, publish-terraform-provider, home-docker-image-merge, test-server-docker-image-merge, test-docker-image-merge, probe-docker-image-merge, app-docker-image-merge, ai-agent-docker-image-merge, nginx-docker-image-merge, e2e-docker-image-merge]
    env:
      CI_PIPELINE_ID: ${{github.run_number}}
    steps:
      # Docker compose needs a lot of space to build images, so we need to free up some space first in the GitHub Actions runner
      - name: Free Disk Space (Ubuntu)
        uses: jlumbroso/free-disk-space@main
        with:
          # this might remove tools that are actually needed,
          # if set to "true" but frees about 6 GB
          tool-cache: false
          android: true
          dotnet: true
          haskell: true
          large-packages: true
          docker-images: true
          swap-storage: true
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: latest
      - run: cd HelmChart && cd Tests && bash index.sh

  test-e2e-test-saas:
    runs-on: ubuntu-latest
    needs: [test-helm-chart, generate-build-number, read-version]
    env:
      CI_PIPELINE_ID: ${{github.run_number}}
    steps:
      # Docker compose needs a lot of space to build images, so we need to free up some space first in the GitHub Actions runner
      - name: Free Disk Space (Ubuntu)
        uses: jlumbroso/free-disk-space@main
        with:
          # this might remove tools that are actually needed,
          # if set to "true" but frees about 6 GB
          tool-cache: false
          android: true
          dotnet: true
          haskell: true
          large-packages: true
          docker-images: true
          swap-storage: true
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: latest
      - name: Preinstall and enable billing
        run: |
          set -euo pipefail
          npm run prerun
          bash ./Tests/Scripts/enable-billing-env-var.sh
      - name: Pin APP_TAG to test release
        run: |
          set -euo pipefail
          VERSION="${{needs.read-version.outputs.major_minor}}-test"
          SANITIZED_VERSION="${VERSION//+/-}"
          if [ -f config.env ]; then
            if grep -q '^APP_TAG=' config.env; then
              sed -i "s/^APP_TAG=.*/APP_TAG=${SANITIZED_VERSION}/" config.env
            else
              echo "APP_TAG=${SANITIZED_VERSION}" >> config.env
            fi
          else
            echo "APP_TAG=${SANITIZED_VERSION}" > config.env
          fi
      - name: Start Server with release tag
        run: |
          set -euo pipefail
          export $(grep -v '^#' config.env | xargs)
          export APP_TAG=${{needs.read-version.outputs.major_minor}}-test
          docker compose -f docker-compose.billing.yml up --remove-orphans -d
          npm run status-check
      - name: Wait for server to start
        run: bash ./Tests/Scripts/status-check.sh http://localhost
      - name: Run E2E Tests. Run docker container e2e in docker compose file
        run: |
          export $(grep -v '^#' config.env | xargs)
          export APP_TAG=${{needs.read-version.outputs.major_minor}}-test
          docker compose -f docker-compose.dev.yml up --exit-code-from e2e --abort-on-container-exit e2e || (docker compose -f docker-compose.dev.yml logs e2e && exit 1)
      - name: Upload test results
        uses: actions/upload-artifact@v4
        # Run this on failure
        if: failure()
        with:
          # Name of the artifact to upload.
          # Optional. Default is 'artifact'
          name: test-results-${{ github.job }}-${{ github.run_attempt }}

          # A file, directory or wildcard pattern that describes what to upload
          # Required.
          path: |
            ./E2E


          # Duration after which artifact will expire in days. 0 means using default retention.
          # Minimum 1 day.
          # Maximum 90 days unless changed from the repository settings page.
          # Optional. Defaults to repository settings.
          retention-days: 7


  test-e2e-test-self-hosted:
    runs-on: ubuntu-latest
    # After all the jobs runs
    needs: [test-helm-chart, generate-build-number, read-version]
    env:
      CI_PIPELINE_ID: ${{github.run_number}}
    steps:
      # Docker compose needs a lot of space to build images, so we need to free up some space first in the GitHub Actions runner
      - name: Free Disk Space (Ubuntu)
        uses: jlumbroso/free-disk-space@main
        with:
          # this might remove tools that are actually needed,
          # if set to "true" but frees about 6 GB
          tool-cache: false
          android: true
          dotnet: true
          haskell: true
          large-packages: true
          docker-images: true
          swap-storage: true
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: latest
      - name: Preinstall
        run: |
          set -euo pipefail
          npm run prerun
      - name: Pin APP_TAG to test release
        run: |
          set -euo pipefail
          VERSION="${{needs.read-version.outputs.major_minor}}-test"
          SANITIZED_VERSION="${VERSION//+/-}"
          if [ -f config.env ]; then
            if grep -q '^APP_TAG=' config.env; then
              sed -i "s/^APP_TAG=.*/APP_TAG=${SANITIZED_VERSION}/" config.env
            else
              echo "APP_TAG=${SANITIZED_VERSION}" >> config.env
            fi
          else
            echo "APP_TAG=${SANITIZED_VERSION}" > config.env
          fi
      - name: Start Server with release tag
        run: |
          set -euo pipefail
          export $(grep -v '^#' config.env | xargs)
          export APP_TAG=${{needs.read-version.outputs.major_minor}}-test
          npm run start
      - name: Wait for server to start
        run: bash ./Tests/Scripts/status-check.sh http://localhost
      - name: Run E2E Tests. Run docker container e2e in docker compose file
        run: |
          export $(grep -v '^#' config.env | xargs)
          export APP_TAG=${{needs.read-version.outputs.major_minor}}-test
          docker compose -f docker-compose.dev.yml up --exit-code-from e2e --abort-on-container-exit e2e || (docker compose -f docker-compose.dev.yml logs e2e && exit 1)
      - name: Upload test results
        uses: actions/upload-artifact@v4
        # Run this on failure
        if: failure()
        with:
          # Name of the artifact to upload.
          # Optional. Default is 'artifact'
          name: test-results-${{ github.job }}-${{ github.run_attempt }}

          # A file, directory or wildcard pattern that describes what to upload
          # Required.
          path: |
            ./E2E


          # Duration after which artifact will expire in days. 0 means using default retention.
          # Minimum 1 day.
          # Maximum 90 days unless changed from the repository settings page.
          # Optional. Defaults to repository settings.
          retention-days: 7

  infrastructure-agent-deploy:
    needs: [read-version, generate-build-number]
    runs-on: ubuntu-latest
    steps:
      - name: Free Disk Space (Ubuntu)
        uses: jlumbroso/free-disk-space@main
        with:
          tool-cache: false
          android: true
          dotnet: true
          haskell: true
          large-packages: true
          docker-images: true
          swap-storage: true
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - name: Set up Go
        uses: actions/setup-go@v4

      - name: Install GoReleaser
        uses: goreleaser/goreleaser-action@v6.1.0
        with:
          install-only: true

      - name: GoReleaser Version
        run: goreleaser -v

      # This tool is used to generate .rpm and .deb packages
      - name: Install NFPM
        run: go install github.com/goreleaser/nfpm/v2/cmd/nfpm@latest

      - name: Show GoReleaser version
        run: goreleaser -v

      - name: Run GoReleaser
        run: cd InfrastructureAgent && export GORELEASER_CURRENT_TAG=${{needs.read-version.outputs.major_minor}}.${{needs.generate-build-number.outputs.build_number}} && goreleaser release --clean --snapshot

      - name: Release MSI Images
        run: cd InfrastructureAgent && bash build-msi.sh ${{needs.read-version.outputs.major_minor}}.${{needs.generate-build-number.outputs.build_number}}


      - name: Upload Release Binaries
        uses: actions/upload-artifact@v4
        # Run this on failure
        with:
          # Name of the artifact to upload.
          # Optional. Default is 'artifact'
          name: binaries

          # A file, directory or wildcard pattern that describes what to upload
          # Required.
          path: |
            ./InfrastructureAgent/dist


          # Duration after which artifact will expire in days. 0 means using default retention.
          # Minimum 1 day.
          # Maximum 90 days unless changed from the repository settings page.
          # Optional. Defaults to repository settings.
          retention-days: 7
