Skip to main content

  • July 28, 2021

Deploying to WPEngine via a GitHub Action

Decorative Illustration WPEngine (WPE) is a great WordPress-only hosting platform. One of the best features is the ability to use git push to deploy your code to your site with just one click. This feature is super handy, but what if you are working on a team and don’t want each developer to have to set up an ssh key and remotes?

What if you only want to be able to deploy from your main git branch via a pull request and with proper approval? Or, what if you want to deploy WPEngine as part of your CI/CD deployment pipeline, only after other automated tests have passed? (Read the Happy Cog primer on getting started with GitHub Actions here.) That’s where WPEngine’s integration with GitHub Actions comes in.

I recently led a WordPress project here at Happy Cog, where the client’s host was WPEngine. We needed a way to deploy our changes via a GitHub Action that would minimize our risk, keep a history of approvals and deploys, keep everyone on the same page, and integrate with our other systems (like automated tests and Slack notifications).

So how did I do it? Read on to find out more!

Hey Dude

via GIPHY (bonus points if you are old enough to know where this gif came from!)

Create a .yml file under .github/workflows/

The first step is to create the  .yml file for our workflow. This will tell GitHub all of the steps it needs to go through in order to deploy our code.

Step 1: Name the workflow! Should be something clear and human readable (it’s ok, actually great, to leave comments in the workflow that are more descriptive).

# This is a workflow to compile and deploy to WPEngine Production

name: PROD Deploy to WPEngine

Step 2: When should the workflow be triggered? In our case, we only want this action to be triggered when pushes are made to the `main` branch.

We are using a release branch strategy for our day to day workflow. This means that we create a new “release” branch for each release and make our PRs into this branch. When it’s time for code to be released to production, the release manager reviews the PRs, approves and merges them. Then, they make a PR from the release branch into `main`. This way we have a plan and an organized method of deploying our code, along with controls around approvals.

We are also taking advantage of the GitHub releases so that we have a changelog and point in time to reference.

# Controls when the workflow will run
on:
    # Triggers the workflow on push or pull request events but only for the main branch
    push:
        branches: [ main ]

        # Allows you to run this workflow manually from the Actions tab
        workflow_dispatch:

So far so good, that was the easy part :)

Step 3: Jobs! What jobs does the action need to perform?

Not only do we want this action to deploy our code to WPE, but we also want it to compile production ready assets, like our javascript and css. So, first we start with creating the job and the build.

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
   # This workflow contains a single job called "build"
   build:
      # The type of runner that the job will run on
      runs-on: ubuntu-latest

Ok, great, now we have the job defined. Onward to the next step!

Step 4: Let’s compile! Tell GitHub how to compile our production ready assets.

We need to setup node and then install our node modules. Once we have that going, we need to run our production build command. We also need to remove the node_modules directory after compiling because we don’t need that taking up space on our server.

Notice that we are running these commands from the theme root so that they are put in the correct place (this may be different for your project!).

steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2
      - name: Setup Node.js environment
        uses: actions/[email protected]
        with:
          # Version Spec of the version to use.  Examples: 12.x, 10.15.1, >=10.15.0
          node-version: '14.6'
      - run: cd project/themes/your-fun-theme && npm install 
      
      - name: Compile production assets
        run: cd project/themes/your-fun-theme && npm run build

      - name: Remove node_modules
        run: cd project/themes/your-fun-them && rm -Rf node_modules

Step 5: Let’s deploy! Tell GitHub where and how to deploy our code.

I will have to admit that I got pretty tripped up here! I’ve been using WPEngine for years, but have only ever used `git push` to deploy to a remote from my local machine, so setting up the action was totally new to me. Not only was it my first WPEngine action, it was my first GitHub Action altogether!

I tried several different pre-existing GitHub actions (check out the GitHub Marketplace for lots of pre-made actions). I finally settled on using the action that was created by WPEngine, duh.

Before we get into the actual action, we have to do some setup in the WPEngine control panel AND in our repository.

Setup our SSH Keys

First, create a new SSH Key Pair. This will serve as a special deploy “key” between GitHub and WPEngine.

Second, in the GitHub repository, go to Settings > Secrets (you will need to have admin privileges on your repo) and add a new Secret. Call it `WPE_SSHG_KEY_PRIVATE` and paste in your newly created private key (it is not required that it be named this way, but whatever you name it should be descriptive so you know what it is, and don’t forget to update it in the action settings - we will get to that shortly).

Third, add the public key to the WPEngine SSH Gateway. I got a little turned around here because in the WPEngine settings, you add the key for an action deploy in a different location than you would if you were setting up the remote on your local machine. So make sure you navigate to the SSH Keys section of the control panel in WPE. (Navigate to this link by clicking on your user avatar in the top right and clicking “Profile”. Once on that screen, you will see “SSH Keys” in the sub menu on the left side of the screen).

NOW we are ready to set up the deploy action

As you can see, we have named our action to reflect what we are doing. And, we have also added the action to use, the pre-defined one from earlier. (Please note that this action uses `rsync` not `git push`.)

    - name: Deploy WordPress to WP Engine
        # You may pin to the exact commit or the version.
        # uses: wpengine/github-action-wpe-site-deploy@78e54ef1e8ce6591267521095a03e304a2b837f1
        uses: wpengine/github-action-wpe-site-deploy@main

Let’s set up the environment variables. We need to tell it what key to use, where the source code is coming from, and where we want that source code to end up. You can also tell it whether or not you want it to lint your PHP.

   env: 
        # Keys, lint & url options 
          WPE_SSHG_KEY_PRIVATE: ${{ secrets.WPE_SSHG_KEY_PRIVATE }} 
          PHP_LINT: TRUE

In our case, we use a WordPress bootstrap and we don’t track WP core files or have the same file structure as a typical WordPress installation, so we want to make sure that ONLY themes and plugins are deployed. Our uploads directory is ignored, so that won’t get pushed up as part of this workflow.

We keep these directories in a folder called project, so make sure to change the TPO_SRC_PATH to suit your specific needs (WPEngine does offer a “Smart Plugin Manager” system which will manage plugin updates, so if using that, you may need to check with WPE as to whether or not plugins should be part of your deployment)

     TPO_SRC_PATH: "project/*"
     TPO_PATH: "wp-content"

Ok cool, we are almost there! Now we need to tell it which branch and environment to deploy to. The branch will in most cases be main, this is what WPE uses as the default branch for it’s environments. Our action is only for Production deployments, but you can add other actions that are triggered by pushes to other branches and pushes to other environments, such as a staging site. And finally, we need to tell it the name of the environment. In the WPE control panel this is the name of the site, usually a descriptive name with no spaces, such as happycog or happycogstaging:

        # Branches & Environments 
          PRD_BRANCH: main
          PRD_ENV: yoursitename
All Together Now, The Beatles

All together now!

Here is a link to the full workflow. Happy deploying!

Back to Top