Saturday, June 27, 2015

Provisioning Buildbot with Vagrant and Ansible

Because the existing Buildbot documentation explains the manual installation process well enough, already, I'm just going to refer you to that if it's something you'd like to learn. What I provide, here, is an automated alternative that will quickly spin up a Buildbot master and slave through Vagrant and Ansible, so we can focus more on the configuration file and less on installation. If we do anything to compromise our configuration or environment, we can quickly reprovision.

Also, take note of the master directory. It contains a master.cfg file you can modify so that you're not always starting with a configuration from scratch. Just keep in mind that the Ansible task simply copies this file over. It doesn't create a shared volume. So when you make changes to your master.cfg file in the VM and want to keep your changes, make sure to copy them to this file before you reprovision the machine.

Prerequisites: Read up on Continuous Integration to get familiar with automated testing. You'll want to be familiar with setting up VirtualBox with Vagrant and Ansible. This guide was written for Mac OS X users.

I've opted to use Buildbot over other Continuous Integration solutions like TeamCity, Jenkins, and TravisCI, mainly because it has deep customization options, is used with Chromium, Mozilla, and other large software efforts[1], and it's free. Be warned, though. I've used this personally and implemented it at two different companies and it's more difficult to set up than most other CI solutions. Many members of the community would agree that the alternatives have a shallower learning curve[2]. Fortunately, I'm going to help make that set up process easier for you.

Provisioning Buildbot in a Local Environment

# clone the repo
git clone git@github.com:roblayton/vagrant-ansible-buildbot
cd vagrant-ansible-buildbot

# generate an ssh key in the ssh_keys folder
ssh-keygen -t rsa -C "myemail@domain.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/username/.ssh/id_rsa): ssh_keys/id_rsa

# spin up the master and slave
vagrant up

You'll want to add the public key you just generated in ssh_keys/id_rsa.pub to any github organization with the private repositories you need. Ansible will copy the private keys to all the slaves for you. If you'd like to learn more about SSH keys, head over to this article.

Note: Take a look at vars.yaml if you would like to know the locations of the buildbot master and virtualenv.

The Master Configuration

Editing the File and Restarting the Master

# ssh into the master node
vagrant ssh master

# edit and save the file
sudo vi /opt/buildbot/master/master.cfg

# check the config for errors
sudo /opt/buildbot/venv/bin/buildbot checkconfig /opt/buildbot/master

# restart the master with your new config file
sudo /opt/buildbot/venv/bin/buildbot reconfig /opt/buildbot/master

ChangeSources

This is where you can add extra sources, or repositories. The following configuration allows buildbot to poll for changes every 300 seconds, but you have the option to add hooks that react to commits, as well.

c['change_source'] = []

# example public repo
c['change_source'].append(changes.GitPoller(
        'git://github.com/buildbot/pyflakes.git',
        workdir='gitpoller-workdir', branch='master',
        pollinterval=300))

# example private repo
c['change_source'].append(changes.GitPoller(
        'git@github.com:[ORGANIZATION]/[REPO].git',
        workdir='gitpoller-workdir', branch='master',
        pollinterval=300))

Schedulers

Schedulers are responsible for telling the builder(s) when and where to run. Where going to have two builders for the Scheduler instead of the default runtests.

c['schedulers'] = []
c['schedulers'].append(schedulers.SingleBranchScheduler(
                            name="all",
                            change_filter=util.ChangeFilter(branch='master'),
                            treeStableTimer=None,
                            builderNames=["pyflakes", "repo"]))
c['schedulers'].append(schedulers.ForceScheduler(
                            name="force",
                            builderNames=["pyflakes", "repo"]))

Factories and Builders

Here, we have a builder for pyflakes and repo. Remember, repo is not an actual repository. I'm simply showing you how to create a builder for it if it were a nodejs project with tests that ran with the gulp test command.

# pyflakes 
pyflakes_factory = util.BuildFactory()
pyflakes_factory.addStep(steps.Git(repourl='git://github.com/buildbot/pyflakes.git', mode='incremental'))
# run the tests (note that this will require that 'trial' is installed)
pyflakes_factory.addStep(steps.ShellCommand(command=["trial", "pyflakes"]))

# repo
repo_factory = util.BuildFactory()
repo_factory.addStep(steps.Git(repourl='git://github.com/organization/repo.git', mode='incremental'))
repo_factory.addStep(steps.ShellCommand(command=["npm", "install"]))
repo_factory.addStep(steps.ShellCommand(command=["gulp", "test"]))

c['builders'] = []
c['builders'].append(
    util.BuilderConfig(name="pyflakes",
      slavenames=["example-slave"],
      factory=pyflakes_factory))
c['builders'].append(
    util.BuilderConfig(name="repo",
      slavenames=["example-slave"],
      factory=repo_factory))

Now, that you've made some changes to your master.cfg file, you're ready to run the builds. Make sure you run /opt/buildbot/venv/bin/buildbot reconfig /opt/buildbot/master to restart the master node with the changes. Read the next section to learn how to use the Buildbot GUI to run a build.

Using the Buildbot GUI

  1. Navigate to http://192.168.33.10:8010
  2. Login with the default username pyflakes and password pyflakes
  3. Click "Waterfall" in the top nav
  4. Click "runtests" and make sure example-slave is connected.
  5. Click "Force build"

Helpful Commands

Checking master.cfg

# check the config file for errors
/opt/buildbot/venv/bin/buildbot checkconfig /opt/buildbot/master/master.cfg

# or by running against the directory
/opt/buildbot/venv/bin/buildbot checkconfig /opt/buildbot/master/
Config file is good!

Copying the master.cfg file to the Host Machine

Before destroying or re-provisioning the buildbot virtual machines, make sure to copy all of your master.cfg changes over to the host. This allows Vagrant and Ansible to copy that updated file to the master VM the next time you spin it up. Run the following command within the vagrant-ansible-buildbot folder (on the host machine):

sftp vagrant@192.168.33.10:/opt/buildbot/master/master.cfg master/master.cfg

Reprovisioning

# run this from the host vagrant-ansible-buildbot folder
# teardown
vagrant destroy -f

# spin up
vagrant up

Some Details About Our Ansible Setup

We've done some interesting things with our Ansible configuration this time around:

  • Differentiates between master and slave nodes
  • Adds github.com to our known hosts rather than manually adding it in everytime we provision[3] or disabling host key checking[4]
  • Reuses the same private ssh_keys/id_rsa file
  • Reuses the same master/master.cfg file

The Buildbot User

If you ever need to log in as the buildbot user on one of the slaves, just run the sudo su - buildbot command.

Conclusion

Check back again to learn about how to provision a Buildbot cluster using Docker. For now, have fun creating your own configuration.

References:


No comments:

Post a Comment