For my projects I make heavy use of Vagrant so that other developers can work in the same environment I am using. This also makes continious integration easier for your builds because you don't need to rely on a build machine becoming out of date or maintaining the correct packages, everything is managed in each VM.
This blogpost explains how I'm using Vagrant + Jenkins for continuous integration.
Jenkins Job
We don't use any of the Vagrant plugins for Jenkins (they seemed a little overkill) instead we just use this build script to boot up Vagrant and launch our build.
#!/usr/bin/env bash
vagrant up
vagrant rsync
vagrant provision
vagrant ssh -c "cd /vagrant; ./build.sh"
result=$?
vagrant suspend
exit ${result}
All that's really happening here is booting up the VM, provisioning it and then executing a build.sh
script from the project (this can be your equivalent build or test script). The VM is suspended at the end of the job to make bringup faster during the next execution. The error code is saved from exectuing the build script and Jenkins can correctly mark the job as failing or passing.
Modifying Vagrantfile to Make Use of Jenkins Resources
If you have dedicated Linux machines that are running your Vagrant based builds this additional tip may be of interest. We have a pool of servers that have lots more memory than our typical devleopment environments. We want the Vagrant VMs to make use of all those resources when they are running on our Jenkins servers, but not on our development machines.
Because a Vagrantfile is a ruby script, we can modify the Vagrantfile to gather information about it's environment before building the VM.
One assumption made is that Jenkins will always be running Vagrant based jobs under the username jenkins
. However, if your environment is different it should be easy to adapt, you just need a programatic way to determine you are running on Jenkins rather than a development machine.
The Vagrantfile basically checks what user is running the machine. If it is a user named jenkins
it determines the number of CPUs and amount of memory on the machine and grows the VM accordingly. The VM is also uses rsync for sharing content rather than VirtualBox shared folders, which perform poorly.
# -*- mode: ruby -*-
# vi: set ft=ruby :
require 'etc'
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64"
if Etc.getlogin == "jenkins" then
cpus = Etc.nprocessors - 1
# Get total memory by calling "free" command and parsing output
total_memory = %x(free -m).split(" ")[7].to_i
memory = total_memory - 1024
# Use rsync for syncing
config.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: ".git/"
else
memory = 1024
cpus = 1
end
config.vm.provider "virtualbox" do |vb|
vb.memory = memory
vb.cpus = cpus
vb.linked_clone = true
end
end
Overall, this is a pretty simple setup for Jenkins + Vagrant that doesn't rely on any plugins.