Continuous integration with Drone
Installing a Drone continuous integration (CI) Ubuntu 14.04 server.
Drone is a continuous integration server with a fully hosted version which you can self-host as well. We gave it a spin for our Rails application: RSpec integration tests with some PhantomJS stuff.
Base
We started off with an Ubuntu 14.04 LTS base image on a 1.6Ghz CPU system with 1GB of RAM and a 10GB drive running on Google Cloud. As always, upgrade the system:
apt update
apt upgrade
See the new apt syntax? Since version 1.0 `apt-get` and `apt-cache` have been merged in a single interface (you even get some nice colours and a progress bar).
Firewall
Let’s lock the system down a bit by enabling the firewall via UFW.
ufw allow ssh
ufw enable
You can lock yourself out if you are not allowing SSH connections, check to see if you can still log in.
Disable root access
Edit `/etc/ssh/sshd_config` and disable the root login.
PermitRootLogin no
Restart the SSH daemon.
service sshd restart
Automatic updates
Set up automatic updates. This will tell Ubuntu to look for and install security patches every so often, not a luxury as you probably won’t log in to the CI server daily.
dpkg-reconfigure --priority=low unattended-upgrades
apt-config-auto-update
Make sure the `update-notifier-common` package is installed (it was for me) and edit `/etc/apt/apt.conf.d/50unattended-upgrades` to make the server reboots when it needs to.
Docker
Let’s install Docker. Bonus hipster points.
curl -fsSL https://get.docker.com/ | sh
A quick hello-world will show if Docker was installed correctly.
docker run hello-world
Drone
Drone needs a database to store its things. I went with SQLite as it’s super easy to install but PostgreSQL or MySQL are probably better suited for production systems. Drone doesn’t mind and can run with MySQL, PostgreSQL or SQLite.
apt install sqlite3 libsqlite3-dev
Now you can tell Docker to fetch the latest Drone image (0.4 at the time of writing):
docker pull drone/drone:0.4
Let’s configure Drone:
mkdir /etc/drone
vi /etc/drone/dronerc
Add Github as a remote driver: get the client id and secret from a developer oAuth application created on Github and point it to the database.
REMOTE_DRIVER=github
REMOTE_CONFIG=https://github.com?client_id=CLIENT&client_secret=SECRET
DATABASE_DRIVER=sqlite3
DATABASE_CONFIG=/var/lib/drone/drone.sqlite
Once done you can run Drone:
docker run \
--volume /var/lib/drone:/var/lib/drone \
--volume /var/run/docker.sock:/var/run/docker.sock \
--env-file /etc/drone/dronerc \
--restart=always \
--publish=80:8000 \
--detach=true \
--name=drone \
drone/drone:0.4
There you go, open your browser a point it to the server’s IP address. Drone will do its oAuth dance with Github when you log in and list your repositories.
Build
Drone looks for a `.drone.yml` configuration file in your project’s root directory. You start from a Docker image of your choosing, run some commands and wait for Drone to tell you if everything works.
build:
image: cimm/ruby-phantomjs
environment:
- RAILS_ENV=test
commands:
- bundle install --without production --without staging
- cp config/database.drone.yml config/database.yml
- bundle exec rake db:create
- bundle exec rake db:test:prepare
- bundle exec rspec spec
compose:
database:
image: postgres
notify:
slack:
webhook_url: $$SLACK_WEBHOOK
channel: general
username: drone
The first ‘build’ part is the most important one. You can use whatever Docker image you want as a base to start from. We built our own as we need a more recent version of PhantomJS to run our tests.
The ‘commands’ section is where you configure your build and get it running, pretty standard Rails stuff here.
The ‘environment’ section can be used to set… well… environment variables. Useful for twelve-factor apps.
The ‘compose’ section behaves like Docker’s compose feature and lets you pull other Docker images needed for your build. Isn’t that awesome?
And finally, the ‘notify’ section to let everyone know how good of a tester you are.
Secrets
Noticed the $$SLACK_WEBHOOK variable in the example? It’s possible to pull in variables from a `.drone.sec` file from your project’s root folder. This is useful for API tokens & passwords you rather don’t expose.
Drone knows how to read and decrypt this file but you’ll need to encrypt it yourself. Go to your project’s “Secrets” tab in the Drone web interface and add your variables.
environment:
SLACK_WEBHOOK: https://hooks...
Generate and save the encrypted version in the `.drone.sec` file. Save, commit, push and watch Drone do its magic.