This post is the first in a series of deployment workflows I use to get code into production.
Many of my weekdays are spent working on and around the WSUWP Platform, an open source project created to provide a large, multi-network, WordPress based publishing platform for universities.
Conceptually, a few things are being provided.
First, a common platform to manage many sites and many users on multiple networks. Achieving this objective takes more than a plugin or a theme. It requires hooking in as early as possible in the process, through sunrise and mu-plugins.
Second, a method to describe some plugins and themes that should be included when the project is built for production.
Third, a way to develop in a local environment without the requirement of a build process firing for any change to a plugin or theme.
The platform repository itself consists of WordPress, several must use plugins, a few drop-ins, a sunrise file, and a build process. These are the things that are absolutely mandatory for the platform to perform as intended. I went back and forth on the decision to include WordPress in its entirety rather than via submodule, but decided—beyond submodules being a pain in the ass—that it was important to provide the exact code being deployed. In certain situations, this could be useful to deploy patches for testing or start using a beta in production.
Outside of the platform, WSU has additional repositories unique to our production build. Basically, if a feature should exist for anyone using the platform in production, it should be an mu-plugin. If a features is optional, it should be added through a repository of common plugins or common themes. Even more repositories exist for individual plugins and themes considered more optional than others.
A lot of repositories.
The build process for the platform, managed with Grunt, looks for anything in
build-themes/individual (deep breath)—and smashes it all together into the appropriate
build/www/wp-content/* directory alongside the files included with the WSUWP Platform project.
When all tasks are complete, the build directory contains:
In local development, it’s likely that you would never run the build process. Instead, the following structure is always available to you:
This allows us to work on individual plugins and themes without worrying about how that impacts the rest of the platform. I can install any theme I want for testing (e.g.
/www/wp-content/themes/make/) or have individual git repositories available anywhere (e.g.
www/wp-content/plugins/wsuwp-sso-authentication/.git). All of these individual plugins and themes are ignored in the platform’s
.gitignore so that only items added via the build process make it to production.
How everything makes it to production is another matter entirely.
A big objective at WSU is to reduce the amount of overhead required for something to make it into production. To achieve this, we use a plugin to handle deployments via hooks in GitHub. It seems like scary magic sometimes, but we even use the platform to deploy the platform.
When a deployment is configured through the plugin, a URL is made available to configure for webhooks in GitHub. We’ve made the decision that any tag created on a repository in GitHub should start the deploy process. A log is available of each deployment as it occurs:
When a deployment request is received, things fire as such:
- A script on the server is fired to pull down the tagged version of that repository and transfer it to the proper “to be built” location.
- After the tagged version is ready, a file is created as a “ready to build” trigger.
- A cron job fires every minute looking for a “ready to build” trigger.
- If ready, another script on the server fires the build process.
rsync is then used to sync this with what is already in production.
There are a few obvious holes with this process that will need to be resolved as we expand.
- If many tags are created at once, a lot of strange things could happen.
- There is currently no great rollback method beyond manually refiring a create tag hook in GitHub.
- It’s a deploy first, code review later model. This works for small teams, but will require more care as we expand our collaborations within the university.
All in all, our objectives are served pretty well.
Anyone on our team with the appropriate GitHub access can tag a release of a theme or plugin and have it appear in production within a minute or two. This has been especially helpful for those who aren’t as familiar with command line tools and need to deploy CSS and HTML changes in a theme.
Anyone contributing to individual themes or features via plugins doesn’t have to worry about the build process as a whole. They can focus on one piece and the series of scripts on the server handles the larger puzzle.
We’ve made a common platform available in the hopes of attracting collaborators and at the same time have a structure in which we can make our own decisions to implement various features and functionality.
I would love feedback on this process. Please leave a comment or reach out if you have any questions or suggestions!