GitHub Actions to create and deploy plugins/themes
Published: – Leave a comment
When creating plugins or themes, you often need build assets and/or deploy it to somewhere else, e.g. to the WordPress.org plugin repository. Since the code is often hosted on GitHub, the so called GitHub Actions can be used to do this.
GitHub Actions
So what are GitHub Actions exactly? It’s a service you can use on GitHub to run certain actions after publishing code, adding a tag or various other Git related triggers. You can define what the action should do and it will be done whenever you want it to. There is also a marketplace with actions someone built, which you can then use without needing to reinvent the wheel. So for most usual actions, there’s already a solution.
How does it work?
The configuration of GitHub Actions is placed within your repository under the .github/workflows
directory. It is YAML file (or multiple YAML files) and contains strict instructions on how to do something and when to do it.
Deploy to WordPress.org
When a plugin should be deployed to the WordPress.org plugin repository, there is an action for that by 10up, which can be used. In the following example, it will always deploy the code to WordPress.org if a tag is created:
name: Deploy to WordPress.org
on:
push:
tags:
- "*"
- "!*-*"
jobs:
tag:
name: New tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: WordPress Plugin Deploy
id: deploy
uses: 10up/action-wordpress-plugin-deploy@stable
env:
SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
Code language: YAML (yaml)
Here, we use two actions. One is the actions/checkout@v4
to retrieve the actual code from the repository, and 10up/action-wordpress-plugin-deploy@stable
to deploy it to WordPress.org.
But let’s break it down line per line:
First, the name of the action is set. Then, we determine that the action should be started whenever a tag is pushed, that doesn’t contain a -
(which allows to ignore tags like v1.0.0-dev1
).
Then, we create the jobs, which is one job called tag
with the name “New tag”, that runs on the latest version of Ubuntu with two steps: one is the above mentioned checkout step to get the code and the other is the deploy action from 10up. As you might have already seen, this needs a username and a password to connect to the SVN on WordPress.org. To set it, go to Settings > Secrets and variables > Actions in your repository at GitHub and create the two variables SVN_USERNAME
and SVN_PASSWORD
with your username and password of your WordPress.org account.
Compile and minify assets
Often you need to compile code, such as SCSS/Sass to CSS or minify JavaScript. You can also use or create an action to do that. Since I usually use @wordpress/scripts
to compile and minify my code, I need to run npm before deploying something. To do that, I use the action bahmutov/npm-install@v1
with the following steps:
- uses: bahmutov/npm-install@v1
- name: npm build
run: npm run build
Code language: YAML (yaml)
Using the job from above, the complete code looks like this:
name: Deploy to WordPress.org
on:
push:
tags:
- "*"
- "!*-*"
jobs:
tag:
name: New tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: bahmutov/npm-install@v1
- name: npm build
run: npm run build
- name: WordPress Plugin Deploy
id: deploy
uses: 10up/action-wordpress-plugin-deploy@stable
env:
SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
Code language: PHP (php)
It installs all npm dependencies and then runs the command npm run build
, which is used in @wordpress/scripts
to build the assets. This is done before deploying it to WordPress.org.
Deploy to remote server via SSH
It may also necessary to deploy the code to a remote server, in this example via rsync on a SSH connection. I use that to keep a plugin updated automatically after deploying a new version on my server without the need to search for updates, first. I use the actions shimataro/ssh-key-action
and Burnett01/rsync-deployments
for that, but it’s also possible to run a rsync
command directly in GitHub Actions (as any other shell command as well):
- name: Install SSH key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SSH_PRIVATE_KEY }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: Deploy plugin
uses: Burnett01/rsync-deployments@7.0.1
with:
switches: -ahv --exclude=".git"
path: .
remote_path: /home/wp-content/plugins/plugin-name
remote_host: ${{ secrets.REMOTE_HOST }}
remote_user: ${{ secrets.REMOTE_USER }}
remote_key: ${{ secrets.SSH_PRIVATE_KEY }}
Code language: YAML (yaml)
The action shimataro/ssh-key-action
makes sure that the GitHub Action knows the host key of my remote server and thus allow connecting to it. The second one actually deploys the code as is to the plugins directory of a WordPress instance on my server.
To use it, you need to create certain secrets again as mentioned above:
KNOWN_HOSTS
: The host key(s) of your remote host. For the server example.com, you can retrieve them viassh-keyscan example.com
.SSH_PRIVATE_KEY
: A SSH private key that matches an allowed SSH public key on your remote server.REMOTE_HOST
: The hostname of your remote server.REMOTE_USER
: The username on your remote server.
Create release
You can also create a GitHub release and attach the plugin/theme as ZIP file to it to always allow access to a released version of your plugin/theme. This requires you to create the ZIP file yourself and then add it to a release via a GitHub action:
- run: mkdir ${{ github.event.repository.name }}-build && rsync -a . ${{ github.event.repository.name }}-build
- run: cd ${{ github.event.repository.name }}-build && zip -r ../${{ github.event.repository.name }}.zip * -x "${{ github.event.repository.name }}-build/*" && cd ..
- run: rm -rf ${{ github.event.repository.name }}-build
- name: Create Release
id: create_release
uses: softprops/action-gh-release@v2
with:
files: ${{ github.event.repository.name }}.zip
name: Release ${{ github.ref_name }}
Code language: YAML (yaml)
I use a temporary directory to copy all data into it I want to have included in the ZIP file. Via rsync
, I could add certain excludes, which won’t be copied to this directory and thus were not present inside the ZIP file later on.
To create the release, I then use the GitHub Action softprops/action-gh-release
and attach the created ZIP file to this release. The ZIP file is named after the repository while the release is named after the tag I gave it.
Conclusion
Nobody wants to do something manually that can be automated. GitHub Actions are perfectly usable to deploy your WordPress plugin/theme fully automatically and without even think about it once the actions have been defined.