Laravel CI/CD Pipeline w/ Lasso and GitHub Actions
Tags: laravel, ci, cd, github
Published: 2021-11-15 17:50:00

> Last updated: November, 15th, 2021

TL;DR: [Example Repository](https://github.com/alexjustesen/lasso-ci-cd)

This guide will walk you though how I use GitHub Actions to create a CI/CD pipeline for [Laravel](https://laravel.com/) applications. We'll use [Lasso](https://getlasso.dev/) from Sam Carré to compile Webpack assets and upload them to a S3 storage provider and then trigger a deployment using the workflow.

> Warning: This article is very much a work-in-progress and in need of polishing my brain dump.

## Getting Started

### What is CI/CD?
"CI/CD" is Continuous (Integeration or Iteration) / Continuous (Development, Delivery or Deployment) is a process of developing, testing and deploying your code. You'll also likely see this referred to as an "Agile Development Cycle".

I recently answered a [Reddit](https://www.reddit.com/r/laravel/comments/j9fsa4/how_to_manage_and_maintain_laravel_application/g8kzlv1?utm_source=share&utm_medium=web2x&context=3) thread which sparked this whole thing. If you're still unsure what CI/CD is I suggest doing some [Googling](https://googlethatforyou.com/?q=what%20is%20ci%2Fcid).

### Assumptions
Let's all get on the same page so we don't make a 🍑 out of you and me.

- You're using GitHub as your source code management (SCM) platform and/or want to use GitHub Actions.
- You're using Laravel and that you're familiar with Laravel's file system and in specific using the S3 driver.
- You compile your assets using Laravel Mix and they get published into the default /public directory.

### Branching
For this example we're going to use a pretty simple main, develop and feature branching model. Develop will be our default branch where all code is based from and main will be our production code.

![Gitflow workflow](https://wac-cdn.atlassian.com/dam/jcr:a9cea7b7-23c3-41a7-a4e0-affa053d9ea7/04%20(1).svg?cdnVersion=1315)
> Source: [https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow)

### Process
We're going to go into some detail but the overall summary of the CI/CD pipeline looks like this.

1. Create a new branch off `develop` to do your work in.
2. Create a pull request (PR) to bring those changes into the `develop` branch.
3. On the creation of the PR into our `develop` branch run our builds and tests.
4. When merged into `develop` run a workflow to compile and upload the assets to an S3 bucket using Lasso and deploy the code.
5. Once you have enough code in `develop` for a release, open a PR into the `main` branch and we'll repeat steps 3 and 4 for production.

## Configuring

### Installing Dependencies
First we need to require a couple of composer packages.

- Require Amazon S3 `composer require league/flysystem-aws-s3-v3 ~1.0`.
- Require Lasso `composer require sammyjo20/lasso`.

### Configuring Laravel
Next we need to update Laravel's .env file with additional S3 driver options and the Lasso environment. [Example .env file](https://github.com/alexjustesen/lasso-ci-cd/blob/develop/.env.example)

- Add `AWS_ENDPOINT=` `after AWS_BUCKET`.
- Add `LASSO_ENV=` after `APP_` variables.

### Configuring Lasso
Next let's get Lasso configured, for a full explaination of the settings go to the Lasso [readme](https://github.com/Sammyjo20/Lasso#configuration).

1. Publish Lasso's config file `php artisan vendor:publish --tag=lasso-config`.
2. In `config/lasso.php` change `'disk' => 'assets'` to `'disk' => 's3'` to use the S3 drivers.
3. Optional, change `upload_to` if you plan on using the same bucket for multiple sites. You'll notice in this repository I've set it to `lasso_ci_cd/lasso`.

### Configure .gitignore
Since the whole point of this is to automate our deployments and no longer commit our assets to GitHub we need to update our .gitignore file as well.

- Add Lasso's temp directory `.lasso`.
- Add our public asset directories and any additional directories and files.
    - /public/css/*
    - /public/img/*
    - /public/js/*
    - /public/favicon.ico
    - /public/mix-manifest.json

## GitHub Actions

To get us started we're going to create and run two workflows, one to do our testing (CI) and one to do our deploying (CD).

### Continuous Improvement Workflow (Test)

The goal of this workflow is to run our build and tests when a PR is opened and when any changes are made to code where a PR is already open.

#### Workflow Additions

We're only going to add one section here to make sure our NPM dependencies install and package correctly. After the `Copy .env` step add the `Install npm dependencies and package` step to your workflow.

> This workflow can be found here: [test.yml](https://github.com/alexjustesen/lasso-ci-cd/blob/develop/.github/workflows/test.yml)

### Continuous Deployment Workflow (Deploy)

The goal of this workflow is to run when a PR is merged into develop or mail, run our tests, compile and upload assets with Lasso and finally deploy the code.

> This workflow can be found here: [deploy.yml](https://github.com/alexjustesen/lasso-ci-cd/blob/develop/.github/workflows/deploy.yml)

#### Using Secrets

> Important: Never hard code passwords or tokens into your code, use secrets.

Before we can use secrets in our workflow we need to create them in the repository. Go to Settings -> Secrets in your repository and add the following variables.

| Name | Value |
| --- | --- |
| AWS_ACCESS_KEY_ID | The public key to your account or API user. |
| AWS_SECRET_ACCESS_KEY | The secret key to your account or API user. |
| AWS_DEFAULT_REGION | The default region where you bucket resides. |
| AWS_BUCKET | The bucket's name. |
| AWS_ENDPOINT | The endpoint should be a fully qualified domain name including the protocol (https://). |

> Note: You can use any s3 compliant API service, I use Backblaze's B2 service because it's cheaper than AWS.

In addition to the changes we made to test our NPM dependencies we'll add additional steps to complete the process.

We're going to add a new step to compile and upload our assets to our S3 bucket and we'll call it `Publish assets with Lasso`. 

## Deployment

Lastly you need to add `php artisan lasso:pull` to your deployment script, I suggest doing this prior to clearing or filling any caches.

Almost forgot, don't forget to update your S3 variables in your `.env` file.

Well, that's pretty much it. At this point you should be up and running, should you have an issues getting this setup comment below or reach out on [Twitter](https://twitter.com/alexjustesen).

### Bonus

I use [Ploi.io](https://ploi.io/register?referrer=Q6l9H3OiyYW58yEcwjy8) (referral link) and Forge to host my Laravel applications.

The steps called `Trigger develop deployment` and `Trigger production deployment` in `deploy.yml` deploy to different environments based on branch name.

| Name | Branch / Environment |
| --- | --- |
| DEVELOP_WEBHOOK | develop/develop |
| PROD_WEBHOOK | main/production |

This pattern allows me to deploy code from my `develop` branch to my preview environment and code from my `main` branch to my production environment.

## Disclaimer
Testing and deployment pipelines have many forms, each is specific to the needs of the project and **should evolve over time**. This is just one way of doing it, find the process that works for you.