← All posts

Automating WordPress.org Plugin Deployment with GitHub Actions and WP-CLI

Automating WordPress.org Plugin Deployment with GitHub Actions and WP-CLI

One of the more tedious aspects of maintaining a public WordPress plugin is the deployment process to WordPress.org. While our development workflow lives happily in Git, the official plugin repository still relies on Subversion. Manually checking out the SVN repository, copying files into `trunk` and `tags/version`, and then committing, feels like a relic from another era. I constantly found myself wishing for a way to automate this, bringing my deployment strategy into the 21st century.

The fundamental challenge is bridging the gap between a Git-based development repository and the SVN-based publishing mechanism. We want to trigger a deployment automatically from a Git push, specifically when we tag a new version in our main branch. This approach not only saves time but also ensures consistency and reduces human error that often creeps into repetitive manual tasks. My goal was to create a robust, repeatable pipeline that handles all the mundane steps, allowing me to focus purely on development.

This is where WP-CLI steps in to help prepare our plugin for release. Beyond its core utility for managing WordPress sites, WP-CLI provides powerful tools for plugin development. For instance, ensuring your internationalization files are always up-to-date is a crucial pre-deployment step. Forgetting to regenerate your `plugin-slug.pot` template file can lead to missing strings for translators. With WP-CLI, we can easily run `wp i18n make-pot . languages/plugin-slug.pot --domain=plugin-slug` as part of our automated process, guaranteeing that our translation template is current with every release.

GitHub Actions serves as the perfect orchestrator for this pipeline. It allows us to define a series of steps that execute automatically upon specific events in our GitHub repository. For plugin deployment, the most common trigger is a `push` event to a version tag, like `v1.2.3`. Before we dive into the steps, a crucial prerequisite is securely storing our WordPress.org SVN username and password as GitHub Secrets, which prevents hardcoding sensitive credentials directly into our workflow files.

The core of our GitHub Action involves a few key stages. First, we need to check out our plugin’s Git repository. Then, we set up a PHP environment (if our plugin has Composer dependencies or if we need WP-CLI’s PHP runtime) and install WP-CLI itself. Once WP-CLI is available, we execute our pre-deployment commands, such as `wp i18n make-pot` to generate the latest translation files. This ensures that every deployment includes the most current translation source, a small but important detail.

Next, the workflow needs to interact with the WordPress.org SVN repository. This typically involves checking out the SVN repo into a temporary directory, synchronizing our plugin files from the Git checkout into the `trunk` and `tags/VERSION` directories of the SVN checkout, being careful to exclude `.git` and `.github` folders. Finally, we issue an `svn commit` command, leveraging the SVN credentials stored in our GitHub Secrets, to push the new version to WordPress.org. The `rsync` command is incredibly useful here for efficiently copying files while excluding specific patterns.

Here’s a simplified snippet demonstrating the WP-CLI integration and the final SVN commit step within a GitHub Actions workflow:

```yaml name: Deploy Plugin to WordPress.org

on: push: tags: - 'v*.*.*'

jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout GitHub repository uses: actions/checkout@v3

- name: Setup PHP and Install WP-CLI uses: shivammathur/setup-php@v2 with: php-version: '8.1' run: | wget https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar chmod +x wp-cli.phar sudo mv wp-cli.phar /usr/local/bin/wp

- name: Generate translation files with WP-CLI run: wp i18n make-pot . languages/my-plugin-slug.pot --domain=my-plugin-slug

# ... (additional steps for SVN checkout and rsync files to trunk/tags) ...

- name: Commit to SVN run: | cd .svn-deploy # Assuming SVN checkout is in .svn-deploy svn commit -m "Deploying version ${{ github.ref_name }}" \ --username="${{ secrets.WPORG_SVN_USERNAME }}" \ --password="${{ secrets.WPORG_SVN_PASSWORD }}" \ --no-auth-cache ```

Implementing this pipeline brings significant benefits. It enforces a consistent deployment process, eliminating the possibility of missed steps or incorrect file placements. It drastically reduces the time spent on releases, freeing up valuable developer hours. Most importantly, it allows us to fully embrace Git as our source of truth, knowing that a simple version tag will reliably trigger a polished, production-ready release to WordPress.org, complete with up-to-date translation files.

Adopting automated deployment workflows like this is a fundamental step in modernizing WordPress development. It shifts the focus from manual, error-prone tasks to a streamlined, code-driven process that enhances both efficiency and reliability. For any serious plugin developer, mastering these infrastructure aspects is just as crucial as writing clean, performant PHP.