name: laravel

on:
  push:
    branches: [main]
  pull_request:

jobs:
  code_lint:
    runs-on: ubuntu-latest
    name: Run code linters

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

      - name: Get Composer cache directory
        id: composer-cache
        run: |
          echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

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

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: 8.2
          extensions: dom, curl, mbstring, pdo, sqlite, pdo_sqlite
          tools: composer:v2
          coverage: none

      - name: Prepare the environment
        working-directory: ./api
        run: cp .env.example .env

      - name: Install composer dependencies
        working-directory: ./api
        run: composer install --prefer-dist --no-interaction --no-progress --ignore-platform-reqs --optimize-autoloader

      - name: Directory permissions
        working-directory: ./api
        run: chmod -R 777 storage bootstrap/cache

      - name: Run PHP lint check
        working-directory: ./api
        run: ./vendor/bin/pint --test

  client_lint:
    runs-on: ubuntu-latest
    name: Run client linters
    defaults:
      run:
        working-directory: ./client

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

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Install npm dependencies
        run: npm ci --no-audit --no-progress --silent

      - name: Run ESLint
        run: npm run lint

  tests:
    runs-on: ubuntu-latest

    services:
      postgres:
        # Docker Hub image
        image: postgres:14
        # Provide the password for postgres
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_USER: postgres
          POSTGRES_DB: postgres
        # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          # Maps tcp port 5432 on service container to the host
          - 5432:5432
      mysql:
        # Docker Hub image
        image: mysql:8
        # Provide the password for mysql
        env:
          MYSQL_ROOT_PASSWORD: test
          MYSQL_DATABASE: test
          MYSQL_USER: test
          MYSQL_PASSWORD: test
        # Set health checks to wait until mysql has started
        options: >-
          --health-cmd="mysqladmin ping"
          --health-interval=10s
          --health-timeout=5s
          --health-retries=5
        ports:
          # Maps tcp port 3306 on service container to the host
          - 3306:3306

    strategy:
      fail-fast: true
      matrix:
        php: [8.2]
        connection: [pgsql, mysql]
        include:
          - connection: pgsql
            host: localhost
            port: 5432
            user: postgres
            password: postgres
            database: postgres
          - connection: mysql
            host: "127.0.0.1"
            port: 3306
            user: root
            password: test
            database: test

    name: Run Feature & Unit tests (PHP ${{ matrix.php }} - ${{ matrix.connection }})

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

      - name: Get Composer cache directory
        id: composer-cache
        run: |
          echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

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

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php }}
          extensions: dom, curl, mbstring, pdo, sqlite, pdo_sqlite
          tools: composer:v2
          coverage: none

      - name: Prepare the environment
        run: cp api/.env.example api/.env

      - name: Install composer dependencies
        working-directory: ./api
        run: composer install --prefer-dist --no-interaction --no-progress --ignore-platform-reqs --optimize-autoloader

      - name: Directory permissions
        working-directory: ./api
        run: chmod -R 777 storage bootstrap/cache

      - name: Run tests (Unit and Feature)
        working-directory: ./api
        run: ./vendor/bin/pest -p
        env:
          DB_CONNECTION: ${{ matrix.connection }}
          DB_HOST: ${{ matrix.host }}
          DB_PORT: ${{ matrix.port }}
          DB_DATABASE: ${{ matrix.database }}
          DB_USERNAME: ${{ matrix.user }}
          DB_PASSWORD: ${{ matrix.password }}

      - name: "Archive log results"
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: log-results-${{ matrix.connection }}
          path: api/storage/logs/laravel.log
          retention-days: 3

  build-nuxt-app:
    runs-on: ubuntu-latest
    name: Build the Nuxt app
    defaults:
      run:
        working-directory: ./client
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Prepare the environment
        run: cp .env.example .env

      - name: Install npm dependencies
        run: npm ci --no-audit --no-progress --silent

      - name: Build client
        run: npm run build
        env:
          SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}

  production-deploy:
    needs: [code_lint, client_lint, tests, build-nuxt-app]
    if: success() && github.ref == 'refs/heads/main' && github.event_name == 'push'
    runs-on: ubuntu-latest
    name: Triggers Deployment (Vapor & Amplify)

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

      - name: Get Composer cache directory
        id: composer-cache
        run: |
          echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

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

      - uses: actions/cache@v4
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: 8.2
          extensions: dom, curl, mbstring, pdo, sqlite, pdo_sqlite
          tools: composer:v2
          coverage: none

      - name: Prepare the environment
        working-directory: ./api
        run: cp .env.example .env

      - name: Install composer dependencies
        working-directory: ./api
        run: composer install --prefer-dist --no-interaction --no-progress --ignore-platform-reqs --optimize-autoloader

      - name: Directory permissions
        working-directory: ./api
        run: chmod -R 777 storage bootstrap/cache

      - name: Trigger front-end deployment
        run: |
          URL="${{ secrets.AMPLIFY_DEPLOY_URL }}"
          curl -X POST -d {} "$URL" -H "Content-Type: application/json"

      - name: Created encrypted .env file before deployment
        working-directory: ./api
        run: |
          echo "${{ secrets.ENCRYPTED_ENV_FILE }}" >> .env.production.encrypted

      - name: Deploy back-end to production
        working-directory: ./api
        run: php vendor/bin/vapor deploy api-production --commit="${GITHUB_SHA}" --message="${GITHUB_REF}"
        env:
          VAPOR_API_TOKEN: ${{ secrets.VAPOR_API_TOKEN }}
