From 2d72d74cc8e69571db701eb3351df26e10aea919 Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Sat, 4 Jul 2026 10:14:01 -0300 Subject: [PATCH] Split CI into parallel backend and e2e jobs Extract the shared PHP/Composer/Node/database/Passport setup into a composite action, and run the backend suite (Unit + Feature) and the frontend/e2e suite (Vitest + Playwright browser tests) as two parallel jobs. This isolates the flaky browser suite so it can be rerun on its own, surfaces failures by area, gives the growing e2e suite room to shard, and uploads Playwright artifacts on failure. --- .github/actions/setup-laravel/action.yml | 65 ++++++++++++ .github/workflows/tests.yml | 126 +++++++++++++---------- 2 files changed, 135 insertions(+), 56 deletions(-) create mode 100644 .github/actions/setup-laravel/action.yml diff --git a/.github/actions/setup-laravel/action.yml b/.github/actions/setup-laravel/action.yml new file mode 100644 index 00000000..c40a2d07 --- /dev/null +++ b/.github/actions/setup-laravel/action.yml @@ -0,0 +1,65 @@ +name: 'Setup Laravel test environment' +description: 'Set up PHP, Composer, optional Node, the app key, database, and Passport keys for a test job.' + +inputs: + node: + description: 'Also set up Node.js and install npm dependencies.' + default: 'false' + db-port: + description: 'Host port mapped to the Postgres service.' + required: true + redis-port: + description: 'Host port mapped to the Redis service.' + required: true + +runs: + using: 'composite' + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.4' + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_pgsql, bcmath, intl, gd, redis + coverage: none + + - name: Setup Node.js + if: inputs.node == 'true' + uses: actions/setup-node@v4 + with: + node-version: '22' + cache: 'npm' + + - name: Cache Composer dependencies + uses: actions/cache@v4 + with: + path: vendor + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Prepare environment + shell: bash + run: cp .env.ci .env + + - name: Install Composer dependencies + shell: bash + run: composer install --no-interaction --prefer-dist --optimize-autoloader + + - name: Install npm dependencies + if: inputs.node == 'true' + shell: bash + run: npm ci + + - name: Generate application key + shell: bash + run: php artisan key:generate + + - name: Run migrations + shell: bash + env: + DB_PORT: ${{ inputs.db-port }} + REDIS_PORT: ${{ inputs.redis-port }} + run: php artisan migrate --force + + - name: Generate Passport keys + shell: bash + run: php artisan passport:keys --force diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1f693d79..4a655c4b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -6,18 +6,19 @@ on: pull_request: branches: [main, develop] +env: + DB_CONNECTION: pgsql + DB_DATABASE: trypost_test + DB_USERNAME: postgres + DB_PASSWORD: password + BROADCAST_CONNECTION: "null" + CACHE_STORE: array + QUEUE_CONNECTION: sync + SESSION_DRIVER: array + jobs: - tests: + backend: runs-on: ubuntu-latest - env: - DB_CONNECTION: pgsql - DB_DATABASE: trypost_test - DB_USERNAME: postgres - DB_PASSWORD: password - BROADCAST_CONNECTION: "null" - CACHE_STORE: array - QUEUE_CONNECTION: sync - SESSION_DRIVER: array services: postgres: @@ -48,64 +49,77 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Setup PHP - uses: shivammathur/setup-php@v2 + - name: Setup test environment + uses: ./.github/actions/setup-laravel with: - php-version: '8.4' - extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_pgsql, bcmath, intl, gd, redis - coverage: none + db-port: ${{ job.services.postgres.ports['5432'] }} + redis-port: ${{ job.services.redis.ports['6379'] }} - - name: Setup Node.js - uses: actions/setup-node@v4 + - name: Run backend tests + env: + DB_PORT: ${{ job.services.postgres.ports['5432'] }} + REDIS_PORT: ${{ job.services.redis.ports['6379'] }} + run: php artisan test --compact --parallel + + e2e: + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:16 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password + POSTGRES_DB: trypost_test + ports: + - 5432/tcp + options: >- + --health-cmd="pg_isready" + --health-interval=10s + --health-timeout=5s + --health-retries=3 + + redis: + image: redis:7 + ports: + - 6379/tcp + options: >- + --health-cmd="redis-cli ping" + --health-interval=10s + --health-timeout=5s + --health-retries=3 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup test environment + uses: ./.github/actions/setup-laravel with: - node-version: '22' - cache: 'npm' - - - name: Cache Composer dependencies - uses: actions/cache@v4 - with: - path: vendor - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Prepare environment - run: cp .env.ci .env - - - name: Install Composer dependencies - run: composer install --no-interaction --prefer-dist --optimize-autoloader - - - name: Install npm dependencies - run: npm ci - - - name: Generate application key - run: php artisan key:generate - - - name: Build assets - run: npm run build + node: 'true' + db-port: ${{ job.services.postgres.ports['5432'] }} + redis-port: ${{ job.services.redis.ports['6379'] }} - name: Run frontend unit tests run: npm run test:unit - - name: Run migrations - run: php artisan migrate --force - env: - DB_PORT: ${{ job.services.postgres.ports['5432'] }} - REDIS_PORT: ${{ job.services.redis.ports['6379'] }} - - - name: Generate Passport keys - run: php artisan passport:keys --force - - - name: Run tests - run: php artisan test --compact --parallel - env: - DB_PORT: ${{ job.services.postgres.ports['5432'] }} - REDIS_PORT: ${{ job.services.redis.ports['6379'] }} + - name: Build assets + run: npm run build - name: Install Playwright browsers run: npx playwright install --with-deps chromium - name: Run browser tests - run: php artisan test tests/Browser --compact env: DB_PORT: ${{ job.services.postgres.ports['5432'] }} REDIS_PORT: ${{ job.services.redis.ports['6379'] }} + run: php artisan test tests/Browser --compact + + - name: Upload Playwright artifacts + if: failure() + uses: actions/upload-artifact@v4 + with: + name: playwright-artifacts + path: tests/Browser/Screenshots + if-no-files-found: ignore + retention-days: 7