phplaravelmariadbgitlab-ci

Example .gitlab-ci.yml for Laravel 12 with MariaDB that seeds database before running php artisan test


I'm setting up a GitLab Runner for a Laravel 12 project and I want my CI pipeline to do the following:

  1. Spin up a MariaDB service for the tests
  2. Run php artisan migrate:fresh --seed to seed the database
  3. Finally run php artisan test

I’ve already registered my runner and can run jobs, but I’m not sure how to correctly structure the .gitlab-ci.yml file so that the database is available and seeded before the tests execute. I wasted a lot of hours for this.

Question: Does anyone have a working example of a .gitlab-ci.yml file that only runs php artisan test for a Laravel 12 app with MariaDB, ensuring the database is seeded first with php artisan migrate:fresh --seed?


Solution

  • Most of the public .gitlab-ci.yml examples for Laravel floating around don’t actually work out of the box. They either miss required PHP extensions, don’t wait for the database to be ready, or assume you’re running npm builds even if your project doesn’t need them. That’s why I wasted hours trying to adapt them.

    The file below is a working example for a Laravel 12 Breeze project with MariaDB. It does exactly what I asked: spins up a MariaDB service, installs the PHP extensions Laravel needs, seeds the database with php artisan migrate:fresh --seed, and finally runs the test suite with php artisan test.

    Notice there’s no npm step here. That’s intentional: if you’re using Laravel Breeze with Blade templates and no frontend build tooling, you don’t need Node.js or npm in CI. Keeping it out makes the pipeline faster and simpler.

    Here’s the full config which worked for me and is copy‑paste ready:

    image: php:8.3
    
    services:
      - name: mariadb:11.8.5
        alias: mariadb
    
    variables:
      DB_HOST: mariadb
      DB_DATABASE: dbname
      DB_USERNAME: username
      DB_PASSWORD: Password-12jcdm4.95mv?2nv%ancJuP #not a real one
      APP_URL: http://127.0.0.1:8000
    
    before_script:
      # Update packages
      - apt-get update -yqq
      # Install dependencies
      - apt-get install libonig-dev libicu-dev libzip-dev zlib1g-dev libjpeg-dev libpng-dev libfreetype6-dev libxml2-dev -yqq
      # Install php extensions
      - docker-php-ext-install mbstring pdo_mysql intl gd bcmath
      # Install Composer and project dependencies.
      - curl -sS https://getcomposer.org/installer | php
      - php composer.phar install --no-interaction --prefer-dist --optimize-autoloader --no-progress --quiet
      - cp .env.example .env
      # Generate an application key. Re-cache.
      - php artisan key:generate
      - php artisan config:cache
      # Run database migrations.
      - php artisan migrate
      # Run database seed if needed, in my case it's not
      #- php artisan db:seed
    
    test:
      script:
        # php artisan serve is usefull in this case because the feature tests relay on actuall HTTP responses
        - nohup php artisan serve --host=0.0.0.0 --port=8000 > storage/logs/server.log 2>&1 &
        - sleep 5 # give server time to boot
        # run laravel tests
        - php artisan test --env=testing
    

    Another way to make the pipeline faster is to pre‑build a custom Docker image with all the PHP extensions and system libraries baked in. Right now, every CI job spends time running apt-get install and docker-php-ext-install. That adds 1–2 minutes to every run.