name: Jcloude Tests

on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - '*'
  workflow_dispatch:

env:
  DB_NAME: test_jingrow
  DB_USER: test_jingrow
  DB_PASSWORD: test_jingrow

concurrency:
  group: ${{ github.ref }}
  cancel-in-progress: true

jobs:
  format:
    name: 'Lint and Format'
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.10'

      - name: Install dependencies
        run: |
          pip install -r dev-requirements.txt

      - name: Get changed files
        id: changed-python-files
        uses: tj-actions/changed-files@v45
        with:
          files: |
            **.py

      - name: List all changed files
        if: steps.changed-python-files.outputs.any_changed == 'true'
        env:
          ALL_CHANGED_FILES: ${{ steps.changed-python-files.outputs.all_changed_files }}
        run: |
          for file in ${ALL_CHANGED_FILES}; do
            echo "$file was changed"
          done

      - name: Lint Check
        if: steps.changed-python-files.outputs.any_changed == 'true'
        env:
          ALL_CHANGED_FILES: ${{ steps.changed-python-files.outputs.all_changed_files }}
        run: |
          ruff check --output-format github ${ALL_CHANGED_FILES}

      - name: Format Check
        if: steps.changed-python-files.outputs.any_changed == 'true'
        env:
          ALL_CHANGED_FILES: ${{ steps.changed-python-files.outputs.all_changed_files }}
        run: |
          ruff format --check ${ALL_CHANGED_FILES} --diff

      - name: Typing Check
        if: steps.changed-python-files.outputs.any_changed == 'true'
        env:
          ALL_CHANGED_FILES: ${{ steps.changed-python-files.outputs.all_changed_files }}
        run: |
          mypy ${ALL_CHANGED_FILES}

  semgrep:
    name: Semgrep Rules
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.10'
      - name: Run Semgrep rules
        run: |
          pip install semgrep==1.32
          semgrep ci --config ./jcloude-semgrep-rules.yml --config r/python.lang.correctness

  ui-tests:
    name: Client
    runs-on: ubuntu-latest
    env:
      JCLOUDE_ADMIN_USER_EMAIL: playwright@example.com
      JCLOUDE_ADMIN_USER_PASSWORD: playwright
      BASE_URL: http://test_site:8000

    services:
      mariadb:
        image: mariadb:10.6
        env:
          MYSQL_ROOT_PASSWORD: root
        ports:
          - 3306:3306
        options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3

    steps:
      - name: Remove unnecessary files
        run: |
          sudo rm -rf /usr/share/dotnet
          sudo rm -rf "$AGENT_TOOLSDIRECTORY"

      - name: Clone
        uses: actions/checkout@v4

      - name: Check for valid Python & Merge Conflicts
        run: |
          python -m compileall -q -f "${GITHUB_WORKSPACE}"
          if grep -lr --exclude-dir=node_modules "^<<<<<<< " "${GITHUB_WORKSPACE}"
              then echo "Found merge conflicts"
              exit 1
          fi
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.10'

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 18
          check-latest: true

      - name: Cache pip
        uses: actions/cache@v4
        with:
          path: ~/.cache/pip
          key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml', '**/setup.py', '**/setup.cfg') }}
          restore-keys: |
            ${{ runner.os }}-pip-
            ${{ runner.os }}-

      - name: Get yarn cache directory path
        id: yarn-cache-dir-path
        run: 'echo "::set-output name=dir::$(yarn cache dir)"'

      - uses: actions/cache@v4
        id: yarn-cache
        with:
          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-

      - name: Install
        run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh

      - name: Add to Hosts
        run: |
          echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts

      - name: Expose GitHub Runtime
        uses: crazy-max/ghaction-github-runtime@v3

      - name: Install Playwright browsers
        working-directory: /home/runner/jingrow-bench/apps/jcloude/dashboard
        run: npx playwright install chromium

      - name: Setup Test Users
        working-directory: /home/runner/jingrow-bench/apps/jcloude/dashboard
        run: |
          bench --site test_site execute jcloude.jcloude.pagetype.team.test_team.create_test_jcloude_admin_team \
            --kwargs "{\"email\": \"${JCLOUDE_ADMIN_USER_EMAIL}\", \"free_account\": True, \"skip_onboarding\": True}"
          bench --site test_site set-password "$JCLOUDE_ADMIN_USER_EMAIL" "$JCLOUDE_ADMIN_USER_PASSWORD"

      - name: Run Playwright Tests
        working-directory: /home/runner/jingrow-bench/apps/jcloude/dashboard
        run: npx playwright test --project=chromium

      - name: Generate Coverage Report
        working-directory: /home/runner/jingrow-bench/apps/jcloude/dashboard
        run: npx nyc report --reporter=cobertura --reporter=text --report-dir=./coverage

      - name: Upload Playwright Test report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: /home/runner/jingrow-bench/apps/jcloude/dashboard/playwright-report

      - name: Upload coverage data
        uses: codecov/codecov-action@v5
        with:
          disable_search: true
          files: /home/runner/jingrow-bench/apps/jcloude/dashboard/coverage/cobertura-coverage.xml
          fail_ci_if_error: false
          verbose: true
          token: ${{ secrets.CODECOV_TOKEN }}
          name: jcloude-dashboard
          flags: dashboard

  tests:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        container: [1, 2]

    name: Server

    services:
      mariadb:
        image: mariadb:10.6
        env:
          MYSQL_ROOT_PASSWORD: root
        ports:
          - 3306:3306
        options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3

    steps:
      - name: Remove unnecessary files
        run: |
          sudo rm -rf /usr/share/dotnet
          sudo rm -rf "$AGENT_TOOLSDIRECTORY"

      - name: Clone
        uses: actions/checkout@v4

      - name: Check for valid Python & Merge Conflicts
        run: |
          python -m compileall -q -f "${GITHUB_WORKSPACE}"
          if grep -lr --exclude-dir=node_modules "^<<<<<<< " "${GITHUB_WORKSPACE}"
              then echo "Found merge conflicts"
              exit 1
          fi
      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.10'

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 18
          check-latest: true

      - name: Cache pip
        uses: actions/cache@v4
        with:
          path: ~/.cache/pip
          key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml', '**/setup.py', '**/setup.cfg') }}
          restore-keys: |
            ${{ runner.os }}-pip-
            ${{ runner.os }}-

      - name: Get yarn cache directory path
        id: yarn-cache-dir-path
        run: 'echo "::set-output name=dir::$(yarn cache dir)"'

      - uses: actions/cache@v4
        id: yarn-cache
        with:
          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-

      - name: Install
        run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh

      - name: Add to Hosts
        run: |
          echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts

      - name: Expose GitHub Runtime
        uses: crazy-max/ghaction-github-runtime@v3

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

      - name: Run Tests
        working-directory: /home/runner/jingrow-bench
        run: |
          bench --site test_site set-config allow_tests true
          bench --site test_site run-parallel-tests --app jcloude --with-coverage --total-builds 2 --build-number ${{ matrix.container }}
        env:
          TYPE: server
          COVERAGE_RCFILE: /home/runner/jingrow-bench/apps/jcloude/.coveragerc

      - name: Upload coverage reports to Codecov
        uses: actions/upload-artifact@v4
        with:
          name: coverage-${{ matrix.container }}
          path: /home/runner/jingrow-bench/sites/coverage.xml
        if: always()

      - name: Upload bench start logs
        uses: actions/upload-artifact@v4
        with:
          name: bench-start-logs-${{ matrix.container }}
          path: /home/runner/jingrow-bench/bench_start_logs.txt
        if: always()

  coverage:
    name: Coverage Wrap Up
    if: always()
    needs: tests
    runs-on: ubuntu-latest
    steps:
      - name: Clone
        uses: actions/checkout@v4

      - name: Download artifacts
        uses: actions/download-artifact@v4

      - name: Upload coverage data
        uses: codecov/codecov-action@v4
        with:
          fail_ci_if_error: false
          verbose: true
          token: ${{ secrets.CODECOV_TOKEN }}
