If you are tired of the long and sometimes stressful build and deploy process of your wordpress website, don't panic anymore there are some cool DevOps magic waiting for you. In this short tutorial, I'll show you how to easily setup a CI/CD workflow for a wordpress website (Github, Codeship and AWS or Digital Ocean.)

What you will need for this guide:

- Github Repo (Private or Public)
- Github Actions or Codeship account (there is a free tier)
- AWS or Digital Ocean account (This guide focuses on these two, but it can be applied to other servers with minimal changes)

Setup Github Actions
Go to your repo and in the upper side submenu click on the actions option.

You will now see a different set of workflows available in the github marketplace, and some other pre-made options that will make your life easier. In this case we will go and set up our own workflow.

This will create two directories and one file in your repo:

Change the name of main.yml to anything better suited for your workflow in order to not get confused.

The fun starts now!
A template YAML file will be created.  You can use part of it or you can just try with the following code:

# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node

name: Build and Deploy

    branches: [ dev ]
    branches: [ dev ]


    runs-on: ubuntu-latest

        node-version: [12.x]

    - uses: actions/checkout@v2
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
        node-version: ${{ matrix.node-version }}
    - run: npm install 
      working-directory: ./wp-content/themes/YourTheme/  
    - run: npm run dev
      working-directory: ./wp-content/themes/YourTheme/ 

    - uses: burnett01/rsync-deployments@4.0
      name: wp-content sync
        switches: -avzru --exclude="/themes/*"  --include="./wp-content/uploads/*"  
        path: ./wp-content/
        remote_path: /var/www/html/wp-content/
        remote_host: ${{ secrets.DEV_HOST }}
        remote_port: 22
        remote_user: ${{ secrets.DEV_USERNAME }}
        remote_key: ${{ secrets.DEV_DEPLOY_KEY }}
    - uses: burnett01/rsync-deployments@4.0
      name: theme sync
        switches: -avzru --delete --exclude="./wp-admin/*" --exclude="./wp-includes/*"  --include="./wp-content/themes/YourTheme/*"
        path: ./wp-content/themes/YourTheme/  
        remote_path: /var/www/html/wp-content/themes/YourTheme/ 
        remote_host: ${{ secrets.DEV_HOST }}
        remote_port: 22
        remote_user: ${{ secrets.DEV_USERNAME }}
        remote_key: ${{ secrets.DEV_DEPLOY_KEY }}    
    - name: acf refresh
      uses: fifsky/ssh-action@master
        command: |
          cd /var/www/html/wp-content/themes/YourTheme
          ls -a
          /bin/bash -c "/usr/bin/php7.0 /usr/local/bin/wp acf clean" ; /bin/bash -c "/usr/bin/php7.0 /usr/local/bin/wp acf import --all"
        host: ${{ secrets.DEV_HOST }}
        user: ${{ secrets.DEV_USERNAME }}
        key: ${{ secrets.DEV_DEPLOY_KEY}}

Lets dig into this YAML file:

First thing to notice is the on. This will determine on which branch the action will be executed. This action will be executed when a direct push or a pull request is made to the dev branch.

Next Part is the jobs. The main workflow part starts here. We are describing a job called build. Next will specify the runs-on option, which describes the OS image that will be summoned from the github worker.

The strategy section is used in case you need to run the build with different software versions.

Steps refers to where the main action will start. This is where we summon tools and action them.

We will use three different sets of actions: the first one to checkout, the second one to do rsync and the third one to run ssh commands.

Next, we'll go into our repo settings and add the secrets so the workflow can read the user, host and private key of the server that we will deploy. This can also be added directly in the workflow file but for the best practice is to keep it in secrets.

Go to Settings -> Secrets -> New secret and add your three variables described in the workflow (DEV_HOST, DEV_USERNAME, DEV_DEPLOY_KEY)

So far, this is what we're doing:

  1. Github Summons a worker virtual machine with the specified OS
  2. Your repo gets cloned into the virtual machine
  3. NPM install and build runs and creates artifacts as described in your script
  4. Rsync is ran into your theme and wp-content server directory
  5. ACF refresh is made with an ssh connection on the remote server

Remember having all of these steps is up to you. You can remove any of them or add a lot of different and cool functionalities as you please. For example, you can go into the github marketplace and add Telegram or mailing alerts, testing suites, and so on.

The next time you make a commit, or merge a PR into your specified branch or manually run the build, you should be getting the following result.

And that's it!! easy right?  You will be delighted as you keep learning the extensive tools that github actions has. One extra point that github actions has is: if your repo is public, you are free of any charge!! cool right?

First let's enable read access from the github project to our Codeship project

Go to Codeship and:
- Create a new organization

- Create a new project in the recently created organization

- Connect your SCM. In this case we will choose github. You will receive an email that a new public key was added to your repository. In case it asks for permissions please allow.

- Select Basic Project

Now you should have a set of options inside of your project. Here comes the fun part.

It's a good idea to make a commit for the branch that you want to setup the trigger for. This makes Codeship refresh the build status.

If your project requires any build commands or tests, this is the place where you can set them up. It is important to say that the commands that you write will run in a virtual environment (container) that is created in Codeship servers, not your actual deployment servers.

In this case we are using the I want to create my own custom commands option and will be adding the following inside the setup part:

For now we are not going to set up any tests so we can leave it as it is.

Next, let's go to the Build triggers option. Depending on your requirements, you can change the following options. This is the way we have it set up for now.

Now, let's go to the deploy option in our project menu. We are going to set up the branch that will trigger our build. In this case I am selecting the master branch but you can choose any deployment/branches you want.

Let's choose the Script option and as an example I will input the following:

#Custom Script #
# Deployment pipeline commands
# Sync files in my custom theme rsync -avz -e "ssh" ~/clone/wp-content/themes/mytheme/ mysshuser@myhostip:/var/www/mywebsite/wp-content/themes/mytheme`

These commands will basically do a sync from the recently Codeship-generated artifacts in the mytheme directory and will sync with the one in your deployment server.

NOTE: This is the most important step, because you will be making direct changes to your production/staging/dev server. It is recommended that you double check the specified directories in the custom script.

Last step for our quick tutorial: Add the Codeship public key to your deployment server.

- Go to General option in settings
- Copy the provided SSH key into your EC2/Droplet/server
- Copy the generated key to the "authorized_keys" file in your .ssh directory in your server. If no .ssh directory or authorized_keys exist you will have to generate them.

Now, it's time to watch the magic happen and we can sit back and relax after any push that we do to our triggered branch. Each time you merge or make any change to your branch, the trigger will build and deploy to your configured server.

I hope this guide was helpful to you. If you have any questions please feel free to contact me. You can find me at telegram as @Sshaman, or twitter as @pepolong.

Also please listen to my band, Rodeo Radio!!