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-plugins/public
, build-plugins/private
, build-plugins/individual
, build-themes/public
, build-themes/private
, and 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:
build/www/wp-config.php
build/www/wordpress/
build/www/wp-content/advanced-cache.php
build/www/wp-content/index.php
build/www/wp-content/install.php
build/www/wp-content/object-cache.php
build/www/wp-content/sunrise.php
build/www/wp-content/mu-plugins/
build/www/wp-content/plugins/
build/www/wp-content/themes/
In local development, it’s likely that you would never run the build process. Instead, the following structure is always available to you:
www/wp-config.php
www/wordpress/
www/wp-content/plugins/
www/wp-content/themes/
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!
Responses and reactions
Replies
A plugin to create a webhook Github points at, that sniffs for special commits and initiates build and deployment processes … This is a great idea.
Scary and great. ;)
I tried to think of a way to make it distributable, but it really relies on some custom server config when it comes down to it. I'm still somewhat terrified of the security and need to revisit again after Evan's comments on Twitter.
Hi Jeremy,
This is really impressive. I have now worked at two universities working on WordPress, and have been stewing for a long time in my mind about how best to solve the problems you're working on. It sounds like you've come up with some really good ideas and approaches to solving the dilemmas we face when trying provide easy but trackable ongoing maintenance of a WordPress multisite system and the collection of plugins and themes that are needed.
I'm interested in collaborating if we can find a way to make it work with our systems.
Thanks!
Hey, thanks Sam! I'm glad to hear this at least seems digestible. :)
One of the main reasons I moved to WSU to build this platform was with the hope we could share our work with other universities. Our commitment to open source is high, and it would be most excellent to find a collaborator.
Let me know if you have any questions or want to talk shop sometime.
The only requirement for your mention to be recognized is a link to this post in your post's content. You can update or delete your post and then re-submit the URL in the form to update or remove your response from this page.
Learn more about Webmentions.