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.
mkdir .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
Open the file in your favourite code editor and add the following code in it.
name: Laravel CI on: pull_request: branches: [ master, staging ] jobs: laravel-tests: runs-on: ubuntu-latest steps: - uses: actions/[email protected]
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)
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.
- name: Setup PHP uses: shivammathur/[email protected] with: php-version: 7.2 # Change to the php version your application is using 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
steps section in the workflow file with below
- name: Copy .env.example to .env 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.
- name: Install composer dependencies 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.
- name: Set required directory permissions 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.
- name: Generate encryption key 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.
- name: Create temporary sqlite database run: | mkdir -p database 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_DATABASEenvironment variables to the newly created temporary sqlite database. We can set these environment variables using the
envcommand as shown below.
- name: Run laravel database migrations env: DB_CONNECTION: sqlite DB_DATABASE: database/database.sqlite 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.
- name: Install NPM dependencies 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.
- name: Minify CSS and JS files 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.
- name: Run unit tests via PHPUnit env: DB_CONNECTION: sqlite DB_DATABASE: database/database.sqlite run: ./vendor/bin/phpunit
Completed workflow file
If you follow all the steps correctly, Your completed workflow file should look like below.
name: Laravel CI on: pull_request: branches: [ master, staging ] jobs: laravel-tests: runs-on: ubuntu-latest steps: - uses: actions/[email protected] - name: Copy .env.example to .env run: php -r "file_exists('.env') || copy('.env.example', '.env');" - name: Install composer dependencies run: composer install - name: Set required directory permissions run: chmod -R 777 storage bootstrap/cache - name: Generate encryption key run: php artisan key:generate - name: Create temporary sqlite database run: | mkdir -p database touch database/database.sqlite - name: Run laravel database migrations env: DB_CONNECTION: sqlite DB_DATABASE: database/database.sqlite run: php artisan migrate --force - name: Install NPM dependencies run: npm install - name: Minify CSS and JS files run: npm run prod - name: Run unit tests via PHPUnit env: DB_CONNECTION: sqlite DB_DATABASE: database/database.sqlite 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
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.