I finally set up a continuous deployment (CD) server for Ducky Guidance. I decided to use Jenkins since we already have a Windows Jenkins server for our Sitecore projects.
Setting up the project
Build task and RVM
Since we use RVM for our development and production enviroments, I
installed RVM for the Jenkins user. Then I set Jenkins to use
/bin/bash for shell commands. I created a .bashrc file to load RVM.
With that, I was ready to create the build step for our project.
The build task
source ~/.bashrc # Loads RVM cd . # Loads the RVM environment set in the .rvmrc file cp ~/duckyg-database.yml config/database.yml # Copies the database.yml locally bundle install # Installs gems rake db:schema:load # Loads all the database schema rake # Runs RSpec and Cucumber
I use the source ~/.bashrc line to load RVM for the build task. After
that, I use cd . to load the Ruby version and gemset we use for Ducky
Guidance.
Since I made sure to not store our database.yml in our git repository,
I created one in the Jenkins user home folder. I copy it from the
Jenkins user’s home directory with every build.
The rake db:schema:load and the bundle install commands ensure that
all the migrations are loaded and all the gems are installed. From
there, we can call rake, which will call RSpec and Cucumber.
RSpec & Cucumber HTML Formatted output
RSpec and Cucumber both have HTML results formatters. Since Jenkins will serve up HTML output, I thought it would be useful to have both tools output their results to an HTML file in the workspace. That way, I can quickly scan the full color, formatted HTML instead of digging through the console output. To accomplish this, I have to call RSpec and Cucumber separately, so that I can redirect their outputs to separate files.
It was easy to tell Cucumber to use the HTML formatter, as Cucumber
looks at the CUCUMBER_FORMAT environment variable. I added the
following line to my build task:
CUCUMBER_FORMAT=html rake cucumber > jenkins/cucumber.html
RSpec looks at the SPEC_OPTS environment variable, so you can call
RSPEC in a similar way with the following line:
SPEC_OPTS="--format html" rake rspec > jenkins/rspec.html
My build task now looks slightly different than it did when I first set up the project:
source ~/.bashrc cd . cp ~/duckyg-database.yml config/database.yml [ -d jenkins ] && rm -rf jenkins mkdir jenkins bundle install > jenkins/bundler.txt rake db:schema:load > jenkins/schema_load.txt SPEC_OPTS="--format html" rake rspec > jenkins/rspec.html CUCUMBER_FORMAT=html rake cucumber > jenkins/cucumber.html
As you can see, I decided to redirect the rake db:schema:load and bundle install
commands to files as well. I stored all the files in a jenkins folder
in the workspace group the output of the various commands called in my
build tasks. I also added a link to the jenkins folder in the
workspace to my job description, so that I can easily get to the output
files when I view the job.
Capistrano
So far, I have Ducky Guidance set up as a Continuous Integration project. It is testing the project with every new commit, but it is not deploying it. The next step was to add another build task which would call Capistrano after all the RSpec and Cucumber tests passed. The contents of that build task are below:
source ~/.bashrc cd . cap development deploy:migrations > jenkins/deploy.txt curl https://demo.duckyg.com --insecure > /dev/null
I use curl to warm up the app after it is deployed, so the first person to
visit the site is no longer penalized with longer load times.
Before using Jenkins for deploys, I was invoking capistrano locally. I
was utilizing SSH Agent Forwarding for authenticating code fetches on
our staging and production servers. So when I used the above build task
initally, it was erroring out when git would fetch the code. It seems
that the way that Jenkins invokes shell commands prevents ssh from
respecting the .ssh/config settings. To solve the problem, I created
an SSH key on my deployment targets. Now capistrano uses the private key
on the staging and production servers to authenticate git commands.
Conclusion
It wasn’t too hard to fit Jenkins into my workflow. There were a couple of hiccups (like explicitly loading RVM, and placing SSH keys on our staging and production servers), but no show stoppers.