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 |
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 |
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