Laravel App CI/CD using GitHub Actions
This article is also published on https://engineering.wedevs.com/2020/05/04/laravel-app-ci-cd-using-github-actions/
Continuous integration becomes mandatory when every second of your application uptime is important. By using Continuous Integration (CI) we can test our codes are working or not through PHPUnit. When all of your tests are pass then you need to deploy the application.
Why GitHub Actions?
If your project is in GitHub then it is a great opportunity to use GitHub Actions. GitHub Actions is only for GitHub repositories. Another advantage of GitHub Actions is, it is much easier to set up than Jenkins and Travis CI
Continuous Integration
Let’s start with continuous integration, to do so first go to your GitHub repository and click on Actions
menu, you will see something like the below image.
You will see GitHub will suggest a few workflow
for you, In GitHub Actions, workflow is a YAML file where you can define each step of your integration. Let’s start with the suggested Laravel workflow. When we click on the Set up this workflow
button it will open an editor with laravel.yml
file in .github/workflows
directory. Here I modify this file a little bit and rename the file to CI.yml
, My file is given below.
name: Continuous Integration
on:
push:
branches:
- master
- develop
- 'feature/**'
defaults:
run:
shell: bash
jobs:
laravel-tests:
runs-on: ubuntu-18.04
env:
DB_CONNECTION: sqlite
DB_DATABASE: database/database.sqlite
steps:
- uses: actions/checkout@v2
- name: Copy .env
run: php -r "file_exists('.env') || copy('.env.example', '.env');"
- name: Create sqlite database
run: touch database/database.sqlite
- name: Install dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
- name: Generate key
run: php artisan key:generate
- name: Set directory permissions
run: chmod -R 777 storage bootstrap/cache
- name: Execute tests (Unit and Feature tests) via PHPUnit
run: vendor/bin/phpunit
After your modification of the file you have to commit this file via Start commit
button. If your are not understand what is this YAML file talking about, you may read the documentation of GitHub Actions workflow file. When you commit your configuration file the integration is done. From now your Laravel application will test automatically on every push of master
, develop
and feature
branches.
Continuous Deployment
The concept is if we push to master branch we will run a new job in the workflow. On the job first we will check all tests are pass or not. If all tests are pass then we will send request to a webhook URL. Here you have to manage the webhook by your own or you may read my article about Add Webhook on Ubuntu. Mainly when the webhook receive the request it run a shell script where it pull the codes from repository and install composer packages on server, also it can run other necessary commands. Our final CI.yml
file will be look like below.
name: Continuous Integration
on:
push:
branches:
- master
- develop
- 'feature/**'
defaults:
run:
shell: bash
jobs:
laravel-tests:
runs-on: ubuntu-18.04
env:
DB_CONNECTION: sqlite
DB_DATABASE: database/database.sqlite
steps:
- uses: actions/checkout@v2
- name: Copy .env
run: php -r "file_exists('.env') || copy('.env.example', '.env');"
- name: Create sqlite database
run: touch database/database.sqlite
- name: Install dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
- name: Generate key
run: php artisan key:generate
- name: Set directory permissions
run: chmod -R 777 storage bootstrap/cache
- name: Execute tests (Unit and Feature tests) via PHPUnit
run: vendor/bin/phpunit
deloy:
if: ${{ github.ref == 'refs/heads/master' }}
runs-on: ubuntu-18.04
needs: laravel-tests
steps:
- name: Call server webhook
run: |
status_code=$(curl -d ${{ secrets.WEBHOOK_DATA }} --silent --show-error --write-out '%{http_code}' --output "/tmp/response.txt" ${{ secrets.WEBHOOK_URL }})
cat /tmp/response.txt
if [[ ${status_code} -ne 200 ]]; then exit 1; fi
Here you can see I have used two new keywords github
and secrets
. These are called Contexts
in GitHub Actions. You can read the documentation about what is this and what they can do.
Check Integration log
GitHub run workflows on each commit, so if you to go to Actions
menu you will see all of your commits. When you click on a specific commit you will see the log for it. Here I am giving my screenshoots.
When I click on the job it shows log for it.
Run Shell Script
Let’s make the things a little bit cleaner, We can move the cURL
command to a shell script. First write the file on bin/deploy.sh
#!/bin/bash
status_code=$(curl -d $1 --silent --show-error --write-out '%{http_code}' --output "/tmp/response.txt" $2)
cat /tmp/response.txt
if [[ ${status_code} -ne 200 ]]; then
exit 1;
fi
Now update the deploy job on CI.yml
file.
deloy:
if: ${{ github.ref == 'refs/heads/master' }}
runs-on: ubuntu-18.04
needs: laravel-tests
steps:
- uses: actions/checkout@v2
- name: Call server webhook
run: bash bin/deploy.sh ${{ secrets.WEBHOOK_DATA }} ${{ secrets.WEBHOOK_URL }}
Tips
It is not possible to re-run a successful job, to do so you have to run an empty commit and push it.
git commit --allow-empty -m "Trigger GitHub actions"
git push origin master