name: E2E Tests

on:
  schedule:
    - cron: "15 5 * * *" # Every day at 5:15 am
  workflow_dispatch:

env:
  AULA_PORT: "80"
  PLAYWRIGHT_VERSION: "1.58.2"

jobs:
  sanitize_project_name:
    runs-on: [self-hosted, cicd]
    steps:
      - id: sanitize
        name: Substitute illegal branch characters
        run: |
          echo "${{ github.ref_name }}" | \
            sed 's/[^a-zA-Z0-9_.-]/_/g' | \
            (echo -n "DOCKER_COMPOSE_PROJECT_NAME=aula-e2e-" && cat) \
          >> $GITHUB_OUTPUT
    outputs:
      DOCKER_COMPOSE_PROJECT_NAME: ${{ steps.sanitize.outputs.DOCKER_COMPOSE_PROJECT_NAME }}
  run-aula:
    needs: sanitize_project_name
    runs-on: [self-hosted, cicd]
    permissions:
      contents: read
      packages: read
    env:
      AULA_IMAGE: ghcr.io/aula-app/ansible-role-aula:latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Setup docker
        uses: docker/setup-buildx-action@v4

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v4
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Pull Ansible image
        run: |
          docker pull ${{ env.AULA_IMAGE }}

      - name: Create Ansible playbook
        run: |
          cat <<- 'EOF' > playbook.yml
          - name: Install aula backend locally for E2E testing
            hosts: localhost
            become_method: su
            become_user: root
            roles:
              - aula
          EOF

      - name: Create inventory file
        run: |
          cat <<- 'EOF' > inventory.yml
          ---
          all:
            hosts:
              localhost:
                ansible_connection: local
                ansible_python_interpreter: /usr/local/bin/python3
                ansible_user: ansible
                apache2_user: www
                network:
                  ssl_enabled: false
                  base_domain: "nginx"
                  bindInterface: "127.0.0.1"
                  httpPort: "${{ env.AULA_PORT }}"
                email:
                  backend: log
                  relay:
                    smtp: ""
                    port: ""
                    username: ""
                    password: ""
                aula:
                  compose_name: ${{ needs.sanitize_project_name.outputs.DOCKER_COMPOSE_PROJECT_NAME }}
                  debug: true
                  log:
                    level: INFO
                    stack: single
                  environment: dev
                  base_url: "http://nginx:${{ env. AULA_PORT }}"
                  superkey: "hunter2"
                  is_pr_deployment_enabled: false
                  multi_instance_enabled: false
                  db:
                    name: "aula_dbname"
                    user: "aula_user"
                    pass: "hunter2"
                    root_password: "hunter2"
                  email:
                    from: admin@aula.local
                    support: support@aula.local
                  report:
                      statistics:
                        recipients: ""
                        schedule: "0 2 1 * *"
                  manager:
                    db:
                      name: "aula_manager"
                      user: "aula_manager_user"
                      pass: "hunter2"
                  backup:
                    enabled: false
                auth0:
                  domain: "AUTH0-DOMAIN"
                  client_id: "AUTH0-CLIENT-ID"
                  client_secret: auth0-secret
                  cookie_secret: hunter2
                  redirect_uri: "http://nginx:${{ env. AULA_PORT }}/api/controllers/auth0.php"
                  frontend_redirect: "http://nginx:${{ env. AULA_PORT }}/oauth-login/"
          EOF

      - name: Run ansible
        run: |
          docker run --rm \
            -v /var/run/docker.sock:/var/run/docker.sock \
            -v /opt/aula:/opt/aula \
            -v "$(pwd)/playbook.yml":/usr/local/share/aula/ansible/playbook.yml \
            -v "$(pwd)/inventory.yml":/usr/local/share/aula/ansible/inventory.yml \
            ${{ env.AULA_IMAGE }} ansible-playbook playbook.yml -i inventory.yml

  e2e-tests:
    runs-on: [self-hosted, cicd]
    continue-on-error: true # allow failing e2e tests while testing
    needs: [run-aula, sanitize_project_name]
    env:
      PLAYWRIGHT_SERVICE_NAME: playwright-svc-${{ github.sha }}
    steps:
      # Playwright can't be started using the 'service' feature of actions as the
      # server needs to be run manually in the container and actions doesn't support
      # this for 'service's.
      - name: Start playwright image
        run: |
          docker run --rm \
            --name ${{ env.PLAYWRIGHT_SERVICE_NAME }} \
            --network ${{ needs.sanitize_project_name.outputs.DOCKER_COMPOSE_PROJECT_NAME }}_aula_external \
            -p 127.0.0.1:3000:3000 \
            --detach \
            mcr.microsoft.com/playwright:v${{ env.PLAYWRIGHT_VERSION }} \
            /bin/sh -c "npx -y playwright@${{ env.PLAYWRIGHT_VERSION }} run-server --port 3000 --host 0.0.0.0"

      - name: Set up Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 22

      - name: Install yarn
        run: corepack install --global yarn

      - name: Install dependencies
        run: yarn install --frozen-lockfile

      - name: Run E2E tests
        env:
          PW_TEST_CONNECT_WS_ENDPOINT: ws://127.0.0.1:3000/
          APP_FRONTEND_HOST: http://nginx:${{ env. AULA_PORT }}
          APP_BACKEND_HOST: http://nginx:${{ env. AULA_PORT }}
          REMOTE_BROWSER: 1 # Enable the use of playwright server in the js
          ADMIN_USERNAME: "admin"
          ADMIN_PASSWORD: "abc123"
        run: yarn playwright test --reporter=github

      - name: Stop playwright service
        if: ${{ always() }}
        run: |
          docker rm -f ${{ env.PLAYWRIGHT_SERVICE_NAME }}

  cleanup:
    runs-on: [self-hosted, cicd]
    needs: [run-aula, e2e-tests]
    # Run cleanup job regardless of previous jobs state
    if: ${{ always() }}
    steps:
      - name: Cleanup running services and files
        run: |
          for name in $(docker ps --format '{{ .Names }}'); do
            if [[ "$name" == ${{ env.DOCKER_COMPOSE_PROJECT_NAME }}* ]]; then
              echo "Removing: $name"
              docker rm -f "$name"
            fi
          done
          docker ps -a
