Skip to content
Latchkey

CI/CD for Symfony with GitHub Actions

Lint, static-analyze, and test your Symfony app against a real database in CI.

Symfony apps test best against a real database, so the workflow spins up a Postgres service container. This recipe installs PHP and Composer, runs PHPUnit and PHPStan, and prepares the app for deploy.

What the pipeline does

  • start a Postgres service container
  • install PHP with setup-php
  • install deps with composer install
  • run PHPStan static analysis
  • run PHPUnit against the database

The workflow

shivammathur/setup-php installs PHP with the needed extensions. The DATABASE_URL points PHPUnit at the service container.

.github/workflows/ci.yml
name: CI
on:
  push:
    branches: [main]
  pull_request:
jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_PASSWORD: postgres
        ports: ['5432:5432']
        options: >-
          --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
    env:
      DATABASE_URL: postgresql://postgres:postgres@127.0.0.1:5432/app?serverVersion=16
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: pdo_pgsql, intl
          coverage: none
      - run: composer install --no-interaction --prefer-dist
      - run: vendor/bin/phpstan analyse
      - run: php bin/console doctrine:migrations:migrate --no-interaction
      - run: vendor/bin/phpunit

Caching and speed

Cache the Composer cache directory with actions/cache keyed on composer.lock so installs are fast. Symfony test suites that boot the kernel per test are the slow part; cheaper managed runners such as Latchkey (around 69% cheaper than GitHub-hosted) keep the suite quick and auto-retry transient database-startup flakes.

Deploying

Deploy by syncing the app to a PHP-FPM host (rsync over SSH, or Deployer), then running composer install --no-dev --optimize-autoloader and the migrations on the server. Containerized deploys build a php-fpm image and push it to ECS, Cloud Run, or a Kubernetes cluster.

Key takeaways

  • Use a Postgres service container to test against a real DB.
  • Cache the Composer cache directory for fast installs.
  • Run migrations before the test suite.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →