Chipper CI was designed to make it quick and easy to test and deploy your Laravel applications.
We're going to see how to setup a Laravel application, add some tests, and then use Chipper CI to test and deploy it.
The whole process just takes a few minutes.
A Quick Laravel App
If you're not starting from zero - great. You'll have most of this done already. However, if you want to follow along and spin up a new application to try Chipper CI out, here's how!
# Create a new Laravel application in directory my-new-app
composer create-project laravel/laravel my-new-app
cd my-new-app
Straight away, we can actually run some tests:
./vendor/bin/phpunit
But if you wanted to create some new tests, you can! Let's create a new controller, and have it bootstrap a test for that controller as well:
php artisan make:controller --test MyFirstController
We'll setup a route that uses the controller, and have the controller respond with a request.
# File routes/web.php
Route::get('/my-route', [App\Http\Controllers\MyFirstController::class, 'respond'])
# File app/Http/Controllers/MyFirstController.php
class MyFirstController extends Controller
{
public function respond()
{
return "my response";
}
}
We created a new route, and assigned the handler for that route to the MyFirstController
class's respond
method. This just responds with the text “my response”.
Let's test this!
When we created the controller, we had it create a test. We can find this test in tests/Feature/Http/Controllers/MyFirstControllerTest.php
.
<?php
namespace Tests\Feature\Http\Controllers;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class MyFirstControllerTest extends TestCase
{
public function test_we_get_a_response()
{
$response = $this->get('/my-route');
$response->assertStatus(200);
$response->assertSee("my response");
}
}
If all goes well, we should be able to run our tests and see this new test is passing!
# Run the tests
./vendor/bin/phpunit
# Output will be something like this:
PHPUnit 9.5.21 #StandWithUkraine
... 3 / 3 (100%)
Time: 00:00.070, Memory: 22.00 MB
OK (3 tests, 4 assertions)
Now that we have an application and some tests, we can setup a project in Chipper CI, run our tests, and see how we might deploy it.
Testing in Continuous Integration
Setting a project up in Chipper CI involves logging in, clicking to create a new project, and authenticating again GitHub, GitLab, or BitBucket. Once authenticated, you'll see a list of repositories to choose from, and you can create select whichever you'd like!
Once the project is created in Chipper CI, you'll see instructions on adding a .vessel.yml
file. It's pretty simple!
You can copy/paste that Yaml, and create a new file in your repository. Once you push that file up, you should quickly see a build started for that repository!
cat <<YAML >> .chipperci.yml
version: 1
environment:
php: 8.1
node: 16
pipeline:
- name: Setup
cmd: |
cp -v .env.example .env
composer install --no-interaction --prefer-dist --optimize-autoloader
php artisan key:generate
- name: Run Tests
cmd: phpunit
YAML
git add .
git commit -m "added Chipper CI yaml file"
git push origin main
The Chipper CI Yaml file controls what happens in your build. You can define the PHP/Node version, additional services (MySQL, PostreSQL, Redis, Docker, and more), setup build triggers, and more!
Any service setup (such as MySQL or Redis) will automatically add the correct values for Laravel's expected environment variables. Assuming your configuration isn't too heavily customized, your application should be able to automatically reads the correct values!
In our example above, I didn't add any services, and I removed the step that uses Node to build our static assets - we didn't it in our case!
That was pretty quick! We didn't need to muck about with creating a custom Docker image, or figuring out a thousand different configurations. It just worked!
Fancier Yaml
If you need or want to get fancier, you can bring in more services, and decide when to build your application. Here's an example chipperci.yml
file:
version: 1
environment:
php: 8.1
node: 14
services:
- redis:
- mysql: 5.7
on:
pull_request:
branches: .*
push:
branches:
- develop
- main
pipeline:
- name: Setup
cmd: |
cp -v .env.example .env
composer install -q --no-interaction --prefer-dist --optimize-autoloader
php artisan key:generate
php artisan migrate:seed
- name: Compile Dev Assets
cmd: |
npm ci --no-audit
npm run dev
- name: ESLint
cmd: npm run lint
- name: Run Tests
cmd: phpunit
This Yaml file does a few more things than our first example:
- We bring in Redis and MySQL services
- We use Build Triggers to build on any pull request, or any pushes to the
develop
ormain
branches (ignoring all other branches). - Our pipeline scripts that setup and run the application run a migration (we didn't need extra configuration to connect to the MySQL database!), and then compile static assets (needed by our tests)
Deploying
How you deploy depends on where your site is hosted. Many people use Forge, Envoyer, Vapor, or Fly to deploy their Laravel application.
These deployments boil down to either sending a webhook, or running a command. We can see how we might do that in our .chipperci.yml
file here. There's no magic!
I'll show a few examples of what it might look like to conditionally deploy to a production vs staging environment.
pipeline:
- name: Setup
cmd: |
cp -v .env.example .env
composer install -q --no-interaction --prefer-dist --optimize-autoloader
php artisan key:generate
php artisan migrate:seed
- name: Compile Dev Assets
cmd: |
npm ci --no-audit
npm run dev
- name: ESLint
cmd: npm run lint
- name: Run Tests
cmd: phpunit
- name: Deploy To Many Services
cmd: |
if [[ $CI_COMMIT_BRANCH == 'master' ]]; then
curl -X POST https://my-webhook-url/master/some-token \
-d branch=$CI_COMMIT_BRANCH \
-d commit=$CI_COMMIT_SHA
vapor deploy production
fly deploy --remote-only -a my-new-app-production
fi
if [[ $CI_COMMIT_BRANCH == 'develop' ]]; then
curl -X POST https://my-webhook-url/develop/some-token \
-d branch=$CI_COMMIT_BRANCH \
-d commit=$CI_COMMIT_SHA
vapor deploy staging
fly deploy --remote-only -a my-new-app-staging
fi
We have examples of sending a webook with curl
, running the vapor deploy
command, or running fly deploy
. These run conditionally based on the branch is pushed to, using the provided environment variables.
CI/CD for Laravel
Chipper CI tries to be the easiest solution for CI/CD with Laravel. The environments are pre-configured for you - all you need to do is select a few options.
It's simple and powerful, enabling you to do what's most important - write code, and get out of your way so you can test / deploy your applications without headaches.