For anyone managing WordPress sites beyond a simple personal blog, the task of deploying code updates quickly becomes a bottleneck. Manually logging into a server, pulling Git changes, or worse, SFTPing files, is not only tedious but ripe for human error. In advanced WordPress development, we demand better. Today, I want to walk through setting up a continuous deployment pipeline for a custom WordPress plugin using WP-CLI and GitHub Actions, transforming a manual chore into an efficient, automated process.
Imagine you’re developing a mission-critical custom plugin, my-project-features, that adds unique functionality to your client’s WordPress site. This plugin lives in its own Git repository. Each time you push a tested change to the main branch of this plugin, you want it to automatically deploy to your staging server, without you lifting a finger. This is precisely where WP-CLI and GitHub Actions shine.
WP-CLI, the command-line interface for WordPress, is our essential toolkit on the server. It allows us to manage everything from posts and users to plugins and themes, all via shell commands. While you might be familiar with wp plugin install or wp post create, for deployment, we’ll leverage commands like wp plugin update and wp cache flush.
Our deployment pipeline will be orchestrated by GitHub Actions. A workflow defined in a YAML file in your plugin’s repository will listen for pushes to main. When triggered, it will connect to your staging server via SSH and execute the necessary WP-CLI commands there. This is a robust and secure way to manage remote deployments.
Let’s define our GitHub Actions workflow, typically located at .github/workflows/deploy.yml within your my-project-features plugin repository:
name: Deploy My Project Features Plugin
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
environment: staging # Optional: associate with an environment for stricter controls
steps:
- name: Checkout plugin code
uses: actions/checkout@v3
- name: Deploy plugin to staging via SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
# Navigate to the WordPress plugins directory on the remote server
cd /var/www/html/wp-content/plugins/my-project-features
# Pull the latest changes for the plugin
git pull origin main
# Run WP-CLI commands from the WordPress root
# Ensure WP-CLI is installed and accessible (e.g., /usr/local/bin/wp)
/usr/local/bin/wp plugin update my-project-features --path=/var/www/html
# Clear WordPress object cache to ensure new code takes effect immediately
/usr/local/bin/wp cache flush --path=/var/www/html
Let’s break down this deploy.yml file. The name is self-explanatory. The on: push: branches: [main] section tells GitHub to run this workflow whenever changes are pushed to the main branch of this specific plugin repository.
Inside the jobs: deploy section, runs-on: ubuntu-latest specifies the virtual machine environment GitHub provides for running our actions. The environment: staging line is optional but recommended; it links this job to a GitHub environment, which can provide additional security features like manual approvals or specific deployment rules.
The steps are the heart of the workflow. First, uses: actions/checkout@v3 clones your plugin repository onto the GitHub Actions runner. This is crucial if you wanted to build an artifact (like a ZIP file) or run local tests before deploying.
The real magic happens with uses: appleboy/ssh-action@master. This popular action allows us to securely execute commands on a remote server. You’ll notice host, username, and key are populated by secrets.SSH_HOST, secrets.SSH_USER, and secrets.SSH_PRIVATE_KEY. These are GitHub repository secrets, which you configure in your repository settings. Never hardcode sensitive information like SSH keys directly in your YAML file. The script block contains the actual commands to be executed on your staging server.
First, we cd into the plugin’s directory within your WordPress installation. This assumes your my-project-features plugin on the staging server is also a Git repository, pointing to the same remote. Then, git pull origin main fetches and merges the latest changes.
Finally, we run our WP-CLI commands. Note the explicit /usr/local/bin/wp path; this ensures we’re calling the correct WP-CLI executable on your server, assuming it’s installed there. The --path=/var/www/html argument is critical. It tells WP-CLI where your WordPress installation root is located, as our script isn’t running from that directory. wp plugin update my-project-features triggers any necessary database schema updates or other lifecycle hooks defined within your plugin. And wp cache flush ensures that any object or opcache entries that might be stale due to your code changes are cleared, guaranteeing users see the latest version immediately.
This setup provides a robust, repeatable, and secure way to deploy your custom WordPress plugins. Once configured, you can push changes with confidence, knowing that your staging environment will be automatically updated, freeing you to focus on developing rather than deploying. This is a foundational step towards mature WordPress infrastructure engineering.