Factor #5: Build, release, run
Strictly separate build and run stages
A codebase is transformed into a (non-development) deploy through three stages:
The build stage is a transform which converts a code repo into an executable bundle known as a build. Using a version of the code at a commit specified by the deployment process, the build stage fetches and vendors dependencies and compiles binaries and assets.
Let's break down the two main things the build stage does:
Fetches and vendors dependencies
As we saw in the Dependencies factor, these are managed through Composer. So in the build stage we need to run
composer installto fetch and install the dependencies.
Compile binaries and assets
Most WordPress apps won't have binaries, but they definitely have assets. We're talking about images, stylesheets, scripts, fonts, etc. Compiling assets might involve the following:
- Optimizing images
- Running CSS pre-processors like SASS or LESS
- Concatenating/minifying CSS
- Concatenating/minifying JS
If you're not currently doing any of these, or doing them manually, you're missing out a great opportunity to improve your development/release workflow. These days Grunt is a very popular tool to automate tasks such as the above.
Whatever task runner/build tool you use (Grunt, Shell scripts, Make, etc), they need to be run at the build stage.
The release stage takes the build produced by the build stage and combines it with the deploy’s current config. The resulting release contains both the build and the config and is ready for immediate execution in the execution environment.
This stage sounds a bit esoteric. What exactly does combining a build with a deploy's current config mean? It really just means you should have a directory of
releases on your servers. Each one should have a unique release ID such as a timestamp (
2011-04-06-20:32:17) or tag/release version (
v1.5.1). These releases can't be changed once created and any change necessitates a new release.
The benefit of this is two-fold: historical record of releases, and more importantly, the ability to rollback to any release.
The part about combining the config is a little more complicated. When we talked about environment variables for the Config factor, they were usually global. To achieve standalone releases, you could also load env vars from a file in each release.
The run stage (also known as “runtime”) runs the app in the execution environment, by launching some set of the app’s processes against a selected release.
This stage will make more sense once we talk about Processes, but for now, the app's execution environment is usually just the PHP application server and any potential background processes for example.
In the PHP and WordPress world, the actual PHP application server gets confusing because the most common setup is Apache with the mod_php module. This means the actual PHP interpreter process is embedded in the Apache process. This might make things easier, but we'll see why it isn't ideal.
The other common setup is Nginx with PHP-FPM. PHP-FPM is a separate process that Nginx communicates with over a socket.
So for the run stage, PHP-FPM is launched to serve up a selected release.
I've already talked a lot about what these 3 stages mean in practice, but a nice deployment tool can make it easy to automate an entire deploy across the 3 stages.
Capistrano is a well known deployment tool that offers easy to write configs and 1 command deploys.
Aside: Capistrano used to be Ruby on Rails centric but as of v3 it's completely framework/language independent thanks to separating our specific plugins. So it's easier than ever to use with PHP and WordPress (you just need Ruby installed locally).
For example, the following command could compile your assets, run Composer, create a new release, and restart your web/PHP application server:
cap production deploy
Or rollback to the last release:
Investing some time into a tool like Capistrano to automate your deploy process so it can build, release, and run is a big win. You shouldn't be deploying code to production if you can't reliably rollback a deploy.
- Backing Services
- Build, release, run
- Port binding
- Dev/prod parity
- Admin processes
Want to turn your WordPress site into a Twelve-factor App? Bedrock is a modern WordPress stack to help you get started with the best tools and practices.