WordPress CI/CD: Ultimate CI/CD pipeline for WordPress

wordpress-ci-cd

In this tutorial, I’ll show you how to create a CI/CD pipeline for your WordPress site. And that’s not all: I’ll also provide you with my complete CI/CD WordPress workflow including the WordPress CI/CD pipeline!

Continuous Integration and Continuous Deployment (CI/CD) in WordPress is somewhat special compared to other types of web applications. This is because we do not want to deploy the entire application, i.e. not the complete WordPress core including plugins, etc., but only the theme to which customisations are made.

In this tutorial, I will introduce you to my complete WordPress workflow. In addition

  • Complete local development environment (including web server, database and phpmyadmin)
  • Code quality and CI tools (including linting, code formatting for HTML, CSS, JS, TS and PHP)
  • CI & CD (Continuous Integration & Continuous Delivery/Deployment) pipeline for GitHub Actions
  • Automated code formatting before each commit
  • Installation of recommended VSCode extensions
  • Script to integrate a live website into the workflow
  • Git workflow with code reviews and PRs (pull requests)
  • Optional JS & CSS Minify for delivery/deployment
  • Rollback to last successful build if deployment fails

Nice, isn’t it? Many functions are only possible with containers and a great way to share the same environment with several developers. But before we start with the set-up, let’s get to the basics.

Why should I use Continuous Integration and Deployment in WordPress?

Why should you use CI/CD in WordPress? CI/CD relieves you of tedious tasks and ensures that your code is always in top form. This allows you to concentrate on the creative side of things and worry less about technical problems. Here is a summary of the most important factors:

  • Save time with workflow automation: Your assistant takes care of all the routine stuff for you – leaving more time for coding.
  • Recognise bugs early: Find errors before they become big and problematic.
  • Avoid errors: Automatic tests ensure that you don’t accidentally sabotage your own website.
  • Faster releases: Your changes go online faster and you can react more quickly to feedback.
  • Continuous improvements: Constant updates keep your website up to date.

Install Requirements

As already mentioned, some functions are based on Docker containers and some features for the IDE also require a few packages. You will therefore need the following programmes:

WordPress CI/CD Pipeline

I have implemented the WordPress CI/CD pipeline in GitHub Actions. You should be able to manage with the free quota for a while. The pipeline executes the linter and prettier on a push to the develop branch. This always ensures good code quality in terms of formatting. If you then want to make the status live, open a PR on the main branch. After confirmation, your theme will be loaded into your production environment. This is done via an FTP sync.

The system then checks whether the website is accessible or whether it returns a 200 OK. If not, something went wrong during deployment and the last commit is reinstalled.

For the pipeline to work, the following variables must be created in the GitHub repo:

  • Variables:
    • FTP_SERVER: The host name of your FTP connection.
    • FTP_USER: The user name of your FTP connection.
    • THEME_NAME: The name of your WordPress theme (e.g. oceanwp-child).
    • LIVE_URL: The URL of your live website.
  • Secrets:
    • FTP_PASSWORD: The password of your FTP connection.
    • PAT: A Personal Access Token from GitHub, which has write access to your repository.

Here is the WordPress CI part, if you only want to use this part for your project:

name: Continuous Integration

on:
  push:
    branches: ['develop']

jobs:
  run:
    runs-on: ubuntu-latest

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

      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Run linter
        run: npm run lint

      - name: Run prettier
        run: npm run format

And here is the WordPress CD part:

name: Continuous Deployment

on:
  push:
    branches: ['main']

jobs:
  cd:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
        with:
          ref: main

      # Remove the comments from line 18-27 to enable minification
      # - name: Set up Node.js
      #   uses: actions/setup-node@v2
      #   with:
      #     node-version: '20'

      # - name: Install dependencies
      #   run: npm ci

      # - name: Run minifier
      #   run: npm run minify

      - name: Sync files
        uses: SamKirkland/FTP-Deploy-Action@v4.3.4
        with:
          server: ${{ vars.FTP_SERVER }}
          username: ${{ vars.FTP_USER }}
          password: ${{ secrets.FTP_PASSWORD }}
          local-dir: ./wordpress/wp-content/themes/${{ vars.THEME_NAME }}/
          server-dir: ${{ vars.FTP_SERVER_DIR }}

      - name: Check Website Reachability
        run: |
          sudo apt-get update
          sudo apt-get install -y curl

          URL="${{ vars.LIVE_URL }}"

          # Perform a cURL request to fetch the HTTP response code.
          echo "Checking if $URL is reachable..."
          HTTP_STATUS=$(curl -sS -o /dev/null -w "%{http_code}" "$URL")

          # Check if the HTTP status code is not 200 (OK).
          if [ "$HTTP_STATUS" != "200" ]; then
            echo "Webpage is reachable but returns an unexpected status code: $HTTP_STATUS"
            exit 1
          else
            echo "Webpage is reachable and returns a 200 (OK) status code."
          fi

      - name: Push
        uses: s0/git-publish-subdir-action@develop
        env:
          REPO: self
          BRANCH: theme
          FOLDER: ./wordpress/wp-content/themes/${{ vars.THEME_NAME }}/
          GITHUB_TOKEN: ${{ secrets.PAT }}
          MESSAGE: 'Build: ({sha}) {msg}'

  rollback:
    runs-on: ubuntu-latest
    needs: cd
    if: failure()

    steps:
      - name: Checkout theme branch
        uses: actions/checkout@v2
        with:
          ref: theme

      - name: Rollback files
        uses: SamKirkland/FTP-Deploy-Action@v4.3.4
        with:
          server: ${{ vars.FTP_SERVER }}
          username: ${{ vars.FTP_USER }}
          password: ${{ secrets.FTP_PASSWORD }}
          local-dir: ./
          server-dir: ${{ vars.FTP_SERVER_DIR }}

      - name: Check Website Reachability after Rollback
        run: |
          sudo apt-get update
          sudo apt-get install -y curl

          URL="${{ vars.LIVE_URL }}"

          # Perform a cURL request to fetch the HTTP response code.
          echo "Checking if $URL is reachable..."
          HTTP_STATUS=$(curl -sS -o /dev/null -w "%{http_code}" "$URL")

          # Check if the HTTP status code is not 200 (OK).
          echo ""
          echo "Rollback result:"
          if [ "$HTTP_STATUS" != "200" ]; then
            echo "Webpage is reachable but returns an unexpected status code: $HTTP_STATUS"
            exit 1
          else
            echo "Webpage is reachable and returns a 200 (OK) status code."
          fi

Set up WordPress in Git Repo

Thanks to my boilerplate code in the repo, setting it up is very easy and can be done in just a few steps. However, a few adjustments are necessary:

  1. Create a folder and clone this repository with git clone https://github.com/lorenzhohmann/wp-workflow-template . inside the empty folder.
  2. Run the setup-repo.sh script (run chmod +x setup-repo.sh and ./setup-repo.sh)
  3. Create a Personal access token under Settings > Developer settings > Personal access tokens > Generate new token (classic) and create a new variable PAT in your repository settings under Secrets and variables > ‘Secrets’ tab > New repository secret

Here is the link to the repo:

WordPress CI/CD Repo Template

To use a website with the repo template, you can now use the import.sh script. To do this, create a complete export (tgz file) of your website (incl. SQL dump) in the root directory and execute the script (./import.sh). This script will ask you a few questions and should then completely set up the repo for you.

If you want to create a completely new website, I still recommend installing it in a different folder and using the tgz file. Otherwise you will have to set som

Understanding WordPress workflow

As announced at the beginning, the repo contains more than just a WordPress CI/CD pipeline. I have configured the pipelines so that they work according to the Git workflow.

Git Workflow
Git Workflow (Source: https://www.atlassian.com/de/git/tutorials/comparing-workflows/gitflow-workflow)

Here is a brief summary of the most important facts for you:

  • Make sure to checkout the develop branch by using git checkout develop. Run git branch develop before, if the branch doesn’t exist.
  • Run git pull every time before you make changes.
  • Make your changes, commit them and push them to the remote repository.
  • Once the changes are pushed, GitHub executes Code Linting and Formatting in the Background.
  • Create a PR (pull request) and have a code review done by another developer.
  • After the other developer accepts the change, the theme is automatically deployed to your production system.

WordPress CI/CD: Conclusion

I hope I haven’t promised too much. In my opinion, this WordPress CI/CD workflow is great if you develop WordPress websites yourself and want to save yourself a bit of work and value code quality and clear work structures. Have fun with the workflow! 🙂 Suggestions for improvement and errors can be created as issues.

Related Posts
Leave a comment

Your email address will not be published. Required fields are marked *

bold italic underline strikeThrough
insertOrderedList insertUnorderedList outdent indent
removeFormat
createLink unlink
code

This can also interest you