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.
This commit is contained in:
Paulo Castellano 2026-07-04 10:14:01 -03:00
parent ef81ea74a8
commit 2d72d74cc8
2 changed files with 135 additions and 56 deletions

View file

@ -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

View file

@ -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