DEV Community

Cover image for Automatically deploying WordPress plugins and/or themes with GitHub actions
Sarah Siqueira
Sarah Siqueira

Posted on

Automatically deploying WordPress plugins and/or themes with GitHub actions

There are a lot of ways in which a WordPress GitHub integration can be helpful in WordPress development and project collaboration. One of them is in deploy routines with automatic deployments, instead of the cowboy coding approach, using FTP, manually grabbing our themes and/or plugin files, and uploading them manually using software like FileZilla, we can deploy directly from GitHub to our live WordPress site.

That's why I wrote this post and, as always, to record what I did for when I forget it in a few months from now.

We will review how to set up a WordPress GitHub integration to manage the deployment of our WordPress themes and WordPress plugins, which can save us a lot of time and is especially important if we are using custom themes and plugins.

We will not cover:

  • The WordPress Core: Well, we should never edit core WordPress files, so it doesn't make sense to include the core files in our repository.

  • The database: Trying to version control the WordPress database opens up a can of worms and we will not open that now.

  • WordPress development of plugins and themes: I am assuming you have this done, ready to deploy.

Let's get started with the sample workflows we will gonna use to synchronize our WordPress themes and plugins!

Deploying a WordPress Theme

The following .yml code is used to synchronize the theme files you coded, with the /wp-content/themes folder in your server. For a LAMP server hosted in a company like Digital Ocean, that's a sample workflow:

name: Deploy Theme

on:
  push:
    branches: [master]

env:
  SSH_USER: ${{ secrets.SSH_USER }}
  SSH_HOST: ${{ secrets.SSH_HOST }}

jobs:
  deploy:
    name: Deploy WordPress Theme on Digital Ocean
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Set SSH Connection
        run: |
          mkdir -p ~/.ssh/
          echo "$SSH_KEY" > ~/.ssh/deploy.key
          chmod 600 ~/.ssh/deploy.key
          cat >>~/.ssh/config <<END
          Host digitalocean
            HostName $SSH_HOST
            User $SSH_USER
            IdentityFile ~/.ssh/deploy.key
            StrictHostKeyChecking no
          END
        env:
          SSH_KEY: ${{ secrets.DEPLOY_KEY }}

      - name: Sync theme files
        run: "rsync --delete -avO
          --exclude /deploy_key \
          --exclude /.git/ \
          --exclude /.github/ \
          ./ ${{ env.SSH_USER }}@${{ env.SSH_HOST }}:${{ env.DEST }}"
        env:
          SSH_HOST: digitalocean
          # That's the most commom path in a WordPress instalation on a LAMP stack,
          # but you can change the destination according to your needs.
          DEST: "/var/www/your-domain/wp-content/themes/theme-folder"
Enter fullscreen mode Exit fullscreen mode

Workflow name

In the first line we have the workflow name name: Deploy Theme.

Workflow triggers

Later, we have the trigger definition, in this case, whenever I push a commit to the master branch on the repository with my WordPress theme, the workflow will be triggered. You can custom that, for more details, you can refer to GitHub documentation.

on:
  push:
    branches: [master]
Enter fullscreen mode Exit fullscreen mode

Secrets

I create variables for the custom secrets. More info here.

env:
  SSH_USER: ${{ secrets.SSH_USER }}
  SSH_HOST: ${{ secrets.SSH_HOST }}
Enter fullscreen mode Exit fullscreen mode

Jobs

The jobs section in a GitHub Actions workflow file defines one or more jobs to be executed when a workflow is triggered.

jobs:
  deploy:
    name: Deploy WordPress Theme on Digital Ocean
    runs-on: ubuntu-latest
Enter fullscreen mode Exit fullscreen mode

In the case above:

  • deploy is the name of the job, which can be customized to describe the job's purpose.
  • name is an optional field we use to making it more understandable when viewing the workflow.

  • runs-on specifies the type of virtual environment or runner on which the job will be executed. In this case, it uses the ubuntu-latest runner, indicating that the job runs on the latest available version of the Ubuntu operating system.

Steps

The steps section in a GitHub Actions workflow file defines a series of individual tasks that are executed as part of a job.

steps:
      - name: Checkout
        uses: actions/checkout@v2
Enter fullscreen mode Exit fullscreen mode

In the case above:

  • steps: contains a list of actions to be executed in the specified order.
  • name: is an optional field we use to making it more understandable when viewing the workflow.
  • uses: Specifies the action to be performed. In this example, the actions/checkout@v2 action is used to check out the source code repository.

Setting SSH Conection

This is the section of your workflow responsible to sets up an SSH connection for secure access to our remote host.

name: Set SSH Connection
        run: |
          mkdir -p ~/.ssh/
          echo "$SSH_KEY" > ~/.ssh/deploy.key
          chmod 600 ~/.ssh/deploy.key
          cat >>~/.ssh/config <<END
          Host digitalocean
            HostName $SSH_HOST
            User $SSH_USER
            IdentityFile ~/.ssh/deploy.key
            StrictHostKeyChecking no
          END
        env:
          SSH_KEY: ${{ secrets.DEPLOY_KEY }}
Enter fullscreen mode Exit fullscreen mode

- name: as in the previous parts, it's a optional field making it more understandable for us, ins this case we will see: Set SSH Connection.

  • run defines the steps or shell commands to execute. In this case:
    • Creates the ~/.ssh/ directory if it doesn't already exist.
    • Writes the SSH key, stored in the SSH_KEY environment variable, to ~/.ssh/deploy.key.
    • Sets the permissions of ~/.ssh/deploy.key to ensure it's only accessible by the user.
    • Appends SSH configuration to ~/.ssh/config, including the hostname, username, and path to the SSH key.
    • Additionally, it disables strict host key checking for the "digitalocean" host.
  • env section specifies environment variables used in the workflow, in this case, it defines the SSH_KEY variable and retrieves its value from a GitHub secret (DEPLOY_KEY).

Syncing the theme files:

This syncing section is responsible for syncing theme files to the remote server using the rsync command. In some hosts, may be necessaire to install manually rsync.

  - name: Sync theme files
        run: "rsync --delete -avO
          --exclude /deploy_key \
          --exclude /.git/ \
          --exclude /.github/ \
          ./ ${{ env.SSH_USER }}@${{ env.SSH_HOST }}:${{ env.DEST }}"
Enter fullscreen mode Exit fullscreen mode

The rsync command performs the following tasks:

  • --delete: Ensures that files deleted locally are also deleted on the remote server.

  • -avO: Sets rsync options for archive mode, verbose output, and optimization.

  • --exclude: Specifies which files or directories to exclude from the synchronization. In this example, it excludes the /deploy_key, /.git/, and /.github/ folders, but you can customize according to your project.

  • ./: Specifies the source directory to sync from, which is the current directory of the workflow.

  • ${{ env.SSH_USER }}@${{ env.SSH_HOST }}:${{ env.DEST }}:Specifies the destination for the synchronization. It uses environment variables for the SSH username, host, and destination path.

The var definition

In this section there are some other environment variables that are used within the workflow.

 env:
          SSH_HOST: digitalocean
          # That's the most commom path in a WordPress instalation on a LAMP stack,
          # but you can change the destination according to your needs.
          DEST: "/var/www/your-domain/wp-content/themes/theme-folder"

Enter fullscreen mode Exit fullscreen mode

Deploying a WordPress Plugin

To deploy a plugin, you can follow the same idea above, just changing the deploy path to /var/www/your-domain/wp-content/plugins/plugin-folder

The sample workflow below:


name: Deploy Plugin

on:
  push:
    branches: [master]

env:
  SSH_USER: ${{ secrets.SSH_USER }}
  SSH_HOST: ${{ secrets.SSH_HOST }}

jobs:
  deploy:
    name: Deploy WordPress Plugin on Digital Ocean
    runs-on: ubuntu-20.04

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Set SSH Connection
        run: |
          mkdir -p ~/.ssh/
          echo "$SSH_KEY" > ~/.ssh/deploy.key
          chmod 600 ~/.ssh/deploy.key
          cat >>~/.ssh/config <<END
          Host digitalocean
            HostName $SSH_HOST
            User $SSH_USER
            IdentityFile ~/.ssh/deploy.key
            StrictHostKeyChecking no
          END
        env:
          SSH_KEY: ${{ secrets.DEPLOY_KEY }}

      - name: Sync plugin files
        run: "rsync --delete -avO
          --exclude /deploy_key \
          --exclude /.git/ \
          --exclude /.github/ \
          ./ ${{ env.SSH_USER }}@${{ env.SSH_HOST }}:${{ env.DEST }}"
        env:
          SSH_HOST: digitalocean
          # That's the most commom path in a WordPress instalation on a LAMP stack,
          # but you can change the destination according to your needs.
          DEST: "/var/www/your-domain/wp-content/plugins/plugin-folder"
Enter fullscreen mode Exit fullscreen mode

That's my repository with some sample workflows customized for different servers. Be free to contribute through pull requests adding more workflows or even suggest improvements to the current ones. If that was useful for you, please consider leaving a star in the repository.

References and special thanks to:

Top comments (0)