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

on:
  push:
    branches:
      - "release"

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
    permissions:
      contents: write
    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 }}
      updated: ${{ steps.determine.outputs.updated }}
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}
      - name: Determine semver base and persist patch
        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"
          updated="false"
          pr_url=""
          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}"
          if [[ "$new_version" != "$VERSION_RAW" ]]; then
            echo "$new_version" > VERSION
            git config --global user.name "github-actions[bot]"
            git config --global user.email "github-actions[bot]@users.noreply.github.com"
            git add VERSION
            if ! git diff --cached --quiet; then
              branch_name="chore/bump-version-${new_version}-$(date +%s)"
              git checkout -b "$branch_name"
              git commit -m "chore: bump version to ${new_version} [skip ci]"
              git push origin "$branch_name"
              pr_title="chore: bump version to ${new_version}"
              pr_body=$'Automated change to VERSION to align release workflow with master.\n\nCreated by GitHub Actions release workflow.'
              gh pr create --repo "$REPOSITORY" --base master --head "$branch_name" --title "$pr_title" --body "$pr_body"
              pr_url="$(gh pr view "$branch_name" --repo "$REPOSITORY" --json url --jq '.url' 2>/dev/null || true)"
              updated="true"
            fi
          fi

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



  helm-chart-deploy:
    runs-on: ubuntu-latest
    needs: [generate-build-number, read-version]
    env: 
        CI_COMMIT_AUTHOR: Continuous Integration
    steps:

      - name: Install Helm 
        run: curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

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

      - name:  Build and Package Helm chart
        run: |
          cd ..
          echo '${{ secrets.GPG_PRIVATE_KEY }}' > private.key
          gpg --import private.key || true
          rm private.key
          echo "GPG key imported successfully"
          gpg --export-secret-keys >~/.gnupg/secring.gpg 
          echo "GPG key exported successfully"
          eval `ssh-agent -s`
          ssh-add - <<< '${{ secrets.HELM_CHART_GITHUB_REPO_DEPLOY_KEY }}'
          git clone git@github.com:OneUptime/helm-chart.git
          cd oneuptime/HelmChart/Public
          helm lint oneuptime
          helm template oneuptime --values oneuptime/values.yaml
          helm package --sign --key 'key@oneuptime.com' --keyring ~/.gnupg/secring.gpg oneuptime --version ${{needs.read-version.outputs.major_minor}} --app-version ${{needs.read-version.outputs.major_minor}} 
          echo "Helm Chart Package created successfully"
          cd ..
          ls
          echo "Copying the package to helm-chart repo"
          rm -r ../../helm-chart/oneuptime
          cp -r ./Public/* ../../helm-chart
          echo "Package copied successfully"
          cd .. && cd .. && cd helm-chart
          echo "Updating helm-chart repo"
          git config --global user.name "${{ env.CI_COMMIT_AUTHOR }}"
          git config --global user.email "hello@oneuptime.com"
          echo "Git config set successfully"
          echo "Adding the package to helm-chart repo"
          helm repo index .
          git add -A
          git commit -m "Helm Chart Release ${{needs.read-version.outputs.major_minor}}"
          git push origin master

  publish-mcp-server:
    runs-on: ubuntu-latest
    needs: [generate-build-number, read-version, publish-npm-packages]
    env:
      CI_PIPELINE_ID: ${{ github.run_number }}
      NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
    permissions:
      contents: write  # For creating releases
      packages: write  # For publishing packages
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Full history for changelog generation

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: latest
          cache: 'npm'

      - name: Install Common dependencies
        run: cd Common && npm install

      - name: Install Script dependencies
        run: cd Scripts && npm install

      - name: Determine version
        id: version
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}"
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "Publishing MCP server version: $VERSION"

      - name: Verify MCP server directory
        run: |
          MCP_DIR="./MCP"
          
          if [ ! -d "$MCP_DIR" ]; then
            echo "❌ MCP server directory not found"
            exit 1
          fi
          
          echo "✅ MCP server directory found"
          echo "📊 Source files:"
          find "$MCP_DIR" -type f -name "*.ts" -o -name "*.js" -o -name "*.json" | wc -l
          echo "📁 Directory structure:"
          ls -la "$MCP_DIR"

      - name: Setup npm authentication
        run: |
          # Clean up any existing npm configuration that might cause warnings
          rm -f ~/.npmrc
          # Create npmrc file with authentication
          touch ~/.npmrc
          echo "//registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN" >> ~/.npmrc
          echo "//registry.npmjs.org/:email=npm@oneuptime.com" >> ~/.npmrc
          echo "✅ npm authentication configured"

      - name: Update package version
        run: |
          cd MCP
          npm version ${{ steps.version.outputs.version }} --no-git-tag-version

      - name: Install dependencies
        run: |
          cd MCP
          npm update @oneuptime/common
          npm install

      - name: Build MCP server
        run: |
          cd MCP
          npm run build

      - name: Run tests
        run: |
          cd MCP
          npm test || echo "No tests found or tests failed, continuing..."

      - name: Verify package before publish
        run: |
          cd MCP
          echo "📦 Package information:"
          set +e
          VERIFY_OUTPUT=$(npm publish --dry-run 2>&1)
          VERIFY_EXIT=$?
          set -e
          echo "$VERIFY_OUTPUT"
          if [ $VERIFY_EXIT -ne 0 ]; then
            if echo "$VERIFY_OUTPUT" | grep -q "You cannot publish over the previously published versions"; then
              echo "⚠️ npm publish --dry-run skipped: version already published"
            else
              echo "❌ npm publish --dry-run failed"
              exit $VERIFY_EXIT
            fi
          fi
          echo "📋 Package.json bin configuration:"
          cat package.json | grep -A 5 -B 5 '"bin"'
          echo "📁 Build directory contents:"
          ls -la build/

      - name: Publish to npm
        run: |
          cd MCP
          set +e
          PUBLISH_OUTPUT=$(npm publish --access public 2>&1)
          PUBLISH_EXIT=$?
          set -e
          echo "$PUBLISH_OUTPUT"
          if [ $PUBLISH_EXIT -ne 0 ]; then
            if echo "$PUBLISH_OUTPUT" | grep -q "You cannot publish over the previously published versions"; then
              echo "⚠️ npm publish skipped: version already published"
            else
              echo "❌ npm publish failed"
              exit $PUBLISH_EXIT
            fi
          else
            echo "✅ Published @oneuptime/mcp-server@${{ steps.version.outputs.version }} to npm"
          fi

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

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push Docker images
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image mcp-server \
              --version "${{ steps.version.outputs.version }}" \
              --dockerfile ./MCP/Dockerfile.tpl \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"

      - name: Upload MCP server artifact
        uses: actions/upload-artifact@v4
        with:
          name: mcp-server-${{ steps.version.outputs.version }}
          path: ./MCP/
          retention-days: 90

  nginx-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/nginx
            ghcr.io/oneuptime/nginx
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy nginx.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image nginx \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./Nginx/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"

  e2e-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/e2e
            ghcr.io/oneuptime/e2e
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy e2e.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image e2e \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./E2E/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"

  isolated-vm-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/isolated-vm
            ghcr.io/oneuptime/isolated-vm
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy isolated-vm.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image isolated-vm \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./IsolatedVM/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"

  home-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/home
            ghcr.io/oneuptime/home
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy isolated-vm.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image home \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./Home/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"
          
            

  
  test-server-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/test-server
            ghcr.io/oneuptime/test-server
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy test-server.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image test-server \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./TestServer/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"

  otel-collector-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/otel-collector
            ghcr.io/oneuptime/otel-collector
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy otel-collector.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image otel-collector \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./OTelCollector/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"



  status-page-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/status-page
            ghcr.io/oneuptime/status-page
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy status-page.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image status-page \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./StatusPage/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"

  test-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/test
            ghcr.io/oneuptime/test
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy test.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image test \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./Tests/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"

  probe-ingest-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/probe-ingest
            ghcr.io/oneuptime/probe-ingest
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy probe-ingest.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image probe-ingest \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./ProbeIngest/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"

  
  server-monitor-ingest-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/server-monitor-ingest
            ghcr.io/oneuptime/server-monitor-ingest
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy probe-ingest.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image server-monitor-ingest \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./ServerMonitorIngest/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"
          
          
  
  telemetry-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/telemetry
            ghcr.io/oneuptime/telemetry
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy telemetry.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image telemetry \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./Telemetry/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"


  incoming-request-ingest-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/incoming-request-ingest
            ghcr.io/oneuptime/incoming-request-ingest
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy incoming-request-ingest.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image incoming-request-ingest \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./IncomingRequestIngest/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"

  probe-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/probe
            ghcr.io/oneuptime/probe
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy probe.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image probe \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./Probe/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"

  admin-dashboard-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/admin-dashboard
            ghcr.io/oneuptime/admin-dashboard
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy admin-dashboard.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image admin-dashboard \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./AdminDashboard/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"


  dashboard-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/dashboard
            ghcr.io/oneuptime/dashboard
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy dashboard.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image dashboard \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./Dashboard/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"

  app-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/app
            ghcr.io/oneuptime/app
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy app.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image app \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./App/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"


  copilot-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/copilot
            ghcr.io/oneuptime/copilot
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy app.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image copilot \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./Copilot/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"

  accounts-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/accounts
            ghcr.io/oneuptime/accounts
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy accounts.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image accounts \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./Accounts/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"


  publish-npm-packages:
    runs-on: ubuntu-latest
    needs: [generate-build-number, read-version]
    env:
      CI_PIPELINE_ID: ${{github.run_number}}
      NPM_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}}
      PACKAGE_VERSION: ${{needs.read-version.outputs.major_minor}}
    steps:
      - name: Checkout 
        uses: actions/checkout@v4
      - name: Preinstall 
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun
      - name: Publish NPM Packages
        run: bash ./Scripts/NPM/PublishAllPackages.sh

  
  llm-docker-image-deploy:
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    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

      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/llm
            ghcr.io/oneuptime/llm
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true
            

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

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

      # - name: Setup Git LFS
      #   run: git lfs install

      # # Cannot do this, no space on the gitHub standard runner. We need to use the large runner which is selfhosted
      # - name: Download the Model from Hugging Face
      #   run: mkdir -p ./LLM/Models && cd ./LLM/Models && git clone https://${{ secrets.HUGGING_FACE_USERNAME }}:${{ secrets.HUGGING_FACE_PASSWORD }}@huggingface.co/meta-llama/Meta-Llama-3-8B-Instruct

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy nginx.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image llm \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./LLM/Dockerfile \
              --context ./LLM \
              --platforms linux/amd64 \
              --git-sha "${{ github.sha }}"
        
  docs-docker-image-deploy: 
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:

      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/docs
            ghcr.io/oneuptime/docs
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true
            

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy nginx.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image docs \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./Docs/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"
        
  


  worker-docker-image-deploy: 
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:

      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/worker
            ghcr.io/oneuptime/worker
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true
            

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy nginx.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image worker \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./Worker/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"
        
  

  
  workflow-docker-image-deploy: 
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:

      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/workflow
            ghcr.io/oneuptime/workflow
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true
            

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy nginx.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image workflow \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./Workflow/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"
            
  

  publish-terraform-provider:
    runs-on: ubuntu-latest
    needs: [generate-build-number, read-version]
    env: 
      CI_PIPELINE_ID: ${{github.run_number}}
      GITHUB_TOKEN: ${{ secrets.SIMLARSEN_GITHUB_PAT }}
      GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
      TERRAFORM_PROVIDER_GITHUB_REPO_DEPLOY_KEY: ${{ secrets.TERRAFORM_PROVIDER_GITHUB_REPO_DEPLOY_KEY }}
    permissions:
      contents: write  # For creating releases
      packages: write  # For publishing packages
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Full history for changelog generation

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 'latest'
          cache: 'npm'

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.21'
          cache: true

      - name: Install GoReleaser
        uses: goreleaser/goreleaser-action@v5
        with:
          install-only: true

      - name: Determine version
        id: version
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}"
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "Publishing Terraform provider version: $VERSION"

      - name: Install dependencies
        run: |
          npm install
          if [ -d "Common" ]; then cd Common && npm install && cd ..; fi
          if [ -d "Scripts" ]; then cd Scripts && npm install && cd ..; fi

      - name:  Import GPG key
        run: |
          echo '${{ secrets.GPG_PRIVATE_KEY }}' > private.key
          gpg --import private.key || true
          rm private.key
          echo "GPG key imported successfully"
          gpg --export-secret-keys >~/.gnupg/secring.gpg 
          echo "GPG key exported successfully"

      - name: Generate Terraform provider
        run: npm run publish-terraform-provider -- --version "${{ steps.version.outputs.version }}" --github-token "${{ secrets.SIMLARSEN_GITHUB_PAT }}" --github-repo-deploy-key "${{ secrets.TERRAFORM_PROVIDER_GITHUB_REPO_DEPLOY_KEY }}"

  

  api-reference-docker-image-deploy: 
    needs: [generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:

      - name: Docker Meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            oneuptime/api-reference
            ghcr.io/oneuptime/api-reference
          tags: |
            type=raw,value=release,enable=true
            type=semver,value=${{needs.read-version.outputs.major_minor}},pattern={{version}},enable=true
            

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

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

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          image: tonistiigi/binfmt:qemu-v10.0.4
          


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

      - name: Generate Dockerfile from Dockerfile.tpl
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 10
          max_attempts: 3
          command: npm run prerun

      # Build and deploy nginx.

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Build and push
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 45
          max_attempts: 3
          command: |
            bash ./Scripts/GHA/build_docker_images.sh \
              --image api-reference \
              --version "${{needs.read-version.outputs.major_minor}}" \
              --dockerfile ./APIReference/Dockerfile \
              --context . \
              --platforms linux/amd64,linux/arm64 \
              --git-sha "${{ github.sha }}"

  push-release-tags:
    name: Push release tags before GitHub release
    needs:
      - read-version
      - generate-build-number
      - publish-mcp-server
      - nginx-docker-image-deploy
      - e2e-docker-image-deploy
      - isolated-vm-docker-image-deploy
      - home-docker-image-deploy
      - test-server-docker-image-deploy
      - otel-collector-docker-image-deploy
      - status-page-docker-image-deploy
      - test-docker-image-deploy
      - probe-ingest-docker-image-deploy
      - server-monitor-ingest-docker-image-deploy
      - telemetry-docker-image-deploy
      - incoming-request-ingest-docker-image-deploy
      - probe-docker-image-deploy
      - admin-dashboard-docker-image-deploy
      - dashboard-docker-image-deploy
      - app-docker-image-deploy
      - copilot-docker-image-deploy
      - accounts-docker-image-deploy
      - llm-docker-image-deploy
      - docs-docker-image-deploy
      - worker-docker-image-deploy
      - workflow-docker-image-deploy
      - api-reference-docker-image-deploy
      - test-e2e-release-saas
      - test-e2e-release-self-hosted
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        image: [
          "mcp-server",
          "nginx",
          "e2e",
          "isolated-vm",
          "home",
          "test-server",
          "otel-collector",
          "status-page",
          "test",
          "probe-ingest",
          "server-monitor-ingest",
          "telemetry",
          "incoming-request-ingest",
          "probe",
          "admin-dashboard",
          "dashboard",
          "app",
          "copilot",
          "accounts",
          "llm",
          "docs",
          "worker",
          "workflow",
          "api-reference"
        ]
    steps:
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.DOCKERHUB_PASSWORD }}" | docker login --username "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

      - name: Login to GitHub Container Registry
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 3
          command: |
            echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io --username "${{ github.repository_owner }}" --password-stdin

      - name: Create Docker Hub release tag from version
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}"
          docker buildx imagetools create \
            --tag oneuptime/${{ matrix.image }}:release \
            ghcr.io/oneuptime/${{ matrix.image }}:${VERSION}

      - name: Create GHCR release tag from version
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}"
          docker buildx imagetools create \
            --tag ghcr.io/oneuptime/${{ matrix.image }}:release \
            ghcr.io/oneuptime/${{ matrix.image }}:${VERSION}

      - name: Create Docker Hub enterprise release tag from version
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}"
          docker buildx imagetools create \
            --tag oneuptime/${{ matrix.image }}:enterprise-release \
            ghcr.io/oneuptime/${{ matrix.image }}:enterprise-${VERSION}

      - name: Create GHCR enterprise release tag from version
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}"
          docker buildx imagetools create \
            --tag ghcr.io/oneuptime/${{ matrix.image }}:enterprise-release \
            ghcr.io/oneuptime/${{ matrix.image }}:enterprise-${VERSION}
            
  
  

  test-e2e-release-saas: 
    runs-on: ubuntu-latest
    needs: [telemetry-docker-image-deploy, publish-mcp-server, copilot-docker-image-deploy, docs-docker-image-deploy, api-reference-docker-image-deploy, workflow-docker-image-deploy, llm-docker-image-deploy, accounts-docker-image-deploy, admin-dashboard-docker-image-deploy, app-docker-image-deploy, dashboard-docker-image-deploy, probe-ingest-docker-image-deploy, server-monitor-ingest-docker-image-deploy, isolated-vm-docker-image-deploy, home-docker-image-deploy, worker-docker-image-deploy, otel-collector-docker-image-deploy, probe-docker-image-deploy, status-page-docker-image-deploy, test-docker-image-deploy, test-server-docker-image-deploy, publish-npm-packages, e2e-docker-image-deploy, helm-chart-deploy, generate-build-number, read-version, nginx-docker-image-deploy, incoming-request-ingest-docker-image-deploy]
    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: true
          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 versioned release
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}"
          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 version tag
        run: |
          export $(grep -v '^#' config.env | xargs)
          export APP_TAG=${{needs.read-version.outputs.major_minor}}
          docker compose up --remove-orphans -d
          npm run status-check
      - name: Wait for server to start
        run: bash ./Tests/Scripts/status-check.sh http://localhost
      - name: Pull E2E test image
        run: |
          set -euo pipefail
          export $(grep -v '^#' config.env | xargs)
          export APP_TAG=${{needs.read-version.outputs.major_minor}}
          docker compose -f docker-compose.e2e.yml pull e2e
      - name: Run E2E Tests. Run docker container e2e in docker compose file
        run: |
          set -euo pipefail
          export $(grep -v '^#' config.env | xargs)
          export APP_TAG=${{needs.read-version.outputs.major_minor}}
          trap 'docker compose -f docker-compose.e2e.yml down -v || true' EXIT
          if ! docker compose -f docker-compose.e2e.yml up --exit-code-from e2e --abort-on-container-exit e2e; then
            docker compose -f docker-compose.e2e.yml logs e2e
            exit 1
          fi
      - 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-release-self-hosted: 
    runs-on: ubuntu-latest
    # After all the jobs runs
    needs: [telemetry-docker-image-deploy, publish-mcp-server, copilot-docker-image-deploy, incoming-request-ingest-docker-image-deploy, docs-docker-image-deploy, api-reference-docker-image-deploy, workflow-docker-image-deploy, llm-docker-image-deploy, accounts-docker-image-deploy, admin-dashboard-docker-image-deploy, app-docker-image-deploy, dashboard-docker-image-deploy, probe-ingest-docker-image-deploy, server-monitor-ingest-docker-image-deploy, isolated-vm-docker-image-deploy, home-docker-image-deploy, worker-docker-image-deploy, otel-collector-docker-image-deploy, probe-docker-image-deploy, status-page-docker-image-deploy, test-docker-image-deploy, test-server-docker-image-deploy, publish-npm-packages, e2e-docker-image-deploy, helm-chart-deploy, generate-build-number, read-version, nginx-docker-image-deploy]
    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: true
          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 versioned release
        run: |
          VERSION="${{needs.read-version.outputs.major_minor}}"
          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 version tag
        run: |
          export $(grep -v '^#' config.env | xargs)
          export APP_TAG=${{needs.read-version.outputs.major_minor}}
          docker compose up --remove-orphans -d
          npm run status-check
      - name: Wait for server to start
        run: bash ./Tests/Scripts/status-check.sh http://localhost
      - name: Pull E2E test image
        run: |
          set -euo pipefail
          export $(grep -v '^#' config.env | xargs)
          export APP_TAG=${{needs.read-version.outputs.major_minor}}
          docker compose -f docker-compose.e2e.yml pull e2e
      - name: Run E2E Tests. Run docker container e2e in docker compose file
        run: |
          set -euo pipefail
          export $(grep -v '^#' config.env | xargs)
          export APP_TAG=${{needs.read-version.outputs.major_minor}}
          trap 'docker compose -f docker-compose.e2e.yml down -v || true' EXIT
          if ! docker compose -f docker-compose.e2e.yml up --exit-code-from e2e --abort-on-container-exit e2e; then
            docker compose -f docker-compose.e2e.yml logs e2e
            exit 1
          fi
      - 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

  draft-github-release:
    name: Create draft GitHub release
    needs: [test-e2e-release-saas, test-e2e-release-self-hosted, generate-build-number, read-version, push-release-tags]
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/release'
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}
      - run: echo "${{needs.generate-build-number.outputs.build_number}}"
      - name: "Build Changelog"
        id: build_changelog
        uses: mikepenz/release-changelog-builder-action@v4.2.0
        with:
          configuration: "./Scripts/Release/ChangelogConfig.json"
      - run: echo "Changelog:"    
      - run: echo "${{steps.build_changelog.outputs.changelog}}"
      - name: Fallback to commit messages if changelog empty
        id: fallback_changelog
        shell: bash
        run: |
          set -euo pipefail
          CHANGELOG_CONTENT="${{steps.build_changelog.outputs.changelog}}"
          OLD_PLACEHOLDER="No significant changes were made. We have just fixed minor bugs for this release. You can find the detailed information in the commit history."
          NEW_PLACEHOLDER="(auto) No categorized pull requests. Fallback will list raw commit messages."
          if echo "$CHANGELOG_CONTENT" | grep -Fq "$OLD_PLACEHOLDER" || echo "$CHANGELOG_CONTENT" | grep -Fq "$NEW_PLACEHOLDER"; then
            echo "Detected empty placeholder changelog. Building commit list fallback."
            # Find previous tag (skip the most recent tag which might be for an older release). If none, include all commits.
            if prev_tag=$(git describe --tags --abbrev=0 $(git rev-list --tags --skip=1 --max-count=1) 2>/dev/null); then
              echo "Previous tag: $prev_tag"
              commits=$(git log --pretty=format:'- %s (%h)' "$prev_tag"..HEAD)
            else
              echo "No previous tag found; using full commit history on this branch."
              commits=$(git log --pretty=format:'- %s (%h)')
            fi
            # If still empty (e.g., no commits), keep placeholder to avoid empty body.
            if [ -z "$commits" ]; then
              commits="(no commits found)"
            fi
            {
              echo "changelog<<EOF"
              echo "## Commit Messages"
              echo ""
              echo "$commits"
              echo "EOF"
            } >> "$GITHUB_OUTPUT"
          else
            # Pass through original changelog
            {
              echo "changelog<<EOF"
              echo "$CHANGELOG_CONTENT"
              echo "EOF"
            } >> "$GITHUB_OUTPUT"
          fi
      - uses: ncipollo/release-action@v1
        with:
          tag: "${{needs.read-version.outputs.major_minor}}"
          artifactErrorsFailBuild: true
          draft: true
          allowUpdates: true
          prerelease: false
          body: |
            ${{steps.fallback_changelog.outputs.changelog}}

  infrastructure-agent-deploy:
    needs: [draft-github-release, generate-build-number, read-version]
    runs-on: ubuntu-latest
    steps:
      - 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}} && goreleaser release --clean --snapshot

      - name: Release MSI Images
        run: cd InfrastructureAgent && bash build-msi.sh ${{needs.read-version.outputs.major_minor}}
      
      # Upload binaries to github release
      - name: Release
        uses: softprops/action-gh-release@v2
        with:
          files: |
            InfrastructureAgent/dist/*
          token: ${{ secrets.GITHUB_TOKEN }}
          draft: true
          prerelease: false
          tag_name: ${{needs.read-version.outputs.major_minor}}


  finalize-github-release:
    name: Publish GitHub release
    needs: [infrastructure-agent-deploy, generate-build-number, read-version]
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/release'
    permissions:
      contents: write
    steps:
      - name: Publish release
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const tag = '${{needs.read-version.outputs.major_minor}}';
            try {
              const releases = await github.paginate(github.rest.repos.listReleases, {
                owner: context.repo.owner,
                repo: context.repo.repo,
                per_page: 100,
              });

              const release = releases.find((item) => item.tag_name === tag);

              if (!release) {
                throw new Error(`Release with tag ${tag} not found in repository ${context.repo.owner}/${context.repo.repo}`);
              }

              await github.rest.repos.updateRelease({
                owner: context.repo.owner,
                repo: context.repo.repo,
                release_id: release.id,
                draft: false,
                prerelease: false,
                make_latest: 'true',
              });

              console.log(`Published release for ${tag}`);
            } catch (error) {
              throw new Error(`Failed to publish release for tag ${tag}: ${error.message ?? error}`);
            }

