I'm currently building a web application using Laravel 5.4 as my framework and Laravel Forge as my hosting provider, utilising the awesome power of Bitbucket Pipelines as a deployment system. I know, on first read that sounds like a very convoluted workflow, but allow me to explain it.
I'm using PHPUnit and Laravel's in-built testing methods to acheive Test Driven Development (or TDD). TDD is essentially writing what you want your code to look like before you write it, in the form of little code snippets called 'tests'.
You then run PHPUnit, PHPSpec or something similar which runs the code you've written and spits out errors for you. You then let the errors guide you forward in developing that feature. So, I'm using TDD and Bitbucket as my Version Control System.
Bitbucket recently rolled out a new feature called Pipelines which essentially 'builds' your code and runs whatever you want it to run. So for mine, it clones my repository, installs PHP, installs Laravel's dependencies then runs PHPUnit to ensure my tests are all passing (which would signify that my code is working), then hits Laravel Forge's webhook to deploy the code to the staging environment.
This means I no longer have to SSH into my servers and run a git pull, and it also means I don't rely on Forge's (or Envoyers) Auto-Deploy feature and decrease the risk of deploying broken code by 100%. Not bad!
Initially, I accomplished this by using Bitbuckets PHP7.1.1 Pipeline stock configuration (with a few tweaks):
# This is a sample build configuration for PHP. # Check our guides at https://confluence.atlassian.com/x/VYk8Lw for more examples. # Only use spaces to indent your .yml configuration. # ----- # You can specify a custom docker image from Docker Hub as your build environment. image: php:7.1.1 pipelines: default: - step: script: # Modify the commands below to build your repository. - apt-get update && apt-get install -y unzip && apt-get install -y wget #install wget and unzip - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # install composer - composer -V # check composer version - php -r "file_exists('.env') || copy('.env.example', '.env');" # set up laravel's environment - composer install # install composer dependencies - php artisan key:generate # generate a key via artisan - vendor/bin/phpunit # run unit tests - wget -q --spider https://forge.laravel.com/servers/xxxx/sites/yyyy/deploy/http?token=zzz # hit the deployment webhook
This worked so well as pipelines are sequential, so if one step fails it never reaches the deployment webhook, so broken code is never deployed. I did just come up against an error which is actually what prompted me to write this, in case anyone else did come up against it. The error I received was:
1) Tests\Feature\DoSomethingWithImagesTest::test_a_someone_can_add_an_image Error: Call to undefined function Illuminate\Http\Testing\imagepng() ./vendor/laravel/framework/src/Illuminate/Http/Testing/FileFactory.php:46 ./vendor/laravel/framework/src/Illuminate/Support/helpers.php:964 ./vendor/laravel/framework/src/Illuminate/Http/Testing/FileFactory.php:49 ./vendor/laravel/framework/src/Illuminate/Http/Testing/FileFactory.php:31 ./tests/Feature/DoSomethingWithImagesTest.php:55
It turned out that I needed to enable all of the image functions PHP requires inside the docker container which Bitbucket pipelines uses.. Below is the updated bitbucket-pipelines.yml file, in case it proves helpful to anyone else in the future
# This is a sample build configuration for PHP. # Check our guides at https://confluence.atlassian.com/x/VYk8Lw for more examples. # Only use spaces to indent your .yml configuration. # ----- # You can specify a custom docker image from Docker Hub as your build environment. image: php:7.1.1 pipelines: default: - step: script: # Modify the commands below to build your repository. - apt-get update && apt-get install -y unzip wget zlib1g-dev libpcre3-dev libfreetype6-dev libjpeg62-turbo-dev libmcrypt-dev libpng12-dev # get unzip, wget, zlib, freetype, jpeg and png - docker-php-ext-install iconv mcrypt # install above - docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ # configure above - docker-php-ext-install gd #install GD - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # install composer - composer -V # check composer version - php -r "file_exists('.env') || copy('.env.example', '.env');" # set up laravel's environment - composer install # install composer dependencies - php artisan key:generate # generate a key via artisan - vendor/bin/phpunit # run unit tests - wget -q --spider https://forge.laravel.com/servers/xxxx/sites/yyyy/deploy/http?token=zzz # hit the deployment webhook