name: Integration tests
on:
  push:
    branches:
      - 'master'
      - 'release-*'
      - '!release-1.4'
      - '!release-1.5'
  pull_request:
    branches:
      - 'master'
      - 'release-*'

env:
  # Golang version to use across CI steps
  # renovate: datasource=golang-version packageName=golang
  GOLANG_VERSION: '1.26.2'
  # a workaround to disable harden runner
  STEP_SECURITY_HARDEN_RUNNER: ${{ vars.disable_harden_runner }}

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}

permissions:
  contents: read

jobs:
  changes:
    runs-on: ubuntu-24.04
    outputs:
      backend: ${{ steps.filter.outputs.backend_any_changed }}
      frontend: ${{ steps.filter.outputs.frontend_any_changed }}
      docs: ${{ steps.filter.outputs.docs_any_changed }}
    steps:
      - name: Harden the runner (Audit all outbound calls)
        if: ${{ vars.disable_harden_runner != 'true' }}
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
        id: filter
        with:
          # Any file which is not under docs/, ui/ or is not a markdown file is counted as a backend file
          files_yaml: |
            backend:
              - '!ui/**'
              - '!**.md'
              - '!**/*.md'
              - '!docs/**'
            frontend:
              - 'ui/**'
              - Dockerfile
            docs:
              - 'docs/**'
  check-go:
    name: Ensure Go modules synchronicity
    if: ${{ needs.changes.outputs.backend == 'true' }}
    runs-on: ubuntu-24.04
    needs:
      - changes
    steps:
      - name: Harden the runner (Audit all outbound calls)
        if: ${{ vars.disable_harden_runner != 'true' }}
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit
      - name: Checkout code
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Setup Golang
        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
        with:
          go-version: ${{ env.GOLANG_VERSION }}
      - name: Download all Go modules
        run: |
          go mod download
      - name: Check for tidiness of go.mod and go.sum
        run: |
          go mod tidy
          git diff --exit-code -- .
  build-go:
    name: Build & cache Go code
    if: ${{ needs.changes.outputs.backend == 'true' }}
    runs-on: ubuntu-24.04
    needs:
      - changes
    steps:
      - name: Harden the runner (Audit all outbound calls)
        if: ${{ vars.disable_harden_runner != 'true' }}
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit
      - name: Checkout code
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Setup Golang
        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
        with:
          go-version: ${{ env.GOLANG_VERSION }}
      - name: Restore go build and module cache
        uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
        with:
          path: |
            ~/.cache/go-build
            ~/go/pkg/mod
          key: ${{ runner.os }}-go-build-v1-${{ hashFiles('**/go.sum') }}
          restore-keys: |
            ${{ runner.os }}-go-build-v1-
      - name: Download Go modules
        run: |
          go mod download
      - name: Compile all packages
        run: make build-local

  lint-go:
    permissions:
      contents: read # for actions/checkout to fetch code
      pull-requests: read # for golangci/golangci-lint-action to fetch pull requests
    name: Lint Go code
    if: ${{ needs.changes.outputs.backend == 'true' }}
    runs-on: ubuntu-24.04
    needs:
      - changes
    steps:
      - name: Harden the runner (Audit all outbound calls)
        if: ${{ vars.disable_harden_runner != 'true' }}
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit
      - name: Checkout code
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Setup Golang
        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
        with:
          go-version: ${{ env.GOLANG_VERSION }}
      - name: Run golangci-lint
        uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0
        with:
          # renovate: datasource=go packageName=github.com/golangci/golangci-lint/v2 versioning=regex:^v(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)?$
          version: v2.11.4
          args: --verbose

  test-go:
    name: Run unit tests for Go packages
    if: ${{ needs.changes.outputs.backend == 'true' }}
    runs-on: ubuntu-24.04
    needs:
      - build-go
      - changes
    env:
      GITHUB_TOKEN: ${{ secrets.E2E_TEST_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
      GITLAB_TOKEN: ${{ secrets.E2E_TEST_GITLAB_TOKEN }}
    steps:
      - name: Harden the runner (Audit all outbound calls)
        if: ${{ vars.disable_harden_runner != 'true' }}
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit
      - name: Create checkout directory
        run: mkdir -p ~/go/src/github.com/argoproj
      - name: Checkout code
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Create symlink in GOPATH
        run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
      - name: Setup Golang
        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
        with:
          go-version: ${{ env.GOLANG_VERSION }}
      - name: Install required packages
        run: |
          sudo apt-get install git -y
      - name: Switch to temporal branch so we re-attach head
        run: |
          git switch -c temporal-pr-branch
          git status
      - name: Fetch complete history for blame information
        run: |
          git fetch --prune --no-tags --depth=1 origin +refs/heads/*:refs/remotes/origin/*
      - name: Add ~/go/bin to PATH
        run: |
          echo "/home/runner/go/bin" >> $GITHUB_PATH
      - name: Add /usr/local/bin to PATH
        run: |
          echo "/usr/local/bin" >> $GITHUB_PATH
      - name: Restore go build and module cache
        uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
        with:
          path: |
            ~/.cache/go-build
            ~/go/pkg/mod
          key: ${{ runner.os }}-go-build-v1-${{ hashFiles('**/go.sum') }}
          restore-keys: |
            ${{ runner.os }}-go-build-v1-
      - name: Install all tools required for building & testing
        run: |
          make install-test-tools-local
        # We install kustomize in the dist directory
      - name: Add dist to PATH
        run: |
          echo "/home/runner/work/argo-cd/argo-cd/dist" >> $GITHUB_PATH
      - name: Setup git username and email
        run: |
          git config --global user.name "John Doe"
          git config --global user.email "john.doe@example.com"
      - name: Download Go modules
        run: |
          go mod download
      - name: Run all unit tests
        run: make test-local
      - name: Generate test results artifacts
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: test-results
          path: test-results

  test-go-race:
    name: Run unit tests with -race for Go packages
    if: ${{ needs.changes.outputs.backend == 'true' }}
    runs-on: ubuntu-24.04
    needs:
      - build-go
      - changes
    env:
      GITHUB_TOKEN: ${{ secrets.E2E_TEST_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
      GITLAB_TOKEN: ${{ secrets.E2E_TEST_GITLAB_TOKEN }}
    steps:
      - name: Harden the runner (Audit all outbound calls)
        if: ${{ vars.disable_harden_runner != 'true' }}
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit    
      - name: Create checkout directory
        run: mkdir -p ~/go/src/github.com/argoproj
      - name: Checkout code
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Create symlink in GOPATH
        run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
      - name: Setup Golang
        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
        with:
          go-version: ${{ env.GOLANG_VERSION }}
      - name: Install required packages
        run: |
          sudo apt-get install git -y
      - name: Switch to temporal branch so we re-attach head
        run: |
          git switch -c temporal-pr-branch
          git status
      - name: Fetch complete history for blame information
        run: |
          git fetch --prune --no-tags --depth=1 origin +refs/heads/*:refs/remotes/origin/*
      - name: Add ~/go/bin to PATH
        run: |
          echo "/home/runner/go/bin" >> $GITHUB_PATH
      - name: Add /usr/local/bin to PATH
        run: |
          echo "/usr/local/bin" >> $GITHUB_PATH
      - name: Restore go build and module cache
        uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
        with:
          path: |
            ~/.cache/go-build
            ~/go/pkg/mod
          key: ${{ runner.os }}-go-build-v1-${{ hashFiles('**/go.sum') }}
          restore-keys: |
            ${{ runner.os }}-go-build-v1-
      - name: Install all tools required for building & testing
        run: |
          make install-test-tools-local
        # We install kustomize in the dist directory
      - name: Add dist to PATH
        run: |
          echo "/home/runner/work/argo-cd/argo-cd/dist" >> $GITHUB_PATH
      - name: Setup git username and email
        run: |
          git config --global user.name "John Doe"
          git config --global user.email "john.doe@example.com"
      - name: Download Go modules
        run: |
          go mod download
      - name: Run all unit tests
        run: make test-race-local
      - name: Generate test results artifacts
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: race-results
          path: test-results/

  codegen:
    name: Check changes to generated code
    if: ${{ needs.changes.outputs.backend == 'true' || needs.changes.outputs.docs == 'true'}}
    runs-on: ubuntu-24.04
    needs:
      - changes
    steps:
      - name: Harden the runner (Audit all outbound calls)
        if: ${{ vars.disable_harden_runner != 'true' }}
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit      
      - name: Checkout code
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Setup Golang
        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
        with:
          go-version: ${{ env.GOLANG_VERSION }}
      - name: Create symlink in GOPATH
        # generalizing repo name for forks:  ${{ github.event.repository.name }}
        run: |
          mkdir -p ~/go/src/github.com/argoproj
          cp -a ../${{ github.event.repository.name }} ~/go/src/github.com/argoproj
      - name: Add ~/go/bin to PATH
        run: |
          echo "/home/runner/go/bin" >> $GITHUB_PATH
      - name: Add /usr/local/bin to PATH
        run: |
          echo "/usr/local/bin" >> $GITHUB_PATH
      - name: Download & vendor dependencies
        run: |
          # We need to vendor go modules for codegen yet
          go mod download
          go mod vendor -v
        # generalizing repo name for forks:  ${{ github.event.repository.name }}
        working-directory: /home/runner/go/src/github.com/argoproj/${{ github.event.repository.name }}
      - name: Install toolchain for codegen
        run: |
          make install-codegen-tools-local
          make install-go-tools-local
        # generalizing repo name for forks:  ${{ github.event.repository.name }}
        working-directory: /home/runner/go/src/github.com/argoproj/${{ github.event.repository.name }}
        # We install kustomize in the dist directory
      - name: Add dist to PATH
        run: |
          echo "/home/runner/work/argo-cd/argo-cd/dist" >> $GITHUB_PATH
      - name: Run codegen
        run: |
          set -x
          export GOPATH=$(go env GOPATH)
          git checkout -- go.mod go.sum
          make codegen-local
        # generalizing repo name for forks:  ${{ github.event.repository.name }}
        working-directory: /home/runner/go/src/github.com/argoproj/${{ github.event.repository.name }}
      - name: Check nothing has changed
        run: |
          set -xo pipefail
          git diff --exit-code -- . ':!go.sum' ':!go.mod' ':!assets/swagger.json' | tee codegen.patch
        # generalizing repo name for forks:  ${{ github.event.repository.name }}
        working-directory: /home/runner/go/src/github.com/argoproj/${{ github.event.repository.name }}

  build-ui:
    name: Build, test & lint UI code
    # We run UI logic for backend changes so that we have a complete set of coverage documents to send to codecov.
    if: ${{ needs.changes.outputs.backend == 'true' || needs.changes.outputs.frontend == 'true' }}
    runs-on: ubuntu-24.04
    needs:
      - changes
    steps:
      - name: Harden the runner (Audit all outbound calls)
        if: ${{ vars.disable_harden_runner != 'true' }}
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit      
      - name: Checkout code
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Install pnpm
        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
        with:
          package_json_file: ui/package.json
      - name: Setup NodeJS
        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
        with:
          # renovate: datasource=node-version packageName=node versioning=node
          node-version: '24.14.1'
          cache: 'pnpm'
          cache-dependency-path: '**/pnpm-lock.yaml'
      - name: Install node dependencies
        run: |
          cd ui && pnpm i --frozen-lockfile
      - name: Build UI code
        run: |
          pnpm test
          pnpm build
        env:
          NODE_ENV: production
          NODE_ONLINE_ENV: online
          HOST_ARCH: amd64
          # If we're on the master branch, set the codecov token so that we upload bundle analysis
          CODECOV_TOKEN: ${{ github.ref == 'refs/heads/master' && secrets.CODECOV_TOKEN || '' }}
        working-directory: ui/
      - name: Run ESLint
        run: pnpm lint
        working-directory: ui/

  shellcheck:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - run: |
          sudo apt-get install shellcheck
          shellcheck -e SC2059 -e SC2154 -e SC2034 -e SC2016 -e SC1091 $(find . -type f -name '*.sh' | grep -v './ui/node_modules') | tee sc.log
          test ! -s sc.log

  analyze:
    name: Process & analyze test artifacts
    if: ${{ needs.changes.outputs.backend == 'true' || needs.changes.outputs.frontend == 'true' }}
    runs-on: ubuntu-24.04
    needs:
      - test-go
      - build-ui
      - changes
      - test-e2e
    env:
      sonar_secret: ${{ secrets.SONAR_TOKEN }}
      codecov_secret: ${{ secrets.CODECOV_TOKEN }}
    steps:
      - name: Harden the runner (Audit all outbound calls)
        if: ${{ vars.disable_harden_runner != 'true' }}
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit      
      - name: Checkout code
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0
      - name: Get e2e code coverage
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
        with:
          name: e2e-code-coverage
          path: e2e-code-coverage
      - name: Get unit test code coverage
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
        with:
          name: test-results
          path: test-results
      - name: combine-go-coverage
        # We generate coverage reports for all Argo CD components, but only the applicationset-controller,
        # app-controller, repo-server, and commit-server report contain coverage data. The other components currently
        # don't shut down gracefully, so no coverage data is produced. Once those components are fixed, we can add
        # references to their coverage output directories.
        run: |
          go tool covdata percent -i=test-results,e2e-code-coverage/applicationset-controller,e2e-code-coverage/repo-server,e2e-code-coverage/app-controller,e2e-code-coverage/commit-server -o test-results/full-coverage.out
      - name: Upload code coverage information to codecov.io
        # Only run when the workflow is for upstream (PR target or push is in argoproj/argo-cd).
        if: github.repository == 'argoproj/argo-cd'
        uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
        with:
          files: test-results/full-coverage.out
          fail_ci_if_error: true
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
      - name: Upload test results to Codecov
        # Codecov uploads test results to Codecov.io on upstream master branch.
        if: github.repository == 'argoproj/argo-cd' && github.ref == 'refs/heads/master' && github.event_name == 'push'
        uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
        with:
          files: test-results/junit.xml
          fail_ci_if_error: true
          token: ${{ secrets.CODECOV_TOKEN }}
          report_type: test_results
      - name: Perform static code analysis using SonarCloud
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
        uses: SonarSource/sonarqube-scan-action@299e4b793aaa83bf2aba7c9c14bedbb485688ec4 # v7.1.0
        if: env.sonar_secret != ''
  test-e2e:
    name: Run end-to-end tests
    if: ${{ needs.changes.outputs.backend == 'true' }}
    runs-on: ${{ github.repository == 'argoproj/argo-cd' && 'oracle-vm-16cpu-64gb-x86-64' || 'ubuntu-24.04' }}
    strategy:
      fail-fast: false
      matrix:
        # latest: true means that this version mush upload the coverage report to codecov.io
        # We designate the latest version because we only collect code coverage for that version.
        k3s:
          - version: v1.35.0
            latest: true
          - version: v1.34.2
            latest: false
          - version: v1.33.1
            latest: false
          - version: v1.32.1
            latest: false
    needs:
      - build-go
      - changes
    env:
      ARGOCD_FAKE_IN_CLUSTER: 'true'
      ARGOCD_E2E_K3S: 'true'
      ARGOCD_IN_CI: 'true'
      ARGOCD_E2E_APISERVER_PORT: '8088'
      ARGOCD_APPLICATION_NAMESPACES: 'argocd-e2e-external,argocd-e2e-external-2'
      ARGOCD_SERVER: '127.0.0.1:8088'
      GITHUB_TOKEN: ${{ secrets.E2E_TEST_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
      GITLAB_TOKEN: ${{ secrets.E2E_TEST_GITLAB_TOKEN }}
    steps:
      - name: Harden the runner (Audit all outbound calls)
        if: ${{ vars.disable_harden_runner != 'true' }}
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit      
      - name: Free Disk Space (Ubuntu)
        uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
        with:
          large-packages: false
          docker-images: false
          swap-storage: false
          tool-cache: false
      - name: Checkout code
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Setup Golang
        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
        with:
          go-version: ${{ env.GOLANG_VERSION }}
      - name: Set GOPATH
        run: |
          echo "GOPATH=$HOME/go" >> $GITHUB_ENV
      - name: Setup NodeJS
        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
        with:
          # renovate: datasource=node-version packageName=node versioning=node
          node-version: '24.14.1'
      - name: Install pnpm
        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
        with:
          package_json_file: ui/package.json
      - name: GH actions workaround - Kill XSP4 process
        run: |
          sudo pkill mono || true
      - name: Install K3S
        env:
          INSTALL_K3S_VERSION: ${{ matrix.k3s.version }}+k3s1
        run: |
          set -x
          curl -sfL https://get.k3s.io | sh -
          sudo chmod -R a+rw /etc/rancher/k3s
          sudo mkdir -p $HOME/.kube && sudo chown -R $(whoami) $HOME/.kube
          sudo k3s kubectl config view --raw > $HOME/.kube/config
          sudo chown $(whoami) $HOME/.kube/config
          sudo chmod go-r $HOME/.kube/config
          kubectl version
      - name: Restore go build and module cache
        uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
        with:
          path: |
            ~/.cache/go-build
            ~/go/pkg/mod
          key: ${{ runner.os }}-go-build-v1-${{ hashFiles('**/go.sum') }}
          restore-keys: |
            ${{ runner.os }}-go-build-v1-
      - name: Add ~/go/bin to PATH
        run: |
          echo "$HOME/go/bin" >> $GITHUB_PATH
      - name: Add /usr/local/bin to PATH
        run: |
          echo "/usr/local/bin" >> $GITHUB_PATH
      - name: Add ./dist to PATH
        run: |
          echo "$(pwd)/dist" >> $GITHUB_PATH
      - name: Download Go modules
        run: |
          go mod download
      - name: Install goreman
        run: |
          go install github.com/mattn/goreman@v0.3.17
      - name: Install all tools required for building & testing
        run: |
          make install-test-tools-local
      - name: Setup git username and email
        run: |
          git config --global user.name "John Doe"
          git config --global user.email "john.doe@example.com"
      - name: Pull Docker image required for tests
        run: |
          docker pull ghcr.io/dexidp/dex:v2.45.0
          docker pull argoproj/argo-cd-ci-builder:v1.0.0
          docker pull redis:8.2.3-alpine
      - name: Create target directory for binaries in the build-process
        run: |
          mkdir -p dist
          chown $(whoami) dist
      - name: Run E2E server and wait for it being available
        timeout-minutes: 30
        run: |
          set -x
          # Something is weird in GH runners -- there's a phantom listener for
          # port 8080 which is not visible in netstat -tulpen, but still there
          # with a HTTP listener. We have API server listening on port 8088
          # instead.
          make start-e2e-local COVERAGE_ENABLED=true 2>&1 | sed -r "s/[[:cntrl:]]\[[0-9]{1,3}m//g" > /tmp/e2e-server.log &
          count=1
          until curl -f http://127.0.0.1:8088/healthz; do
            sleep 10;
            if test $count -ge 180; then
              echo "Timeout"
              exit 1
            fi
            count=$((count+1))
          done
      - name: Run E2E testsuite
        run: |
          set -x
          make test-e2e-local
          goreman run stop-all || echo "goreman trouble"
          sleep 30
      - name: Upload e2e coverage report
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: e2e-code-coverage
          path: /tmp/coverage
        if: ${{ matrix.k3s.latest }}
      - name: Upload e2e-server logs
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: e2e-server-k8s${{ matrix.k3s.version }}.log
          path: /tmp/e2e-server.log
        if: ${{ failure() }}

  # workaround for status checks -- check this one job instead of each individual E2E job in the matrix
  # this allows us to skip the entire matrix when it doesn't need to run while still having accurate status checks
  # see:
  # https://github.com/argoproj/argo-workflows/pull/12006
  # https://github.com/orgs/community/discussions/9141#discussioncomment-2296809
  # https://github.com/orgs/community/discussions/26822#discussioncomment-3305794
  test-e2e-composite-result:
    name: E2E Tests - Composite result
    if: ${{ always() }}
    needs:
      - test-e2e
      - changes
    runs-on: ubuntu-24.04
    steps:
      - name: Harden the runner (Audit all outbound calls)
        if: ${{ vars.disable_harden_runner != 'true' }}
        uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
        with:
          egress-policy: audit      
      - run: |
          result="${{ needs.test-e2e.result }}"
          # mark as successful even if skipped
          if [[ $result == "success" || $result == "skipped" ]]; then
            exit 0
          else
            exit 1
          fi
