Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Refringe's avatar

Laravel CI Testing with GitLab

I'd love to set Laravel up on GitLab with CI, however I can not find any tutorials on how to configure the .gitlab-ci.yml file for a basic Laravel 5.2 installation. Does anyone have any experience with this? Currently I'm just on gitlab.com using their shared runners.

0 likes
32 replies
ohffs's avatar

Oddly enough - this is on my todo list (although that's basically infinite...). I think maybe @bashy has poked at this more? :: flutters eyelashes :: ;-)

noeldiaz's avatar

I forget where I found this sample script that someone placed as a Gist, but I have used a variant on this on my steps to start using the CI component of Gitlab (just got manual install migrated to Omnibus last week). So far just doing phpunit tests and it is working wonderfully. But here is the full script I got online:

before_script:
    - composer install --prefer-dist > /dev/null
    - export APP_ENV=testing

unitTesting:
    script:
        - echo "Running PHP Unit tet"
        - php vendor/bin/phpunit --colors --debug --coverage-text
codeSniffer:
    script:
        - php vendor/bin/phpcs --config-set ignore_warnings_on_exit 1
        - php vendor/bin/phpcs --standard=PSR2 --ignore=app/views,app/storage,app/tests,app/filters.php,app/routes.php,packages/,app/Providers/,app/Console/,app/services/,http/Middleware/,app/Exceptions/,app/Events/ -w --colors app/
    allow_failure: true

phpMess:
    script:
        - php vendor/bin/phpmd app/ text cleancode,controversial,codesize,design,naming,unusedcode --exclude=app/views,app/storage,app/tests,app/filters.php,app/routes.php,packages/,app/Providers/,app/Console/,app/services/,http/Middleware/,app/Exceptions/,app/Events/
    allow_failure: true
Refringe's avatar

Hey @noeldiaz, thanks for the reply. Are you sure that's all that's needed for basic unit testing? It's failing for me on the composer install line.

$ composer install --prefer-dist > /dev/null
bash: line 23: composer: command not found

ERROR: Build failed with: exit code 1

Also, will a simple set-up like that get functional testing to work? eg:

$this->visit('/login')->see('Login');
noeldiaz's avatar

Ah, don't forget, if you want your gitlab server to do the CI testing you need to install all the tools for it. I made that mistake at first too.

I installed php, phpunit, composer, phpcs, and phpmd globally.

Now, at minimum all you need is composer because the other tools you can add as dev dependencies on your project composer.json. In fact, laravel already pull down phpunit so you will have that one in:

vendor/bin/phpunit

So just do the global composer install (so it is in somewhere like /usr/local/bin/) and the CI runner should find it and be able to execute for you.

bashy's avatar

This is the script I use for a lot of projects.

before_script:
  - git submodule update --init
  - php -v
  - composer --version
  - git --version
  - ls -lah
  - composer self-update
  - composer config --global github-oauth.github.com $GITHUB_TOKEN
  - composer install --no-interaction
  - php artisan env
  - touch database/testing.sqlite
  - php artisan migrate --database=testing --env=testing

stages:
  - test

test:
  script:
  - vendor/bin/phpunit
  - vendor/bin/phpmd app/ text phpmd.xml
  - vendor/bin/phpcs --standard=psr2 app

I also use this locally to test the build before commiting.

#!/bin/sh

# Run some general commands so we're up-to-date
composer self-update
composer install --no-interaction --optimize-autoloader

# Setup db
touch database/testing.sqlite
echo "" > database/testing.sqlite
php artisan migrate --database=testing --env=testing

# Start tests
vendor/bin/phpmd app/ text phpmd.xml
vendor/bin/phpcbf --standard=psr2 app/
vendor/bin/phpcs --standard=psr2 --colors app/
vendor/bin/phpunit

Got a docker build for Laravel (php7) if you want to use it for the runner: https://hub.docker.com/r/bashy/docker-build/

Source: https://github.com/WithSocial/docker-build

4 likes
Refringe's avatar
Refringe
OP
Best Answer
Level 6

Alright, I wanted to work with the official PHP docker builds, so here's what I ended up doing. It tests using PHP v5.5, v5.6, and v7 with MySQL v5.6 and v5.7; six tests in total. A test takes about 6-7 minutes on average to compile before running. Thanks for the help!

.gitlab-ci.yml:

before_script:
  - bash .gitlab-ci.sh

variables:
  MYSQL_DATABASE: project_name
  MYSQL_ROOT_PASSWORD: secret

phpunit:php5.5:mysql5.6:
  image: php:5.5
  services:
    - mysql:5.6
  script:
    - php vendor/bin/phpunit --colors

phpunit:php5.6:mysql5.6:
  image: php:5.6
  services:
    - mysql:5.6
  script:
    - php vendor/bin/phpunit --colors

phpunit:php7.0:mysql5.6:
  image: php:7.0
  services:
    - mysql:5.6
  script:
    - php vendor/bin/phpunit --colors

phpunit:php5.5:mysql5.7:
  image: php:5.5
  services:
    - mysql:5.7
  script:
    - php vendor/bin/phpunit --colors

phpunit:php5.6:mysql5.7:
  image: php:5.6
  services:
    - mysql:5.7
  script:
    - php vendor/bin/phpunit --colors

phpunit:php7.0:mysql5.7:
  image: php:7.0
  services:
    - mysql:5.7
  script:
    - php vendor/bin/phpunit --colors

.gitlab-ci.sh:

#!/bin/bash

# Install dependencies only for Docker.
[[ ! -e /.dockerinit ]] && exit 0
set -xe

# Update packages and install composer and PHP dependencies.
apt-get update -yqq
apt-get install git libcurl4-gnutls-dev libicu-dev libmcrypt-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libpq-dev libsqlite3-dev libaspell-dev libsnmp-dev libpcre3-dev libtidy-dev -yqq

# Compile PHP, include these extensions.
docker-php-ext-install mbstring mcrypt pdo_mysql curl json intl gd xml zip bz2 opcache

# Install Composer and project dependencies.
curl -sS https://getcomposer.org/installer | php
php composer.phar install

# Copy over testing configuration.
cp .env.testing .env

# Generate an application key. Re-cache.
php artisan key:generate
php artisan config:cache

# Run database migrations.
php artisan migrate

.env.testing:

APP_ENV=testing
APP_DEBUG=true
APP_KEY=key

DB_HOST=mysql
DB_DATABASE=project_name
DB_USERNAME=root
DB_PASSWORD=secret

CACHE_DRIVER=array
SESSION_DRIVER=array
QUEUE_DRIVER=sync
MAIL_DRIVER=log
6 likes
ohffs's avatar

I've been looking into this package (when I say 'looking into' I of course mean 'finding it in my list of browser tabs once in a while and going "oh yeah, I was going to look into that"' ;-)

https://github.com/dockunit/dockunit

Fuxy22's avatar

@Refringe what is the below code for you never posted that file and it prevents the shell script from running

.gitlab-ci.sh:

# Install dependencies only for Docker.
[[ ! -e /.dockerinit ]] && exit 0
set -xe
Refringe's avatar

@Fuxy22 It checks to see if Docker exists. If it doesn't then the script halts. @bashy pointed to an issue that explains that this method stops working with newer versions of Docker. This should work with the new version:

[[ ! -e /.dockerinit ]] && [[ ! -e  /.dockerenv ]] && exit 0

However, I have yet to test it.

lorvent's avatar

currently i am using something like envoyer for live deployments on each commit, can we do same with gitlab ci?

Mythos33's avatar

Hey there, I'm using the config of @Refringe. But I'll get this error:

Checking out ca730a3c as master...
$ bash .gitlab-ci.sh
$ php vendor/bin/phpunit --colors
Could not open input file: vendor/bin/phpunit
ERROR: Build failed: exit code 1

Does anyone know why composer doesn't install the dependencies?

Regards, Stefan

3 likes
bashy's avatar

@Mythos33 What does it say for the composer install command process or does it not show?

gwawr's avatar

This is because the ./vendor folder created during the before_script phase isn't carried through into the testing builds. I've yet to reach a satisfactory answer for this - but its currently looking like you need to do a composer install for each of the different build instances.

https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/issues/336

gwawr's avatar

It's actually something else... the [[ ! -e /.dockerenv ]] && [[ ! -e /.dockerinit ]] && exit 0 line is causing the script to drop out early

Mythos33's avatar

I'm sorry, but I totally forgot about this thread due to missing email notifications. ;-)

@gwawr 's solution works for me, thanks!

gandra404's avatar

I have just tried @Refringe setup and Gitlab build fails with similar error as @Mythos33. I have copied files from https://github.com/didikz/laravel-gitlab-ci into my project and push it into GitLab and build fails with error:

Running with gitlab-ci-multi-runner 1.9.0 (82714ae)
Using Docker executor with image php:5.6 ...
Pulling docker image mysql:5.6 ...
Starting service mysql:5.6 ...
Waiting for services to be up and running...
Pulling docker image php:5.6 ...
Running on runner-e11ae361-project-2277718-concurrent-0 via runner-e11ae361-machine-1483904340-0654037a-digital-ocean-4gb...
Cloning repository...
Cloning into '/builds/gandra404/ticketbeast'...
Checking out bacd084d as master...
$ bash .gitlab-ci.sh
$ php vendor/bin/phpunit --colors
Could not open input file: vendor/bin/phpunit
ERROR: Build failed: exit code 1

Here is repo url of the failing project: https://gitlab.com/gandra404/ticketbeast

and here are failiong builds: https://gitlab.com/gandra404/ticketbeast/pipelines/5717598

In case I made some new changes this is relevant commit: https://gitlab.com/gandra404/ticketbeast/commit/bacd084defd3a718b185c8de89ba7f9cabc1fa9b

@Mythos33, can you post your solution? I didn't get what have to change in order to work.

gandra404's avatar

Finally I manage to run sucesfully tests on GitLab. Here is the project: https://gitlab.com/gandra404/ticketbeast

This article helped me a lot: https://woohuiren.me/blog/how-to-laravel-testing-on-gitlab-ci-with-docker/

I have code on GitLab. Runner installed on my host(probably would work only with shared runner?) with docker as executor.

I have copied this files in my root: https://github.com/GIANTCRAB/gitlabby-dockerish-laravel

The only error I had at first try was "Unable to prepare route [api/user] for serialization. Uses Closure."(https://gitlab.com/gandra404/ticketbeast/builds/8359637) but seems that is known error: https://laracasts.com/discuss/channels/laravel/why-unable-to-prepare-route-for-serialization-uses-closure

So, at the moment I have commented line php artisan route:cache andbuild paased ok!

1 like
scuttlebyte's avatar

These scripts are wonderful, thank you all for sharing your knowledge.

I have everything up and running but being new to the CI and docker/container worlds, I feel compelled to ask if theres any way to expedite the build process by pre-compiling php and extensions and creating a container--something along those lines.

Or is there a benefit to using the official images I'm missing out on?

If it helps, I used forge to provision my production server, so if there's a forge-flavored container I'd be safe running my ci-against that would be swell.

Giolf's avatar

Hi all,

While i was reading this topic

i was thinking if it's possibile to have this kind of test functionality into the docker container:

 public function testBasicExample()
    {
        $this->visit('/')
             ->see('Laravel 5')
             ->dontSee('Rails');
    }

If not what i would need ? maybe a webserver that runs into the docker container ?

thank you

sshamsudheen's avatar

Hi,

I am following the same, however ended up with the permision denied error

$ ./vendor/bin/phpunit /bin/sh: eval: line 64: ./vendor/bin/phpunit: Permission denied ERROR: Job failed: exit code 2

I am using the image, image: zaherg/php-7.1-xdebug-alpine:latest

Also i am unable to run the command as sudo as well.

Can someone help on this.. thanks

davidnn's avatar

change

vendor/bin/phpunit to 

to

php ./vendor/phpunit/phpunit/phpunit

molerat's avatar

Cool. Thanks for all this great work. I am stuck in the database connection establishment.

What credentials should I actually put in? I mean, at that point, it doesn't even know my live servers IP, I don't feel comfortable putting the live credentials there and it will probably not have access anyway.

This is the error message:

Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover

   Illuminate\Database\QueryException  : SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = forge and table_name = settings)

  at /builds/securitas-fra/qs-tool/vendor/laravel/framework/src/Illuminate/Database/Connection.php: 664
  660:         // If an exception occurs when attempting to run a query, we'll format the error
  661:         // message to include the bindings with SQL, which will make this exception a
  662:         // lot more helpful to the developer instead of just the database's errors.
  663:         catch (Exception $e) {
  664:             throw new QueryException(
  665:                 $query, $this->prepareBindings($bindings), $e
  666:             );
  667:         }
  668: 
  669:         return $result;

  Exception trace:

  1   Illuminate\Foundation\Application::Illuminate\Foundation\{closure}(Object(App\Providers\SettingsServiceProvider))
      [internal] : 0

  2   PDOException::("SQLSTATE[HY000] [2002] Connection refused")
      /builds/securitas-fra/qs-tool/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php : 68

  Please use the argument -v to see more details.

I am new to this whole topic with CI / CD and docker so forgive me :)

Next

Please or to participate in this conversation.