All of your source code is in your version control system, but what about your build environment?
If your development machine crashed, would you be able to recreate your build environment?
Do you dread the thought of bringing on another developer?
You won't have these issues if you use Vagrant to create portable, reproducible build environments.
Vagrant is essentially a wrapper for VirtualBox to make it easier to configure, manage and interact with virtual machines. We can use these virtual machines to create build environments which can be easily saved and consistently reproduced.
With Vagrant -- instead of giving you a bunch of instructions to install and configure the project dependencies -- I can just give you a Vagrantfile and a provisioning script. And, it doesn't matter what OS you're running. Here's how:
- Download my Vagrantfile and provisioning script to some folder on your machine (or clone my GitHub repo). Don't let your system rename the files or add extensions, the should be named
- Open a terminal/shell and run
vagrant upfrom the folder where you downloaded the files. Note that the first time we bring up the machine it will take a little while. This is because Vagrant needs to do an initial download of the entire base box image and run the provisioning script.
- You now have a virtual build machine running. Use
vagant sshto log in to it. You are now in the
- The example project was downloaded to
/vagrant/try-tdd-with-ceedling. Switch to this folder with
rake test:allto run the project unit tests from the example.
That's it. That was pretty easy, right? Lets look at what we did there in a little more detail.
Vagrant uses a Vagrantfile to define how each virtual machine is configured. This is plain text file which is easily stored in version control. Here's ours:
# -*- mode: ruby -*- # vi: set ft=ruby : # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| # Use Ubuntu 14.04 64-bit. config.vm.box = "ubuntu/trusty64" # Run the provisioning script. config.vm.provision :shell, path: "provision.sh" # Fix for VirtualBox and Ubuntu losing internet connection. config.vm.provider "virtualbox" do |v| v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] v.customize ["modifyvm", :id, "--natdnsproxy1", "on"] end end
Vagrant configurations are specified by starting with a "base" Vagrant box. This is the starting point for the system and generally represents a clean install of some operating system. In this example we're using the
ubuntu/trusty64 base box, which is Ubuntu 14.04 (64-bit).
Then this Vagrantfile specifies that we should run the
provision.sh script to provision the box. Provisioning is an operation executed by Vagrant from inside the virtual machine after it is first created. Ours is just a bash script that installs our build environment dependencies:
#!/bin/bash # This is the provisioning script which is executed when the virtual machine is first created. # Here is where we install all of the dependencies for our project. # Configure the machine to switch us to the shared folder immediately upon login. printf 'cd /vagrant' >> /home/vagrant/.bashrc # Rake is a dependency for projects built with Ceedling. apt-get -y install rake # Some other tools we might want to use in the future. # apt-get -y install doxygen # apt-get -y install splint # apt-get -y install pandoc # Developer tools. apt-get -y install git # apt-get -y install subversion # Get the test repository used in this example. cd /vagrant git clone https://github.com/ElectronVector/try-tdd-with-ceedling.git
Ruby is included with this Ubuntu image, so the only critical dependency is Rake. It gets installed with the command
apt-get -y install rake.
Git is installed for source code revision control, and there are a few other tools referenced that might be useful in the future.
The last thing the script does is to pull down my example code from GitHub.
Also note that Vagrant creates a shared folder between your host and the virtual machine. By default, the virtual machine
/vagrant folder is shared with the host folder containing the Vagrantfile. So, you should be able to see the
try-tdd-with-ceedling source from your host.
This means that you can build with Vagrant inside the virtual machine and still use your favorite editor on your host machine.
There are other Vagrant commands we can use as well. To exit the ssh session, just use
vagrant suspend to suspend the machine or
vagrant halt to shut it down. The same
vagrant up starts it again from either state.
In summary, Vagrant is a way automate the creation of a build environment. We take our build environment and define it in a way that we can easily distribute it to anyone... or save it for just in case.
With a little effort up front, it's just one less thing we'll have to worry about during development.
For more information, see the Vagrant "getting started" documentationn.