Github provides continuous integration(CI) build pipelines using their service called github actions.
Github actions CI builds are called workflows, and a workflow can be triggered when a certain event happens on your github repository.
Events like a commit is made, a pull request is opened, etc will trigger workflow runs on github actions.
If you are working with a team of developers, Github actions can help you validate the pull requests by running required test cases against a pull request, So we can confidently merge a pull request when it is opened and all the test cases are passed.
Github actions provides unlimited build minutes for public repositories. For private repositories, The free account gives us 2000 build minutes/month. For a solo developer, This is more than enough.
Laravel CI generally consists of various steps to make sure the application runs smoothly when it goes to production. We will create a github actions workflow to perform the following tasks when a pull request is opened.
- Verify if we can install composer dependencies
- Verify if npm dependencies can be successfully installed
- Run the frontend assets build command to verify if we can successfully minify our css and js files
- Verify if we can run migrations on a database without any issues(We will use a temporary sqlite database for this)
- Run our unit tests and make sure the code changes in the pull request did not break existing functionality.
Once the above tasks are successfully executed without any issues, Then we can confidently merge the pull request if the code changes looks good.
Create Workflow File For Laravel
All the workflow files should reside inside .github/workflows
directory inside your project root.
So first, Create these two directories.
1mkdir .github && mkdir .github/workflows
Workflow files uses yaml syntax
to define the tasks. A single workflow file can contain multiple tasks.
Let's create our workflow file inside .github/workflows
directory. I am going to call this file laravel-ci.yml
. You can use any file name you want. Just make sure the file extension is .yml
or .yaml
.
1touch .github/workflows/laravel-ci.yml
Open the file in your favourite code editor and add the following code in it.
1name: Laravel CI 2 3on: 4 pull_request: 5 branches: [ master, staging ] 6 7jobs: 8 laravel-tests: 910 runs-on: ubuntu-latest1112 steps:13 - uses: actions/checkout@v2
The above file provides a basic skeleton for our github actions laravel ci build. It is configured to run the workflow on the latest version of ubuntu operating system when a pull request is opened against master or staging branches.
Our workflow is currently not running any tasks. So let's start by adding some tasks to this workflow.
1. Setup PHP(Optional)
The ubuntu-latest
image comes with the latest version of php installed already. If your application requires php version of 7.3 and lower, Add the below code to steps
section in your workflow file to switch to the php version your application is using.
1- name: Setup PHP2 uses: shivammathur/setup-php@v23 with:4 php-version: 7.2 # Change to the php version your application is using5 extensions: mbstring, bcmath # Install any required php extensions
2. Create .env file
Every laravel application should have a .env file in it to manage its environment variables. The first task we run on our workflow is copying .env.example
file to .env
.
Update the steps
section in the workflow file with below
1- name: Copy .env.example to .env2 run: php -r "file_exists('.env') || copy('.env.example', '.env');"
3. Install composer dependencies
The next step is installing composer dependencies. By testing the installation of composer dependencies, We are making sure there are no broken packages in the pull request.
1- name: Install composer dependencies2 run: composer install
4. Set our directory permissions correctly
Laravel requires certain directories to be writable by the web server. We can set these directory permissions to 777
as this is just a CI server.
You should never set directory permissions to 777 in your actual server. Setting this might result in unauthorized access to restricted files.
1- name: Set required directory permissions2 run: chmod -R 777 storage bootstrap/cache
5. Generate application encryption key
Since we are creating our .env
file freshly, It will not have an encryption key. So let's create and set an encryption key.
1- name: Generate encryption key2 run: php artisan key:generate
6. Create temporary database
In the next steps, We are going to run database migrations and unit tests. We need a temporary database to run these tasks. We can create a temporary sqlite database by adding the following task.
1- name: Create temporary sqlite database2 run: |3 mkdir -p database4 touch database/database.sqlite
7. Run database migrations
We can run database migrations on the temporary database we created. Doing so we can make sure that the new and existing migration files still work and makes necessary schema changes.
Before we run the migrations, We need to set our
DB_CONNECTION
andDB_DATABASE
environment variables to the newly created temporary sqlite database. We can set these environment variables using theenv
command as shown below.
1- name: Run laravel database migrations2 env:3 DB_CONNECTION: sqlite4 DB_DATABASE: database/database.sqlite5 run: php artisan migrate --force
8. Install NPM Dependencies
The next step is installing node dependencies. By testing the installation of npm dependencies, We are making sure there are no broken npm packages in the pull request.
1- name: Install NPM dependencies2 run: npm install
9. Minify CSS and JS files
We can run npm run prod
command to test and make sure our frontend build command works as expected and minifies our css and js files.
1- name: Minify CSS and JS files2 run: npm run prod
10. Run Unit tests
Finally, Our application is completely ready with all the necessary composer and node packages installed. It has a temporary database, env file, and the frontend assets are compiled and minified.
Now we can dive into running our unit tests to make sure the new code changes did not break existing functionality.
1- name: Run unit tests via PHPUnit2 env:3 DB_CONNECTION: sqlite4 DB_DATABASE: database/database.sqlite5 run: ./vendor/bin/phpunit
Completed workflow file
If you follow all the steps correctly, Your completed workflow file should look like below.
1name: Laravel CI 2 3on: 4 pull_request: 5 branches: [ master, staging ] 6 7jobs: 8 laravel-tests: 910 runs-on: ubuntu-latest1112 steps:13 - uses: actions/checkout@v214 - name: Copy .env.example to .env15 run: php -r "file_exists('.env') || copy('.env.example', '.env');"16 - name: Install composer dependencies17 run: composer install18 - name: Set required directory permissions19 run: chmod -R 777 storage bootstrap/cache20 - name: Generate encryption key21 run: php artisan key:generate22 - name: Create temporary sqlite database23 run: |24 mkdir -p database25 touch database/database.sqlite26 - name: Run laravel database migrations27 env:28 DB_CONNECTION: sqlite29 DB_DATABASE: database/database.sqlite30 run: php artisan migrate --force31 - name: Install NPM dependencies32 run: npm install33 - name: Minify CSS and JS files34 run: npm run prod35 - name: Run unit tests via PHPUnit36 env:37 DB_CONNECTION: sqlite38 DB_DATABASE: database/database.sqlite39 run: ./vendor/bin/phpunit
After you commit the above file to your github repository, Github will run the said tasks when ever a new pull request is opened against master
and staging
branches.
Failure / Success status of the workflow run will be displayed on the pull request on which it ran.
You can view all the workflow runs triggered in a specific repository by clicking on the actions
tab in the navigation menu of a repository page.