The SPA conference website deploys to production automatically on merge to master. It is on shared hosting, and setting this up with Travis was a bit tricky, so I’m blogging how I did it in case it’s useful for others.
Configuring Travis to deploy automatically on merge to master is pretty straightforward if you’re using a supported provider. However, if you’re using shared hosting, the documentation is not amazing.
I figured it out eventually by juggling between a blog post (this one is useful for explanations of how Travis works but less so for step-by-step), the actual config that person uses, another blog post (useful for some of the steps), the Travis docs on encrypting files, custom deployment and the build lifecycle, and yet another blog post (very useful for the actual config, but for a different set-up than I wanted).
That juggling made me think my addition to the genre was worth it.
Create a .travis.yml
file. The inital one can just have the language and how to build the site.
language: ruby
rvm:
- 2.3.3
script: scripts/build.sh
branches:
only:
- master
You can tell Travis how to build the site inline, or call out to a build script as I have done.
#!/bin/bash
set -e
bundle exec jekyll build
The build script has to be executable (chmod +x 600
).
gem install travis
), and, using the command line tool, encrypt any variables that you will use for deploy. For example, if you use FTP, you will want to encrypt at least the password.
travis encrypt SOMEVAR="secretvalue" --add
The --add
flag in this command adds the required lines to your Travis file.
Write a deploy script: a script that describes the steps you take to deploy to shared hosting. For example, if you use FTP, then write the command that you would use to FTP the built site to the server. Instead of the variables you have encrypted, use SOMEVAR
.
I use Rsync to deploy, and have encrypted the username and deploy host. You can see the deploy script on GitHub.
This also needs to be executable.
Create a dedicated SSH key (no passphrase) for deploying. This makes it easy to to identify and revoke if necessary.
ssh-keygen -t rsa -b 4096 -C '[email protected]' -f ./deploy_rsa
Log in to command line Travis (travis login
) and get Travis to encrypt the private key file. It prints a helpful output reminding you to only commit the .enc
version NOT the deploy_rsa
itself.
travis encrypt-file deploy_rsa --add
Again, the --add
flag automatically adds the required lines to your Travis file.
Commit the changes to .travis.yml
and the deploy_rsa.enc
.
Copy the public key to the remote host.
ssh-copy-id -i deploy_rsa.pub <ssh-user>@<deploy-host>
rm -f deploy_rsa deploy_rsa.pub
In the before_install
, change the out
location for the decrypted private key to /tmp/
so it doesn’t end up in any of the publically accessible directories, and make it executable.
before_install:
- openssl [snip...] -out /tmp/deploy_rsa -d
- chmod 600 /tmp/deploy_rsa
In the same section, start the ssh agent and add the key to it.
- eval "$(ssh-agent -s)"
- ssh-add /tmp/deploy_rsa
Get .travis.yml
to call the deploy script.
This is an example of how the Travis docs could be clearer. You don’t want to deploy if the build script fails, so you might want to call this in an after_success
step as part of a script deployment, but in fact, this will do whatever you ask after every successful build. But in our case, we only want to actually deploy on merges to master, not on any successful build. For example, if we’ve just opened a PR and that builds successfully, we don’t want that branch deployed to production.
So what we actually want is custom deployment.
deploy:
provider: script
script: scripts/deploy.sh
skip_cleanup: true
on:
branch: master
skip_cleanup
is required because otherwise Travis resets the working directory, so you lose the artefects from the build (i.e. exactly what you want to deploy!)
The full travis.yml
we’ve now created looks like this:
language: ruby
rvm:
- 2.3.3
script: scripts/build.sh
branches:
only:
- master
env:
global:
- secure: qvSoY270qAXOtmWdRio9vvhLEf5HHdyzMS39yS4yZw74[snip for length]
- secure: Hr7FV7lHFEblYfn7EYM/4qV3qV8zdHLebXzNyRvP8L/U[snip for length]
before_install:
- openssl aes-256-cbc -K $encrypted_ed2cb1b127e1_key -iv $encrypted_ed2cb1b127e1_iv
-in deploy_rsa.enc -out /tmp/deploy_rsa -d
- chmod 600 /tmp/deploy_rsa
- eval "$(ssh-agent -s)"
- ssh-add /tmp/deploy_rsa
deploy:
provider: script
script: scripts/deploy.sh
skip_cleanup: true
on:
branch: master
This (allegedly deprecated but still working) travis.yml
linter is useful.
Have a look at the SPA website Travis file and the builds if you’d like to know more about how it works for us.
Useful commit for future reference is the creating/encrypting SSH key one.
If you’d like to be notified when I publish a new post, and possibly receive occasional announcements, sign up to my mailing list: