Platoon is really just a wrapper around Envoy. You could do everything that Platoon does using Envoy alone. However, Platoon is designed to make your life just a little bit easier. Envoy is fantastic and is really not all that complicated. Getting zero-downtime deployments right can be a little tricky as there's a bunch of steps to get through, so this is where Platoon is really useful.
The script
Since Platoon just wraps Laravel Envoy, there is a default Envoy script at it's heart. If you feel the need to modify the script, you can publish the Envoy script with:
php ./artisan platoon:plublish --envoy
or...
php ./artisan vendor:publish --tag=platoon-envoy
This will place an Envoy.blade.php file at the root of the app. If you're interested in learning more about Envoy (and we strongly encourage you to do so), take a look through the official documentation.
You shouldn't really need to publish the Envoy script, and if you're simply trying to add commands to each task, take a look at Hooks in the config reference. You can add functionality to each step without needing the Envoy script at all.
The Envoy script is broken up into the separate Platoon tasks (build, install, composer, etc...), and are run in sequence using the deploy story:
@story('deploy')
build
install
prep
composer
dependencies
assets
database
live
cleanup
finish
@endstory
You can add or remove tasks from the story as you need to. For example, let's say you wanted to add a task that reloaded the Supervisor configuration, and you wanted to run this BEFORE the cleanup task. Add a new task block just above this story block like this:
@task('supervisor', ['on' => 'live'])
supervisorctl reload
@endtask
Now update the story block:
@story('deploy')
build
install
prep
composer
dependencies
assets
database
live
supervisor
cleanup
finish
@endstory
When creating new tasks, you can choose to run the task either on the local environment (where Platoon is being run) or on the remote server. Our new supervisor task will run on the server by specifying ['on' => 'live']. To run the task locally, you could change this to ['on' => 'local'].
Envoy helper
Platoon provides a simple helper class for use in the Envoy script. If the script provided by Platoon isn't to your liking and you want to build your own script, you can still use the Platoon Envoy helper in your own scripts. You can reference the Platoon provided script for ideas on how the helper can be used.
At the very top of the script you should find the @setup block which looks something like this:
@include ('./vendor/autoload.php')
@setup
$helper = new TPG\Platoon\Helpers\Envoy;
$release = $helper->newRelease();
$target = $helper->target($server);
@endsetup
To make this work, take note of how the the Composer autoload script is included.
Note
For obvious reasons, Envoy does not boot an entire Laravel application. You will not have access to your actual app or any configuration. To get round this, the Envoy helper imports it's own configuration only. Anything you place in the platoon.php config file will be accessible through the helper, but that's it. You won't have access to stuff inside the app.php config.
You can get hold of any Platoon configuration option through the helper with the config() method. In most cases, you should not need to be grabbing configuration items, but the method is there if you need it:
$helper->config('targets.common.host');
The first task of the helper is to create a new release by calling $helper->newRelease(). This will return the name of the directory that will be created inside the releases directory. Since this name is needed a bunch, it's a good idea to keep a copy of it. Next, the helper also needs to provide the deployment target. The target($server) method returns an instance of Target which in turn provides all the details of the specified target.
Paths
The paths() method can be used to fetch a fully qualified project path. There are four defined paths: releases, live, storage and .env. You can also get the project root by using the path property on the Target instance.
$target->path; // Project root: /path/to/application
$target->paths('releases'); // /path/to/application/releases
$target->paths('live'); // /path/to/application/live
$target->paths('storage'); // /path/to/application/storage
$target->paths('.env'); // /path/to/application/.env
The paths method also accepts a second parameter as a suffix. This can be useful if you need to get to the deployed release path:
$target->paths('releases', $release); // /path/to/application/releases/1234567890
Executables
Platoon needs to know where the PHP, and Composer binaries are. This is done because it's not uncommon to find multiple versions of PHP on the same host. These values can be configured per target with the php and composer settings. The Target instance provides these values through the php and composer properties respectively:
$target->php; // Path specified as the `php` config
$target->composer; // Path specified as the `composer` config
However, since Composer would need to be run using the same PHP executable, there is a composer() method that does this for you:
$target->composer(); // /path/to/php /path/to/composer
Likewize, there is an artisan() method that does something similar:
$target->artisan(); // /path/to/php /path/to/application/live/artisan
Note
Note the difference between $target->composer and $target->composer().
Assets
Since assets are always copied into the release directory, the assets() method takes the name of the release returned by the newRelease() method on the helper. The assets method will then alter the assets array to include the full target path.
$target->assets('54321');
/*
['public/localfile.test' => 'public/remotefile.test']
becomes...
['public/localfile.test' => '/path/to/application/releases/54321/public/remotefile.test']
/*
Hooks
The hooks method will return an array of scripts specified in the target config. The method requires the name of the hook as the only parameter.
$target->hooks('build');
The hooks method will always return an array of commands, so you'll need to loop through them in an Envoy script. The script supplied with Platoon does exactly this:
@foreach ($target->hooks('build') as $step)
{{ $step }}
@endforeach
To add hooks to the previous supervisor task, the result could look as follows:
@task('supervisor', ['on' => 'live'])
supervisorctl reload
@foreach ($target->hooks('supervisor') as $step)
{{ $step }}
@endforeach
@endtask