Continuous deployment of a website or application with a service like buddy.works greatly reduces the chance of mistakes that can occur when launching or updating a site.
In this blogpost I'll go over our config at Marbles for how we deploy our Craft CMS 3 websites with Buddy. With some creative thinking, this method will also work on Envoyer, Deploybot or any other continuous delivery service.
Before configuring your own website to run on Buddy I suggest getting up to speed with the concept of Pipelines.
First things first, there's a few config settings that need to be set to have a continuous deployment workflow without errors or inconvenience.
You need to give your Craft site a unique ID and override the session location, this is to make sure that sessions and logins are not lost between deployments. It's very annoying to lose access to the backend every time a deployment gets run.
* [
'appId' => 'marbles',
'overridePhpSessionLocation' => true,
]
The next option should only be enabled on a staging
or production
environment to prevent updates. You don't want to have an update Craft instance with updated database changes being overwritten by a deployment that wasn't updated yet!
[
'allowUpdates' => false,
]
Buddy can be configured by using either the GUI or a buddy.yml
file. I'll go over the settings in the GUI here but know that these can be just as easily configured using the config file. Buddy even allows you to switch at any time and keep your pipelines intact.
It's possible to define multiple pipelines for each project and even start one pipeline from an action within another. For this example I've just defined one pipeline, but we often have a pipeline for each environment (staging, acceptance, live...)
Inside each pipeline you can define a set of actions that need to be run.
This is a slightly modified version of the default “Run Webpack” action that Buddy provides, what we've changed here is the Docker image (with one from Yarnpkg) and the basic commands. This runs our Laravel Mix script to compile our assets, generate critical css and run some optimizations.
To install Craft CMS and all your plugins, a composer install
needs to be run. Make sure you commit your composer.lock
to speed things up and keep everything consistent!
For this action we use the laratools/laravel-ci docker image which is a great base that easily allows us to install everything without having to customise too much.
This action is pretty straight forward, after everything is installed and compiled it uses rsync to upload the files from the pipeline filesystem to a deploy-cache
folder on the server.
I've set up a few environment variables for the working directory and SSH settings in the pipeline settings to make this configuration easier to reuse on other projects or pipelines.
This is the most complicated part of our pipeline, the action is set to "Run as a script" which means the context is saved between each line of code, we're doing a few things:
current
link in the working directory.Below the image is the full code with extra comments to clarify what we're doing.
# If it exists and we want to refresh
if [ -d "releases/${execution.to_revision.revision}" ] && [ "${execution.refresh}" = "true" ];
then
# Then delete the revision
rm -rf releases/${execution.to_revision.revision};
fi
# If there is no directory for this release yet
if [ ! -d "releases/${execution.to_revision.revision}" ];
then
# Copy the deploy cache to the new release directory
cp -dR deploy-cache releases/${execution.to_revision.revision};
fi
# Make sure we have a storage/assets folder
mkdir -p storage/assets
# Make sure the release doesn't have a storage or web/assets folder
rm -rf releases/${execution.to_revision.revision}/storage
rm -rf releases/${execution.to_revision.revision}/web/assets
# Link the storage and web/assets folders
ln -s ~/httpdocs/storage releases/${execution.to_revision.revision}/storage
ln -s ~/httpdocs/storage/assets releases/${execution.to_revision.revision}/web/assets
# Remove the link to the current release
rm -f current
# Symlink to the new release
ln -s releases/${execution.to_revision.revision} current
# Reload FPM to make new code available
sudo /bin/systemctl reload plesk-php71-fpm
# Move into the current release
cd current
# Run any migrations we might have
./craft migrate/all
# Clear caches
./craft cache/flush-all
# Only keep 2 releases
cd ../releases && ls -t | tail -n +3 | xargs rm -rf
Most of this setup was done with the help of the following resources:
If you have any questions or comments, or you find that something in this blogpost doesn't work (anymore), don't hesitate to send me a Tweet or any other way of contact!