3 min read

Deploy Wordpress using Trellis & Circle CI

Overview

The following assumes the use of Trellis and Circle CI being deployed to a Digital Ocean droplet. This will focus on Circle CI and not about setting up Trellis or Digital Ocean.

  • Generate a GitHub repo deploy key with Circle CI
  • Add local SSH private key to Circle CI
  • Add Ansible vault password as an environment variable
  • Add tags to deploy tasks so they can be ignored
  • Configure Circle CI machines with circle.yml file

Generate a GitHub repo deploy key with Circle CI

Circle CI can create a deploy key automatically under Project Settings → Checkout SSH Keys If there are multiple private repositories needed as dependencies then it’s best to either create a machine user or authenticate and give Circle CI user level access.

Add local SSH private key to Circle CI

When deploying or provisioning to a server from a local machine with Trellis, the local private key is matched to the public key in the authorized_keys file on the server. Since the Circle CI build machine is now taking the place of the local machine, it needs to have the same local private key. It might be best to generate a new key specifically for this purpose but SSH permissions between both servers & GitHub can be overly complex.

Add Ansible vault password as an environment variable

Ansible Vault needs a password to decrypt files but the .vault_pass is kept outside of version control. In this case one needs to be created at build time by adding a custom environment variable and echoing it to a file once Circle CI has spun up.

echo "${ANSIBLE_VAULT_PASSWORD}" > . vault_pass

This is done in the circle.yml file below after changing into the Trellis directory.

Add tags to deploy hooks so they can be ignored

There is some duplication that goes on during this configuration. Before tests are run, the build is compiled using Gulp + NPM. There’s no sense in compiling, running tests, then compiling again when trying to deploy. But at the same time it’s necessary to have all the tasks in place to be able to compile locally.

Adding tags to the tasks in the before-build.yml playbook overcomes this by simply telling Ansible to skip tasks with the tag that’s passed in when calling the deploy playbook.

below is an exmaple of a build-before.yml playbook using Gulp to build the site.

- name: Run npm install
command: npm install
connection: local
args:
chdir: "{{ project.local_path }}/web/app"
tags: skip-using-ci
- name: Rebuild Node Sass
command: npm rebuild node-sass
connection: local
args:
chdir: "{{ project.local_path }}/web/app"
tags: skip-using-ci
- name: Run gulp
command: npm run production
connection: local
args:
chdir: "{{ project.local_path }}/web/app"
tags: skip-using-ci
- name: Copy project local files
synchronize:
src: "{{ project.local_path }}/web/app/themes"
dest: "{{ deploy_helper.new_release_path }}/web/app/themes"
group: no
owner: no
rsync_opts: --chmod=Du=rwx,--chmod=Dg=rx,--chmod=Do=rx,--chmod=Fu=rw,--chmod=Fg=r,--chmod=Fo=r
view raw build-before.yml hosted with ❤ by GitHub

Some of the tasks now have the tag skip-using-ci. When the deploy playbook is called, --skip-tags "skip-using-ci" can be passed in to, well, skip them.

Configure Circle CI machines

The environment under which everything will run can be configured using the circle.yml file that can be checked into version control. There are also override options within the Circle CI interface.

# Set the folder under which commands will be executed
general:
build_dir: site
# Configure the machine
machine:
timezone:
Europe/London
node:
version: 6.0.0
python:
version: 2.7.10
dependencies:
pre:
# Allow ansible playbooks to be run
- pip install ansible
# Turn an environment variable into a vault file that ansible can read
- cd ../trellis && echo "${ANSIBLE_VAULT_PASSWORD}" > .vault_pass
# This _should_ be inferred by Circle CI as we specify a node version but for some reason, it never ran for me. This tells it explicitly to run.
override:
- npm install
test:
# Again, this _should_ be inferred by Circle CI but wasn't.
override:
- npm run test
# Deployment Scenarios
deployment:
staging:
branch: staging
commands:
# This is just an ansible playbook command with some options to specify where the host file is located and that we want to skip tasks with the tag `skip-using-ci`
- cd ../trellis && ansible-playbook deploy.yml -e "site=example.com env=staging" -i hosts/staging --skip-tags "skip-using-ci" -vvv
view raw circle.yml hosted with ❤ by GitHub

It will probably work with Travis as well, not too sure about Jenkins. You can read about the challenges in a little more details over on Roots Discourse

Posted