Continuous Integration with Jenkins, git and psake

Right now, I’m using a Continuous Integration (CI) setup consisting of:

  • A Jenkins CI server, running on a Rackspace Ubuntu 12.04 server
  • git source control, backed by a github project
  • .net projects, with psake build scripts
  • Windows 7 build machine

Here are a few take-aways:

Windows slave

  • Use labels to identify a build machine as a Windows machine.
  • Since my build machine isn’t accessible from the Internet, I used Java Web start to get started and install it as Windows service from the UI [7]. Note you might want to run the `javaws … ` from a command prompt with elevated privileges to be able to install a Windows Service.
  • I configured the Jenkins Slave service to log on as dedicated user on the build machine that has all the build paths and ssh keys set up to work with my bot account on Github [8]
  • Don’t forget that your slave has to give consent to restore missing using NuGet [9]; id did this by setting the EnableNuGetPackageRestore environment variable to true.
  • Install the Windows (7/8/…) SDK
  • You might need to copy some build targets from C:Program Files (x86)MSBuildMicrosoftVisualStudio, or alternatively install Visual Studio on your build server (now WHO would want to do THAT?).

git & Github

  • Authenticate using https, make sure you can connect WITHOUT entering credentials. I did this using gitextensions, which stores the credentials in the Windows credential cache.

  • Or install using SSH:

    • On your build slave, set up an ssh key pair that doesn’t require a pass phrase.
    • The first time, connect manually from the command line [5].
    • Run the slave service as a user that has a ssh key pair setup for the git repo.
    • Check from a command window that your git client is properly set up. You should be able to do ssh -T git@github.com and git clone git@github.com:<user>/<repo>.git without any additional key strokes.
    • When setting up your Windows slave, you might find Thomas’ blog post [6] useful.

psake

  • Don’t forget to set the PS execution policy to RemoteSigned on your build slave.
  • When using the Jenkins PS plugin, use the psake.ps1 helper script with $psake.use_exit_on_error = $true [1]. This to make sure the build script exits with an exit code not equal to 0 in the case of build errors. I didn’t get this to work; not sure why. So …
  • Instead of using the Jenkins PowerShell[#PSPLugin]_ plugin for executing psake build scripts, I used the psake.cmd deployed with psake. By default, psake.cmd bypasses the execution policy, so you might not want to do this.

Footnotes

[1]https://github.com/psake/psake/wiki/How-can-I-integrate-psake-with-Hudson%3F
[2]http://matosjorge2013.wordpress.com/2010/07/27/how-to-integrate-psake-with-hudson/
[3]https://github.com/psake/psake/wiki
[4]https://wiki.jenkins-ci.org/display/JENKINS/PowerShell+Plugin
[5]https://help.github.com/articles/generating-ssh-keys
[6]http://blog.thomasvandoren.com/2011/09/jenkins-windows-slave-with-git/
[7]https://wiki.jenkins-ci.org/display/JENKINS/Distributed+builds#Distributedbuilds-LaunchslaveagentviaJavaWebStart
[8]https://github.com/serra-bot
[10]http://ferritedog.wordpress.com/2011/05/27/1-hour-guide-to-continuous-integration-setup-jenkins-meets-net/
[11]https://wiki.jenkins-ci.org/display/JENKINS/NUnit+Plugin
[12]https://wiki.jenkins-ci.org/display/JENKINS/xUnit+Plugin
[13]https://wiki.jenkins-ci.org/display/JENKINS/HTML+Publisher+Plugin