How to set up Continuous Integration | Laravel & CircleCi
Using Circle CI with Laravel
If you ever wondered How to set up Continuous Integration with Laravel, well, everything starts with a test! Continuous integration (CI) is part of the DevOps approach and it goes together with TDD (Test Driven Development). We need to use a test suit like PHP Unit. Write actual tests before we can start using this

If you ever wondered How to set up Continuous Integration with Laravel, well, everything starts with a test! Continuous integration (CI) is part of the DevOps approach and it goes together with TDD (Test Driven Development). We need to use a test suit like PHP Unit. Write actual tests before we can start using this approach. Otherwise CI it won’t make sense.
There are various platforms that we can use to do CI. One of them, the one that I will be using here is Circleci. But we can use BitBucket, GitLab, Jenkins, Travis, and more.
Continuous Integration| Requirements
We need to take a different approach when we build our applications in order to take advantage of CI. That is known as TDD.
Test-driven development (TDD) is a development technique where you must first write a test that fails before you write new functional code. TDD is being quickly adopted by agile software developers for development of application source code and is even being adopted by Agile DBAs for database development
Agiledata.org
Continuous Integration | Laravel Test-Driven Development
In Laravel, we can use the phpunit test suite to start writing our tests. This is the first step to learn how to set up Continuous Integration using Laravel and
For example, something like that could go in the tests/features/BookmarksTest.php file:
/** @test */ public function guests_cannot_save_bookmarks() { //$this->withoutExceptionHandling(); $user = factory('App\User')->create(); $this->actingAs($user); $attributes = factory('App\Bookmark')->raw(); $this->post('/bookmarks', $attributes); $this->assertDatabaseMissing('bookmarks', $attributes); }
Laravel comes with a built-in set of commands that we can use to speed up development. One of these commands is used to generate tests files.
php artisan make:test BookmarksTest
To see a description of this command we can use the help option
php artisan help make:test
We can run our tests by typing:
vendor/bin/phpunit
If in the terminal, we run the command below, we will store an alias inside our bash_profile file on Linux. This will help us to avoid to type that over and over, and it looks like that:
echo ‘alias test=”vendor/bin/phpunit” >> ./profile_rc’
After that, we can type test in the terminal and our tests will run.
There is a lot more to learn about TDD. But for the purpose of this article that’s enough to get to the point. You can learn more about TDD on Laracasts.
Continuous Integration | Version Control
Once our tests are written and our repository is online we can move forward. See this video if you don’t know how to use git to version control your source code
Continuous Integration | Setting up Circleci
Now we are ready to register a free account on Circleci. You can signup using GitHub or BitBucket, I am using bitbucket because it’s where I host all my repositories. We can then import our project from Bitbucket so that Circleci can do its job. Track commits and triggers a new build, every time running tests to check our code.

We need to create a config file before our build process with Circle ci returns a green light. That means a successfully built and tested application. We need to place a config.yml file inside our project and make some adjustments to make it work. Check the CircleCI PHP documentation for more details.

I made a few adjustments to make the config file work with My Laravel application. My phpunit.xml is configured to use SQLite database in memory. So, I have commented out these two lines from my config file, you can safely remove them:
#- run: touch storage/testing.sqlite #- run: php artisan migrate --env=testing --database=sqlite_testing --force
I have also upgraded the docker image. So that it uses PHP 7.2 instead of the default 7.1. Some of the dependencies of my application required PHP 7.2.
- image: circleci/php:7.2-node-browsers
Laravel uses a .env file to store some configuration details. It is not submitted to the repository in the version control. I have included this command below to make a copy of the .env.example file that is instead stored in the repository
- run: cp .env.example .env
Then we need to generate a new application key. Running our tests using phpunit is the final step, so we add these two more commands
- run: php artisan key:generate - run: ./vendor/bin/phpunit
Finally, our configuration file is ready. We need to create a folder inside the root of our project .circleci and create a file named config.yml.
This is the complete config.yml file. You need to place it in ./circleci/config.yml (Remember to push this file to the online repository to trigger the build process).
version: 2 # use CircleCI 2.0 jobs: # a collection of steps build: # runs not using Workflows must have a `build` job as entry point docker: # run the steps with Docker - image: circleci/php:7.2-node-browsers # ...with this image as the primary container; this is where all `steps` will run working_directory: ~/laravel # directory where steps will run steps: # a set of executable commands - checkout # special step to check out source code to working directory - run: sudo apt install -y libsqlite3-dev zlib1g-dev - run: sudo docker-php-ext-install zip - run: sudo composer self-update - restore_cache: # special step to restore the dependency cache if `composer.lock` does not change keys: - composer-v1-{{ checksum "composer.lock" }} # fallback to using the latest cache if no exact match is found (See https://circleci.com/docs/2.0/caching/) - composer-v1- - run: composer install -n --prefer-dist - save_cache: # special step to save the dependency cache with the `composer.lock` cache key template key: composer-v1-{{ checksum "composer.lock" }} paths: - vendor - restore_cache: # special step to restore the dependency cache if `package-lock.json` does not change keys: - node-v1-{{ checksum "package-lock.json" }} # fallback to using the latest cache if no exact match is found (See https://circleci.com/docs/2.0/caching/) - node-v1- - run: yarn install - save_cache: # special step to save the dependency cache with the `package-lock.json` cache key template key: node-v1-{{ checksum "package-lock.json" }} paths: - node_modules #- run: touch storage/testing.sqlite #- run: php artisan migrate --env=testing --database=sqlite_testing --force - run: cp .env.example .env - run: php artisan key:generate - run: ./vendor/bin/phpunit # See https://circleci.com/docs/2.0/deployment-integrations/ for deploy examples
That was it, you know how to set up Continuous Integration for a Laravel application using Circleci.
If you need any help with a project, these are some of the services that I offer. Find out more here or visit my store.