How to test and auto deploy your laravel code from Gitlab

Few days ago, I was playing with the new Laravel 5.4 and Gitlab CI, and got to the point where I wanted the CI to test my code once I push it.

Using google lead me to this post on Laracasts, and it was the starting point for me, there you can get important files .gitlab-ci.yml and .gitlab-ci.sh  , basically the first one will define the stages for the testing and the second one will build the environment for your test.

So lets look at a short version of .gitlab-ci.yml

Looking at the file we can figure out that the before_script will run .gitlab-ci.sh file before any tests and variables define the variables for mysql and the other two is stages for executing the tests on two different php images (you can check Laracasts post which have the full version of the file as they also test it on php 5.x).

But what is image and services ? basically they are docker images which the CI is going to pull for you and link them together so you can execute your tests, nice right :D, lastly script is the command that you want to execute inside your test image.

With those basics information, you have got a full testing CI environment for your Laravel application, which will be triggered whenever you pushed your code.

What about the auto deploy how we can do that? in Gitlab they have some integration with Docker and kubernetes which you can look at Gitlab documentations, but for me I use simple SSH methods which is nice and simple.

Lets talk about what we should do step by step:

Create Secret Variables:

GitLab CI allows you to define per-project secret variables that are set in the build environment. Those variables stored outside the repository and used within your CI so you dont need to add them as plain text. You can add your secret variables from within your repository Settings -> CI/CD Pipeline, once you are there you can define your secrets like the following images

Once you created them, you can use them in your .gitlab-ci.yml file.

You will need to create two secret variables, one for the SSH and the second for Github Access Token which we will be using for PHP Composer.

[Optional] Create your own Docker image:

For me, I try to use any opportunity to learn the things I want to learn, and since the GitlabCI depends on Docker, so why dont I use my Docker knowledge to do something nice, plus am using Docker with PHPStorm so I wanted to use the same Docker image for both the CI and my development environment. The image am going to use is PHP7.1 with xDebug which I built and published on my Docker Hub.

Create your own .gitlab-ci.yml file:

Our gitlab-ci instruction file will contain mainly four parts:

  1. before_script: In this section we will define the commands which we want to use on each and every stage, before anything else within the stage scripts section.
  2. stages: In this section we will define the order which our system is going to work (Jobs from the same stage will run in parallel).
  3. Testing stage: In this section we tell the CI what we want to execute and which Docker image it should pull.
  4. Deploy Stage: In this section we just define the second job that we want the CI to execute.

So it will looks like the following:

Lets explain it section by section:

First we need to make sure that we are running inside docker, if not then exit immediately.

Second we defined the two stages we want to work with, and add a Docker variables which will be used with MySQL docker image.

Third we define the testing stage for our Laravel code base, we first make sure to say that this job belongs to the phpunit stage, now since I need to test my code when I push it to develop branch only I specified that on my only section,  then we specify which PHP docker image we want to use, as I said before I use my own images, we specify the service which is linked to our code which is mysql and finally we specify the commands we want to execute in the script section.

I just grouped all the commands inside .gitlab-ci.sh file which will do everything for me :

  1. configure composer and run it
  2. copy my testing env file to be the main one
  3. run migration and seeds
  4. and finally run phpunit

As you can see I used the first secret variable out of the two we said we will define GitHubKey.

Now whenever I push to develop branch, I got the CI to test my code and if it fail I’ll get something like this

Which is really really nice thing.

Now we are going to be on our last stage, Auto deploy if the test went green.

its really simple, if you read it you will notice that its not different than the previous stage except that we dont pull any Docker image, we only SSH into the remove server and pull the code from gitlab.

Information! Make sure that the Private SSH key that you have added to your secret variables, can access your remote server.
First we define that this job belongs to the deploy stage, then we overwrite the before_script so it will execute the one we define instead of the global on, basically this is what I did :

  1. Make sure that I create the ~/.ssh  folder with in Gitlab Docker image, cause at the end everything run inside a container.
  2. I use the second secret key that we have defined which will contain my the private key to access the remote server.
  3. Make sure that the file is not fully open, SSH will complain if the file is not set as 600 mode.
  4. Check if we are running inside docker and then disabled StrictHostKeyChecking for all the hosts inside ~/.ssh/config

Information! Make sure that you either pulled your code once on the remote server to add gitlab servers to your know_hosts files, if the remote origin was not originally from gitlab
The environment section will define your environments variable which you will see within your Environment section under the Pipelines section

You are free to create this manually or once you set them inside your gitlab-ci.yml file they will be auto created for you.

Now if you clicked on develop you will see how many times you have sent your code to the server, and even you can rollback to older version of your code

and now whenever you pushed to develop your code will be tested and auto deploy without any manual interaction from your side.

And thats all, let me know if you have anything else that you can add to enhance my post.

 

Alert! As always, you may find some lingual mistakes in my post, as english is not my mother language, so if you do and want to help me out, just let me know so I can fix it.
Filed under: Business, Code, docker, Laravel, Linux, MySQL, PHP

12 Comments

  1. Is it possible to implement this Zero downtime in the deploy stage, that way it can be tested and zero downtime autodeploy

    • yes its some how simple to do that, in the script section on your deployment you can just create a new bash file and add whatever commands you like (like what we have done in the script section in phpunit stage), instead of having them listed in the script section.

      so instead of just having to pull the code, you will have bash script like this one https://gist.github.com/linuxjuggler/e1492188a82847601f9d17748db80a4c the same from the article you mentioned, and just execute it.

  2. Hi Zaher,

    I’m new to GitLab and Laravel. I’ve setup a GitLab on a private server. I’ve locally deployed a laravel 5.4 install and coded some tests using phpunit. My laravel app runs on a vagrant homestead VM. As I would like to have a TDD and some CI, I started to google and found the same thread as you on Laracast. Then I found you article.

    I added to my project .gitlab-ci.yml and .gitlab-ci.sh, made some changes in the .yml. Then I committed the files to my local git rep and then I pushed them to my GitLab server. A pipeline automatically starts and get “stuck” as soon as it starts. I don’t know how to check what’s wrong as their is no error or log.

    I would really appreciate some help.

    Many thanks for your help and anwser.

    • Hello Vincent,
      in my article I didnt explain how to setup gitlab and I have assumed that you are using the hosted one, so mostly your problem related to how you configured Gitlab, the Pipeline will not work if you dont have a CI Runner installed somewhere to run the tests for you, then do the push. So I advice you to have a look at the documentation and make sure that you have configured your Gitlab instance correctly.

      • Thanks for you answer Zaher.

        I do have a GitLab hosted running but you’re right I should have spend more time on the documentation.

        Thanks for your time.

        • You are most welcome Vincent, we are all here to help each other.

          but remember to share your solution with us, so we all (including me) benefit from it.

          Thanks again.

  3. From gitlab worker:
    Pulling docker image zaherg/php-7.1-xdebug-alpine:latest ...
    after 13 minutes is still pulling …
    how is that possible ?!?

      • if i would like to install ‘apt’ in the order to run install some extra package … how can i do that ?
        thanks

        • the Docker image which you are pulling ( zaherg/php-7.1-xdebug-alpine:latest ) depends on alpine linux (https://alpinelinux.org/) not ubuntu .
          but you didnt specify where you want to install those extra packages, while testing or in your production server ? if you want to install them in the testing stage, you can edit the .gitlab-ci.sh file and install those to it.

          • The problem is that im trying to run laravel/dusk ‘tests’ in the gitlab CI.
            So i need several packages to do that. I found a docker image that should have all the dep i need :)

          • Am not sure if laravel/dusk will work with gitlab CI, as I didnt try it, but if it worked with you lets us know, so we can dig deep with it :D


Add a Comment

Your email address will not be published. Required fields are marked *

Comment *

Name *
Email *
Website

15 − thirteen =