name: E2E Tests

on:
  workflow_call:
    secrets:
      PLAYWRIGHT_SERVICE_URL:
        required: false
      PLAYWRIGHT_SERVICE_ACCESS_TOKEN:
        required: false
      ENTERPRISE_LICENSE_KEY:
        required: true
      # Add other secrets if necessary
  workflow_dispatch:

env:
  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
  TURBO_TEAM: ${{ vars.TURBO_TEAM }}

permissions:
  contents: read
  actions: read

jobs:
  build:
    name: Run E2E Tests
    runs-on: ubuntu-latest
    timeout-minutes: 60
    services:
      postgres:
        image: pgvector/pgvector@sha256:9ae02a756ba16a2d69dd78058e25915e36e189bb36ddf01ceae86390d7ed786a
        env:
          POSTGRES_DB: postgres
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
        ports:
          - 5432:5432
        options: >-
          --health-cmd="pg_isready -U postgres"
          --health-interval=10s
          --health-timeout=5s
          --health-retries=5
      valkey:
        image: valkey/valkey@sha256:12ba4f45a7c3e1d0f076acd616cb230834e75a77e8516dde382720af32832d6d
        ports:
          - 6379:6379
    steps:
      - name: Harden the runner (Audit all outbound calls)
        uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
        with:
          egress-policy: audit
          allowed-endpoints: |
            ee.formbricks.com:443
            registry-1.docker.io:443
            docker.io:443

      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
      - uses: ./.github/actions/dangerous-git-checkout

      - name: Setup Node.js 22.x
        uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # v3.8.2
        with:
          node-version: 22.x

      - name: Install pnpm
        uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0

      - name: Install dependencies
        run: pnpm install --config.platform=linux --config.architecture=x64
        shell: bash

      - name: create .env
        run: cp .env.example .env
        shell: bash

      - name: Fill ENCRYPTION_KEY, ENTERPRISE_LICENSE_KEY and E2E_TESTING in .env
        run: |
          RANDOM_KEY=$(openssl rand -hex 32)
          sed -i "s/ENCRYPTION_KEY=.*/ENCRYPTION_KEY=${RANDOM_KEY}/" .env
          sed -i "s/CRON_SECRET=.*/CRON_SECRET=${RANDOM_KEY}/" .env
          sed -i "s/NEXTAUTH_SECRET=.*/NEXTAUTH_SECRET=${RANDOM_KEY}/" .env
          sed -i "s/ENTERPRISE_LICENSE_KEY=.*/ENTERPRISE_LICENSE_KEY=${{ secrets.ENTERPRISE_LICENSE_KEY }}/" .env
          sed -i "s|REDIS_URL=.*|REDIS_URL=redis://localhost:6379|" .env
          echo "" >> .env
          echo "E2E_TESTING=1" >> .env
          echo "S3_REGION=us-east-1" >> .env
          echo "S3_BUCKET_NAME=formbricks-e2e" >> .env
          echo "S3_ENDPOINT_URL=http://localhost:9000" >> .env
          echo "S3_ACCESS_KEY=devminio" >> .env
          echo "S3_SECRET_KEY=devminio123" >> .env
          echo "S3_FORCE_PATH_STYLE=1" >> .env
        shell: bash

      - name: Install MinIO client (mc)
        run: |
          set -euo pipefail
          MC_VERSION="RELEASE.2025-08-13T08-35-41Z"
          MC_BASE="https://dl.min.io/client/mc/release/linux-amd64/archive"
          MC_BIN="mc.${MC_VERSION}"
          MC_SUM="${MC_BIN}.sha256sum"

          curl -fsSL "${MC_BASE}/${MC_BIN}" -o "${MC_BIN}"
          curl -fsSL "${MC_BASE}/${MC_SUM}" -o "${MC_SUM}"

          sha256sum -c "${MC_SUM}"

          chmod +x "${MC_BIN}"
          sudo mv "${MC_BIN}" /usr/local/bin/mc

      - name: Start MinIO Server
        run: |
          set -euo pipefail

          # Start MinIO server in background
          docker run -d \
            --name minio-server \
            -p 9000:9000 \
            -p 9001:9001 \
            -e MINIO_ROOT_USER=devminio \
            -e MINIO_ROOT_PASSWORD=devminio123 \
            minio/minio:RELEASE.2025-09-07T16-13-09Z \
            server /data --console-address :9001

          echo "MinIO server started"

      - name: Wait for MinIO and create S3 bucket
        run: |
          set -euo pipefail

          echo "Waiting for MinIO to be ready..."
          ready=0
          for i in {1..60}; do
            if curl -fsS http://localhost:9000/minio/health/live >/dev/null; then
              echo "MinIO is up after ${i} seconds"
              ready=1
              break
            fi
            sleep 1
          done

          if [ "$ready" -ne 1 ]; then
            echo "::error::MinIO did not become ready within 60 seconds"
            exit 1
          fi

          mc alias set local http://localhost:9000 devminio devminio123
          mc mb --ignore-existing local/formbricks-e2e

      - name: Build App
        run: |
          pnpm build --filter=@formbricks/web...

      - name: Apply Prisma Migrations
        run: |
          # pnpm prisma migrate deploy
          pnpm db:migrate:dev

      - name: Run Rate Limiter Load Tests
        run: |
          echo "Running rate limiter load tests with Redis/Valkey..."
          cd apps/web && pnpm vitest run modules/core/rate-limit/rate-limit-load.test.ts
        shell: bash

      - name: Run Cache Integration Tests
        run: |
          echo "Running cache integration tests with Redis/Valkey..."
          cd packages/cache && pnpm vitest run src/cache-integration.test.ts
        shell: bash

      - name: Check for Enterprise License
        run: |
          LICENSE_KEY=$(grep '^ENTERPRISE_LICENSE_KEY=' .env | cut -d'=' -f2-)
          if [ -z "$LICENSE_KEY" ]; then
            echo "::error::ENTERPRISE_LICENSE_KEY in .env is empty. Please check your secret configuration."
            exit 1
          fi
          echo "License key length: ${#LICENSE_KEY}"

      - name: Disable rate limiting for E2E tests
        run: |
          echo "RATE_LIMITING_DISABLED=1" >> .env
          echo "Rate limiting disabled for E2E tests"
        shell: bash

      - name: Run App
        run: |
          echo "Starting app with enterprise license..."
          NODE_ENV=test pnpm start --filter=@formbricks/web | tee app.log 2>&1 &
          sleep 10  # Optional: gives some buffer for the app to start
          for attempt in {1..10}; do
            if [ $(curl -o /dev/null -s -w "%{http_code}" http://localhost:3000/health) -eq 200 ]; then
              echo "Application is ready."
              break
            fi
            if [ $attempt -eq 10 ]; then
              echo "Application failed to start in time."
              exit 1
            fi
            echo "Still waiting for the application to be ready..."
            sleep 10
          done

      - name: Install Playwright
        run: pnpm exec playwright install --with-deps

      - name: Determine Playwright execution mode
        shell: bash
        env:
          PLAYWRIGHT_SERVICE_URL: ${{ secrets.PLAYWRIGHT_SERVICE_URL }}
          PLAYWRIGHT_SERVICE_ACCESS_TOKEN: ${{ secrets.PLAYWRIGHT_SERVICE_ACCESS_TOKEN }}
        run: |
          set -euo pipefail

          if [[ -n "${PLAYWRIGHT_SERVICE_URL}" && -n "${PLAYWRIGHT_SERVICE_ACCESS_TOKEN}" ]]; then
            echo "PW_MODE=service" >> "$GITHUB_ENV"
          else
            echo "PW_MODE=local" >> "$GITHUB_ENV"
          fi

      - name: Run E2E Tests (Playwright Service)
        if: env.PW_MODE == 'service'
        env:
          PLAYWRIGHT_SERVICE_URL: ${{ secrets.PLAYWRIGHT_SERVICE_URL }}
          PLAYWRIGHT_SERVICE_ACCESS_TOKEN: ${{ secrets.PLAYWRIGHT_SERVICE_ACCESS_TOKEN }}
          CI: true
        run: pnpm test-e2e:azure

      - name: Run E2E Tests (Local)
        if: env.PW_MODE == 'local'
        env:
          CI: true
        run: |
          pnpm test:e2e

      - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
        if: always()
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30

      - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
        if: failure()
        with:
          name: app-logs
          path: app.log

      - name: Output App Logs
        if: failure()
        run: cat app.log
