Continuous Integration for WordPress

Mikael Lindqvist
8 min readSep 5, 2016

When we develop a WordPress site, we put the code that makes up the site into plugins and themes. At least, this is the way we should do it. In theory, it would also be possible to modify the files that makes up the WordPress core itself. This is, however, a very bad practice and the saying “don’t hack core” is often used to discourage this way of working. When we talk about developing a WordPress site, we actually talk about developing plugins and themes for the site.

Deploying our plugins and themes using FTP

While we develop our plugins and themes we need to upload them to our server to test them. This is traditionally done using FTP or similar methods. This works, but it has a number of drawbacks. We need to think about which files we have changed and upload these files. If we have modified several files, there is a chance that we miss a file here. If we work in a team, there is a chance that someone else is editing the same file and upload their changes in place of our changes. But one of the biggest drawbacks is actually that it is tedious and boring to fire up our FTP client, log in to the site, select files to upload and so on. The reason why it is bad to have tedious and boring tasks in our workflow is not because we are lazy. It is because this tends to make us deploy our code less often. We might be tempted to clump together several changes and upload them all at once. Sometimes there might be several days between the updates, and this makes it difficult to get feedback from users and clients on how the development is going.

Continuous Integration

To combat the problems with tedious and boring deployment processes, the term “continuous integration” has been coined. In short, this means that we try to minimize the manual tasks needed to deploy our code to the environment where it runs. Ideally, the process of deploying our code should be so easy so we don’t even have to think about it. This way we can “release early and release often”, which is a principle that fits well together with what is called “agile development”. This agile approach has several advantages, and one of the most important is that it makes it possible to show the progress of the work and involve users and clients in the development process.

Continuous Integration for WordPress

The term “continuous integration” is generic. What it actually means in practice, and the tools and systems we use to support the process, depends on the underlying system and the context in which we work. In the case of WordPress, we can use a plugin called “GitHub Updater” to support the process. The remainder of this article shows how we can use GitHub Updater to set up a continuous integration workflow for our WordPress site.

The various processes used for continuous integration often make heavy use of version control systems, and the process relying on GitHub Updater is no different. The steps below assume that you are familiar with git and cloud hosted git services. In the examples we use GitHub, but GitHub Updater also supports Bitbucket and GitLab. Setting up a workflow based on those services is very similar to what is described in this article.

Step 0 - Prerequisites

We need to host our plugin in a git repository. For this example we will use GitHub. If you don’t already have a GitHub account and a WordPress plugin there, go ahead and sign up and put a plugin there! While testing, I used this plugin:

As we will use GitHub Updater, we need to add the extra “GitHub Plugin URI” line in our plugin header as described here.

Also, we need a WordPress site to deploy to. Please note that we can’t use a WordPress site hosted locally on a development machine, it needs to be accessible on the Internet. While doing research for this article I tried a number of free hosts and ran in to a few problems, since the intended use case for those free hosts is somewhat different compared to how we use WordPress here. Some free hosts don’t allow the code hosted there to make connections to the outside world, which is required for downloading the updates from GitHub. Some free hosts are set up in a way so the site there can’t respond to anything but browser requests, and this doesn’t work for us since we utilize the RESTful endpoint in GitHub Updater. Finally, I found which worked really well for this purpose. If you don’t already have a way to publish your WordPress site on the Internet for testing, I recommend signing up there.

Step 1 - Installing GitHub Updater

Once we have our WordPress site set up we need to install GitHub Updater. Unfortunately, this plugin is not hosted in the official WordPress Plugin Directory. We need to download it as a zipped file and install it to our site by uploading it. You can follow the instructions here.

Step 2 - Installing our plugin through GitHub Updater

In order to get GitHub Updater to manage the updates for us, we should use GitHub Updater to install our plugin. This is actually quicker and more convenient than uploading our plugin code as a zip file or through FTP, so already we see the benefits!

In order to install our plugin, find the “GitHub Updater” admin page under Settings, and go to the “Install Plugin” tab. Copy and paste the GitHub URI for your plugin into the “Plugin URI” field, and leave the other settings with their defaults. Next, click “Install Plugin” and your plugin should be downloaded from GitHub and installed!

The plugin will not be activated automatically. Go to the regular “Plugins” settings and activate your plugin there.

Installing our plugin through GitHub Updater

Step 3 - Setting up the Webhook

This is where the actual magic happens. We will now tell GitHub that whenever we push to our repository, we want our plugin to be updated on our site. This happens via a RESTful endpoint call from GitHub to our site, and we need to tell GitHub the URI for the endpoint that it should access. To find this URI, see the “Remote Management” tab in the GitHub Updater settings.

Finding the URI for the RESTful endpoint

We need to append the name of our plugin to this URI. The full URI in my case is:

Please note the addition of the part “&plugin=mickesplugin” at the end of the URI. Your URI will of course be slightly different depending on the API key and depending on the name of your plugin. Next, we need to set up a Webhook in GitHub to access this URL whenever we push to the repository. In the repository settings for your GitHub repository, find the “Webhooks & Services” section. Click “Add Webhook”.

Adding a Webhook to trigger updates on pushes to the repository

In the “Payload URL” field, enter the full URI, i.e. the URI from the Remote Management tab with the added plugin name. Click “Add Webhook” at the bottom of the page.

Step 4 - Pushing to our repository

Now we should be good to go! Assuming we have a cloned copy of our repository on our computer, we can make changes and as we push them to GitHub the changes should be instantaneously visible on our site. However, don’t assume that it works, go ahead and make a change, push to the repository and verify that the change actually got pushed to your WordPress site.


There are a few moving parts in this process, and obviously it is possible that things can go wrong. A tool that is useful for troubleshooting, and also useful to get a deeper understanding for how things work, is curl. Let’s try to use curl from the command line prompt to access the API URL:

Accessing the RESTful endpoint using curl

As we can see, we can access the URI fine, and GitHub Updater tells us that we need to specify a plugin or theme to update. Let’s try to add the name of our plugin to the URI, so the URI is the same as the one we use for the Webhook:

Updating a plugin using curl

Now we can actually see that the plugin was updated, and the messages tells us that GitHub Updater went ahead and downloaded the updated plugin from GitHub. This is the same process that should happen when the Webhook is accessed. To verify that this is actually the case, we can access the “Webhooks & Services” section again in our repository settings on GitHub, and click “edit” next to the Webhook we created. If we scroll down, there is a section that says “Recent Deliveries”. Here we will find a log of the attempts GitHub made to access our Webhook. Let’s look at one of the deliveries there, specifically on the “Response” tab:

Verifying the response from the Webhook in the log on GitHub

We can see here that our site replied the same thing to GitHub when the Webhook was delivered as we got from curl when we accessed the URI manually. Everything seems to work as it should!

About the authors of GitHub Updater

GitHub Updater was originally created by Andy Fragen, an acute care surgeon and open source hacker in southern California. It has seen additions by over 30 volunteers from around the world. The Webhook functionality described in this article was added by Mikael Lindqvist, a digital nomad currently residing in Kenya where he is involved in Tunapanda, a technology, design and business school in the informal settlement Kibera in Nairobi.



Mikael Lindqvist

Software developer, programming teacher and digital nomad who loves open source.