Using Envoyer for Deployment
June 13, 2016
The Problem:
For every deploy that was done to Kickfurther all user sessions would be destroyed. That means every-time one line of copy needed to be changed all users would be kicked out and forced to login again. If a company was in the middle of filling out their Co-Op information and uploading images and getting everything just right, sorry! Please login and do it all over again.
The Solution:
Laravel’s Envoyer, a Zero Downtime Deployment Solution. It allows us to deploy to production 50+ times a day if we need to. (Hopefully we don’t ever need to.)
Envoyer works by checking out your project into a releases folder which is named as a timestamp of when it was checked out, eg.
once all the deployment scripts have run, this release folder is then symlinked to
which is where the web root is pointed, so /var/www/kickfurther.com/current is always the most current codebase and nginx or other configurations never need to change.
The First Step:
The first step in hooking envoyer up is to give it the github repo of your project and tell it which branch it should be defaulting to. In Kickfurther’s case we have master, stage and dev projects to deploy the respective branches.
Deployment Hooks:
The next step is to input your custom deployment hooks. In Kickfurther’s case we have separate Job and Web Servers which gives us a separation of concerns but that means they do not need the same deployment scripts. For example, the Job server does not need to run any npm tasks.
The deployment scripts can be completely customized based on your projects needs. In our case we are using supervisor to manage the queue workers and this needs to be restarted upon every deploy so it updates the symlink with the /current directory, thus always running the current release.
This is an example of the deployment script I’ve setup to run npm install only when the package.json file has changed, otherwise there is no need to replace the node_modules folder and thus we would only run gulp –production since only the source files have changed.
cd {{release}}
# Compare the current package.json with the new package.json
# only npm install if they are different
if ! cmp -s {{project}}/current/package.json {{release}}/package.json
then
rm -rf {{project}}/node_modules
rm -rf {{project}}/bower_components
npm install
mv {{release}}/node_modules {{project}}/node_modules
mv {{release}}/bower_components {{project}}/bower_components
# Compare the current bower.json with the new bower.json
# only bower update if they are different
elif ! cmp -s {{project}}/current/bower.json {{release}}/bower.json
then
rm -rf {{project}}/bower_components
npm run bower
mv {{release}}/bower_components {{project}}/bower_components
fi
ln -s {{project}}/node_modules {{release}}/node_modules
ln -s {{project}}/bower_components {{release}}/bower_components
npm run gulp
A Deployment:
Conclusion:
Envoyer has given us the peace of mind that our deploys will always follow a repeatable pattern with insight into all output done on each command.
Isn’t that what all SAAS should strive for?