If you haven’t heard the ThoughtWorks Go Continuous Delivery server is now open source. The source code is located on GitHub, https://github.com/gocd/gocd. I decided to give it a test drive and I was pleased. Since I am primarily a Windows developer my point of reference is CCNET (which is based on ThoughtWorks Cruise Control Continuous Build server), TFS Team Build and TeamCity. I don’t have a lot of TeamCity experience, but I can say that I can easily see automating many scenarios in Go that I was having a hard time conceiving in CCNET. Adding the concept of Environments, Pipelines, Stages, and User Roles opened an easier path to automated production deployment for me.
Install was pretty simple. Go is cross platform, but I have a Windows server. I downloaded the Windows packages from http://www.go.cd/download/. I installed the server and agent on my server, opened it up in a browser, and it was there ready to go. Very easy, only a few minutes of clicking and I was ready to start. Before I started building pipelines, I made a few customization for my environment. I want to use Git and NAnt in my build, test, deploy process so I added the path to their exe’s to the Path (Windows system environment variable). This makes it less painless to run them from Go.
Server User Authentication
I am eventually going to use LDAP for user authorization, but for now I setup an htpasswd file with usernames and SHA-1 hashed passwords. Then I entered the name of the file, htpasswd.txt, in the server configuration (Admin > Server Configuration > User Management > Password File Settings). I generated the contents for the SHA-1 hashed password file on http://aspirine.org/htpasswd_en.html, but I could have easily just used a Crypto library to hash the passwords myself. Usernames are not case sensitive, but you shouldn’t have colon, spaces or equal sign in the username unless you escape them with backslash.
The Go configuration is stored in an XML file, like Jenkins and CCNET. I know many people have a disdain for XML, but it doesn’t bother me and it makes Go portable. I can deploy it to another server or even a developer workstation, use a common config file, and its ready to start processing pipelines. You can use the UI to configure most of what you want to do, but I enjoy the fine grain control in editing the XML directly. There is an XML validator so when my error prone fingers type the wrong character it will automatically reject the change and continue using the current configuration. Since the configuration is XML, I decided to put the file under source control. The reason for this is to have a backup of the config and to allow the ability to config the server from XML and automatically push the changes to the Go server with the Go server (sweet). This doesn’t work both ways, so if there are changes made through the UI they won’t be pushed to source control (although I can envision some convoluted solution for this). For now, I am the only person managing the server and I will configure through the XML file and not the UI.
Pipelines are a unit of organization in Go. A pipeline is comprised of stages which is comprised of jobs which is comprised of tasks. Tasks are the basic unit of work in Go. In my instance most of my tasks are NAnt tasks that call targets in nant build scripts. There are all kinds of ways to create chains of actions and dependencies. This is going to probably be where I focus a lot of attention as this is where the power of the system lies, IMHO. Being able to customize the pipelines and wire up various dependencies is huge for me. Granted I could do this in CCNET to a certain degree, but Go just made it plain to envision and implement.
Working with Nant was a pain. Actually, this was the only major hurdle I had to cross. I couldn’t figure out how to pass properties to the nant build file. Then I decided to try to pass the properties through the target argument of the Go nant task, like this
<nant buildfile=”testcode\test\this-is-my-buildfile.xml” target=”-D:this-is-a-nant-property="dev" -D:another-nant-property="jun" ThisIsMyNantTarget” />
Note: Paths are relative to your Agent pipeline working directory.
This worked great, but a more intuitive way of doing this would have been good. Maybe an arguments property so there is no confusion between nant property and nant target.
I know this post is lite on details, but I just wanted to get a quick brain dump of my experience with Go. Go has pretty good documentation on the Go.cd website and posting questions to support elicited pretty fast feedback for a free product. I am excited to get involved with the Go and the Go Community. Overall, it was very easy to get a powerful Continuous Delivery server up and running in no time. You should check it out.