Automating WordPress Plugin Deployment with WP-CLI and GitHub Actions
One of the most tedious and error-prone tasks in advanced WordPress development is deploying code changes to staging or production environments. Manually pulling updates, running Composer, or executing database migrations is a recipe for forgotten steps and inconsistent deployments. This is exactly where the power of WP-CLI combined with GitHub Actions can revolutionize your workflow, ensuring reliable and automated deployments directly from your source control.
I’ve personally adopted this approach for managing custom plugins and themes that drive unique business logic, and the efficiency gains are substantial. My goal isn't just to update files, but to execute a full deployment lifecycle: pulling code, updating dependencies, running database migrations, and flushing caches—all orchestrated automatically.
Let's consider a practical scenario: I have a custom WordPress plugin, `my-custom-plugin`, living in its own GitHub repository. This plugin includes Composer dependencies and a custom WP-CLI command (`my-plugin schema-update`) to handle database migrations. Whenever I push changes to the `main` branch of this repository, I want those changes to be automatically deployed to my staging server.
Here’s a simplified GitHub Actions workflow I use, located at `.github/workflows/deploy.yml` in my plugin's repository:
name: Deploy My Custom Plugin
on: push: branches: - main
jobs: deploy: runs-on: ubuntu-latest steps: - name: Deploy to Staging uses: appleboy/[email protected] with: host: ${{ secrets.SSH_HOST }} username: ${{ secrets.SSH_USERNAME }} key: ${{ secrets.SSH_PRIVATE_KEY }} script: | cd /var/www/html/wp-content/plugins/my-custom-plugin git pull origin main composer install --no-dev --optimize-autoloader wp my-plugin schema-update wp cache flush wp rewrite flush
Let’s break down what's happening here. The `on: push: branches: - main` configuration tells GitHub Actions to trigger this workflow every time I push code to the `main` branch. The `runs-on: ubuntu-latest` specifies the virtual environment where the job will execute.
The core of this deployment pipeline lies within the `steps` block, specifically using the `appleboy/ssh-action`. This action provides a secure way to establish an SSH connection to my remote server from GitHub Actions. Crucially, sensitive information like the `host` IP, `username`, and the `key` (my SSH private key) are stored as GitHub Secrets, preventing them from being exposed in the public workflow file. The `key` secret, `SSH_PRIVATE_KEY`, would contain the entire private key, including the `-----BEGIN OPENSSH PRIVATE KEY-----` and `-----END OPENSSH PRIVATE KEY-----` headers.
Once the SSH connection is established, the `script` parameter executes a series of commands directly on the remote server:
1. `cd /var/www/html/wp-content/plugins/my-custom-plugin`: I navigate to the root directory of my plugin on the server. Assuming your server structure is similar, you might adjust this path. 2. `git pull origin main`: This command fetches the latest changes from the `main` branch of my plugin’s GitHub repository directly into the server’s copy. This assumes the plugin directory on the server is a Git repository itself, which I recommend for easier management. 3. `composer install --no-dev --optimize-autoloader`: If my plugin uses Composer for dependency management, this command installs or updates all required packages, optimizing the autoloader for production performance and excluding development dependencies. 4. `wp my-plugin schema-update`: This is where my custom WP-CLI command comes into play. I've designed this command within my plugin to handle any necessary database schema changes, ensuring that the database is always in sync with the latest code version. This could involve adding new tables, modifying columns, or updating options. 5. `wp cache flush`: Crucially, I flush the WordPress object cache to ensure any cached data derived from old code or database schemas is cleared. 6. `wp rewrite flush`: If my plugin introduces custom rewrite rules, flushing them ensures that WordPress regenerates the rewrite rules, preventing broken permalinks or routing issues.
This setup significantly reduces the cognitive load during deployment. I simply push my validated code to `main`, and the automation takes care of the rest. The benefits are clear: faster deployments, fewer human errors, and a consistent environment. By leveraging WP-CLI's power for server-side operations and GitHub Actions for orchestration, you can build robust, reliable deployment pipelines for any custom WordPress component.