This article is going to walk you through how to create a modern workflow for local development with exceptional deployments. There will be a brief intro into local dev environments but the main technical explanations in this article will center on deployments. For more info on any part just hit up the comments or shoot me a tweet.
So I was working on a WordPress site the other day and I keep finding myself in need of deploying updates. It's for a small client that isn't a big budget project so I was trying to avoid setting up something like capistrano for deployments. The problem is though, after the initial deployment, any tweaks and changes I make are kind of confusing to sync.
Deploment: To migrate your local code to a remote environment.
Looking deeper at the problem: Small Changes = Medium Headaches
I work in a VM so to do things right, you have to switch over to the VM, boot up vagrant, start up gulp and then start doing whatever. When you make the change you then have to push it to Github or whatever you're using for VC and then after all that you have to manually copy the files you have changed up to the server. This is a pain to keep synced, keep current. Not the kind of workflow we expect in this modern age of development.
A better way: Local development with deploy tools.
So what's the best way to get up and running with a modern development environment? Well, I can tell you my way ( which I think is best ;) ). First, we need to get setup with a VM. If you are running PHP this is a must. If you are running Node then it's more at your discretion. It depends on how seperate you want to keep your computer vs your development environment.
VM: Virtual machine. A VM is used to create a custom server / environment for each project you work on.
VM's are good because they keep all of the configurations, all of the custom packages, and all of the tools a project needs from cluttering up your local machine.
If you have never used a VM just think of it as when you run Windows on your Mac. The native OS is Mac OSX but you can run windows at the same time by running it in a VM.
What VM enviroment should I use?
The setup I use is Vagrant and VVV. To me it is the easiest to use and the most flexible. Docker has become the cool tool though for provisioning VM's lately though. What are the advantages to using a VM?
- Doing installs from Bower, Composer, and NPM don't clutter up your machine.
- You can configure each environment you use to match your staging and production environments exaclty.
- If you break something you can just throw the VM out and start over.
Enough of the Jibber Jabber. Let's Deploy our code.
So once you get your local dev environment setup and you get some code that you want to deploy what's next? You could reach for an FTP client, but that strategy is older than Viggo the Carpathian's wardrobe. The new, and legit way is to use a deploy tool.
Deploy tools let you just exectue a command on the CLI and then boom, you're code gets pushed from your SCM ( source control manager ) to your desired location: either a staging server or production. In addition, most deploy tools create an environment on your servers where each deployment gets put in a folder called releases, where each release is marked by a timestamp. The deployment tool then creates a symlink called current that points to the latest release. Then you just have to tell your sever to point to the current symlink in your server configs.
There are many options out there for deployment tools. There are services that have their own tools built in like Heroku, or Envoyer. Then there are stand alone options that give you all of the control. Those are the solutions I tend to lean twoards. I have used Capistrano, which is a ruby tool, and Deployer which is written in PHP. I also came accross one that is called Rocketeer which looks pretty cool. The one we are going to go with in this post though is Deployer.
Installing it is dead simple. You just go to their website and download the phar file. Once you get the phar file you move it to a place that's in your executable path. Once you move it, then you have to change the permissions on it to make it executable.
#The reccomended path to move it to mv deployer.phar /usr/local/bin/dep #Make it executable chmod +x /usr/local/bin/dep
For those that don't know, a .phar file is just a PHP archive. It's a bundle of PHP code that's executable on the command line.
The project config file: deploy.php
Once you get the phar file installed it is accessible globally. Each project though will have a config file to tell it where it can deploy to and how to deploy there. That file is called deploy.php. Here is an example:
<?php require 'recipe/wordpress.php'; server('prod', '69.125.294.164', 22) ->user('your_username') ->password('your_password') ->stage('production') ->env('deploy_path', '/home5/your_user/public_html/folder/wp-content/themes'); set('repository', 'https://github.com/your_handle/your_repo.git');
Boom, that's it. You're ready to go after that. Next, you should be able to run
dep and then you will get a list of commands that looks something like:
Deployer version 3.0.10 Usage: command [options] [arguments] Options: -h, --help Display this help message -q, --quiet Do not output any message -V, --version Display this application version --ansi Force ANSI output --no-ansi Disable ANSI output -n, --no-interaction Do not ask any interactive question -f, --file[=FILE] Specify Deployer file. --tag[=TAG] Tag to deploy. -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug Available commands: cleanup Cleaning up old releases current Show current release. deploy Deploy your project help Displays help for a command list Lists commands rollback Rollback to previous release self-update Updates deployer.phar to the latest version worker Deployer uses workers for parallel deployment. deploy deploy:copy_dirs Copy directories deploy:prepare Preparing server for deploy deploy:release Prepare release deploy:shared Creating symlinks for shared files deploy:symlink Creating symlink to release deploy:update_code Updating code deploy:vendors Installing vendors deploy:writable Make writable dirs
If you see the deploy command there then all you have to do to deploy is type
dep deploy production to deploy to production. Since we only have production in our deploy.php that's all we can deploy to, but if we had a staging config you could push to either location.
Case study: Deploying WordPress to shared hosting.
I deployed this clients code to Bluehost so that's who we'll use for this explanation. First off, the docs for deployer say to put your deploy.php in the root directory of your project. For WordPress I think that would be the part that has the wp-content folder and all that stuff, top level. To me though, it's stupid to deploy and track in VC a whole version of whatever you're working with when you are only really using the theme folder. So, we will be putting our deploy.php file in the theme folder. It will act as our root.
Setting up the WordPress to understand the deployer directory structure.
So recall that when deployer create's a deployment, it uses this structure:
#Our wp-content/themes directory ./ ../ current releases 20151031212204 20151031213934 20151031215230 shared index.php
Current, releases, and shared were all created by our deploy tool as well as each release in releases.
So when wordpress scans this directory, it sees the symlink current and thinks it's the theme, instead of a shortcut pointing to the release, which is actually the theme. If you are deplying a whole project instead of a wordpress theme, you just have to configure your server to point to the current symlink. On Bluehost you can point the site home in the Cpanel under the domain manager option.
Conclusion: say hello to your modern workflow
So to sum things up, now you can work locally. Develop your projects on your computer while it behaves just like the real site with the real URL. Then when you're done you push the code to github, then run your deploy command and boom. Always up to date, synced code that's a joy to work with has never been easier.