Deploying WordPress to WP Engine with GitHub Actions

GitHub Actions allow deployment directly to servers based on branch commits individually. We have separate deployment scripts for development (the dev branch), staging (the stg branch), and production (the main branch). The scripts use a GitHub variable for an SSH key tied to the Kalamuna GitHub account so as long as the WP Engine installs are part of the Kalamuna WP Engine account, they should work.

Setting up .gitignore: Whitelisting approach

This approach basically ignores everything, then adds back in only the specific resources needed for the project. It’s preferred as it’s simpler to keep track of and guarantees you’ll only have what you specifically want in the repo.

The drawback is that for existing repos, you have to remove all previously tracked files that are now unwanted (like WP core files) because once a file gets tracked with Git, it will continue to be tracked unless removed from the cache. Unfortunately that also results in having it removed from your local install.

First, here’s the .gitignore file contents. Note that you’ll need to update the theme folder name, add any specific plugins you do want tracked, etc.

# Ignore everything * # Whitelist certain files in any location !**/.gitignore !**/.github/** !**/.gitkeep !**/.circleci/** !**/.gitattributes !**/.lando.yml !**/.env.example !**/wp-config-sample.php !**/wp-cli.yml !**/README.md !**/readme.md !**/README.html !**/package.json !**/package-lock.json !**/composer.json !**/composer.lock !**/.editorconfig !**/CHANGELOG.md !**/webpack.config.js !**/webpack.mix.js !**/phpunit.xml.dist !**/phpunit.xml !**/phpcs.xml !**/phpcs.xml.dist !**/phpcs.ruleset.xml !**/.eslintrc !**/license.txt # track favicon files, if they exist !**/android-chrome-*.png !**/apple-touch-icon*.png !**/browserconfig.xml !**/favicon*.png !**/favicon*.ico !**/manifest.json !**/mstile-*.png !**/safari-pinned-tab.svg !**/site.webmanifest # Don't ignore the theme file !wp-content/themes/understrap-master/** # This means that the node_modules directory inside the theme directory is not ignored by default, # because it falls under the theme directory, which is an exception to the * rule. # Note that in gitignore the order of rules is important. hence the above. **/node_modules/ **/vendor/ # Ignore OS generated files **/.DS_Store **/._* **/Thumbs.db # Ignore Editor files **/.vscode/ **/.idea/ **/*.sublime-project **/*.sublime-workspace **/*.komodoproject # Ignore log files and databases **/*.log **/*.sql **/*.sqlite # Ignore compiled files **/*.com **/*.class **/*.dll **/*.exe **/*.o **/*.so # Ignore packaged files **/*.7z **/*.dmg **/*.gz **/*.iso **/*.jar **/*.rar **/*.tar **/*.zip

If you have an existing install that was previously tracking core files and such, you need to remove the unwanted files from git:

git rm -r --cached .

This removes the previously tracked files like WP core etc. from the repo, basically anything that was tracked earlier but now is covered by the updated gitignore.

Check to see what files have been changed. If you need to forcibly add files or folders to the git repo, you can use this command:

git add -f <filenames/directories>

For instance, to add the theme from the previous gitignore example, you might need to do:

This keeps those files in the repo if they got ignored as part of the cache removal.

Now you will need to manually paste back in the theme file or plugins (downloaded from the dev or live environments) to your local to get back up and fully running. Or install them manually through the CMS. Those will likely include the files in the root WordPress install, wp-admin, wp-includes, etc.

By default, WP Engine expects their installations to automatically update WordPress core files, and they encourage people to use Smart Plugin Manager for automatically updating plugins. For clients using those options, your .gitignore file needs to exclude those files from version control or you'll end up overwriting automatically updated files with ones that may be out of date.

If the client and Kalamuna decide to include WordPress core and plugin version control in the repo and deployment strategy, however, you will need to contact WP Engine support and ask them to disable auto updates (as of this writing, there’s no way to change automatic updates within the WP Engine interface directly). You would then need to make sure those files are not being ignored in .gitignore.

WP Engine’s general guidelines for Git can be found here.

.gitignore excluding core and plugins (allow WP Engine and Smart Plugin Manager to handle those updates, they are not part of the repo)

Note that lines 24 and 48 include the wordpress folder declaration for plugins and uploads. We are still investigating why that's required for those folders but not others, but for now only include wordpress/ if the repo is set up with WordPress installed into that directory instead of the root.

.gitignore allowing WP Core and plugins to be version controlled in the repo

Remember, you will need to contact WP Engine support and ask them to disable auto updates (as of this writing, there’s no way to change automatic updates within the WP Engine interface directly).

GitHub Action Deployment Scripts

To start, add a .github directory in the project root, then add a workflows directory inside it.

Development

Create a file called build-and-deploy-development.yml file in workflows with the following content:

Replace the WPE_ENV variable on line 30 with the name of the installation from WP Engine (it's the part of the SSH key before the @ symbol if you go into the WPE install and click on Overview. In this example it's devfoodwise:

Line 20 defines the root directory for the repository code to load from. In this case the repo is set to have Wordpress installed in a wordpress directory in the root. If the repo you are using has everything in a root folder including the WordPress source files, you would just need a slash for the variable content.

Staging

Create a file called build-and-deploy-staging.yml file in workflows with the following content:

Replace the WPE_ENV variable on line 30 with the name of the installation from WP Engine (it's the part of the SSH key before the @ symbol if you go into the WPE install and click on Overview. In this example it's stgfoodwise.

Line 20 defines the root directory for the repository code to load from. In this case the repo is set to have Wordpress installed in a wordpress directory in the root. If the repo you are using has everything in a root folder including the WordPress source files, you would just need a slash for the variable content.

Production

Create a file called build-and-deploy-production.yml file in workflows with the following content:

Replace the WPE_ENV variable on line 30 with the name of the installation from WP Engine (it's the part of the SSH key before the @ symbol if you go into the WPE install and click on Overview. In this example it's foodwise.

Line 20 defines the root directory for the repository code to load from. In this case the repo is set to have Wordpress installed in a wordpress directory in the root. If the repo you are using has everything in a root folder including the WordPress source files, you would just need a slash for the variable content.

Summary

Once an SSH key has been set up and assigned to a variable in the Settings → Security → Secrets portion of the Kalamuna WP Engine account, it can be referenced in yml files tied to specific branches to deploy specific branches to the designated server automatically. If we ever need to change the SSH key, we can just change it in the secret variable and not have to update ever install’s configuration files.

Gotchas in this process are:

  1. Make sure the SRC_PATH is correct, otherwise you won't be pushing the right files. By default Kalamuna WordPress repos are set up to have WordPress in its own directory outside the root, but there are legacy or inherited projects that don’t follow this pattern.

  2. Make sure the WPE_ENV variable are set to the correct WP Engine installations.

  3. Make sure branches is set properly on line 5 of the deployment file for the matching branch. While the three default Kalamuna branches are dev, stg, and main, legacy or inherited sites may differ so be sure to check.