The CF Webtools tag line is "You Dream it We Build it", including SVN servers.

Keeping it in house
CF Webtools has been using it's own task and project tracking system for years. Over this time it's grown. It keeps track of clients, hours of dev work, hours paid by clients, projects, project tracks/tasks and a lot more. It does what CF Webtools needs and it will be expanding as more needs come up. But it does not integrate with anything (or it didn't used to). We also run our own SVN server as well as numerous development and staging servers. All needed to maintain the clients dev/staging sites for ongoing work.

Mark Kruger, aka. ColdFusion Muse believes in keeping these services in house as much as possible. I know people will argue the cost of do it yourself, verses someone hosting it for you. But, there are other reasons being considered as well. We're keeping it in house. However, it finally came to a point where we needed a better SVN system and some integration.

Hudson CI
Mark had already setup Hudson CI and we are using it to handle publishing code to development and staging servers. We also have a few sites that use Hudson CI for publishing to production.

New SVN server with F/OSS web tools
In a previous blog post I mentioned that I was given the chance to build a new SVN server for CF Webtools and I jumped in headfirst. I really enjoy getting into sysadmin mode. In the process I upgraded CF Webtools from SVN 1.4.x to SVN 1.6.x and included Submin and WebSVN interfaces to help us manage the repositories. I also connected the SVN to the Hudson CI server that Mark setup so if we choose to do so for a project, each SVN commit will trigger, via a post-commit hook, the proper Hudson job and build the code on the dev/staging server automatically.

view plain print about
1#post-commit hook for hudson ci
2
3REPOS="$1"
4REV="$2"
5UUID='svnlook uuid $REPOS'
6/usr/bin/wget \
7 --header "Content-Type:text/plain;charset=UTF-8" \
8 --post-data "'svnlook changed --revision $REV $REPOS'" \
9 --output-document "-" \
10 --timeout=2 \
11 --quiet \
12 http://hudson.servername.com:620/job/build_project_name/build?token=someIdYouCreate &>
/dev/null
13
14exit 0

We did more than just use these tools as-is. The WebSVN pretty much still is as-is only with a minor tweak to display the full SVN url so our developers know what URL to put in their SVN clients. Submin however needed a bit more tweaking. The version we are using does not create everything that is needed to create a repository. The part it missed was the Apache config. I realize that in many cases the Apache config is different from server to server or Linux flavor, so that part may be a pain to do. Not having to worry about other servers, just ours at CF Webtools, I went about tweaking the Python code. This was my first time ever seeing Python code which means my hacks at Submin are down and dirty. I decided to not try to parse Apache config files, but use the fact that Apache can include config files based on wild cards.

The base virtual host section for the subversion server has the settings for everything the SVN needs, but I stripped out the blocks and put them into their own files in the same folder Submin uses to write to and update the permissions files. This way each Repository has it's own config file that gets created on the fly and can easily be deleted if the repo has to be delete. (We try not to have to delete repos.) The next hurdle was reloading the Apache config. I found this to be harder than I expected and didn't really find anything to help me. The Submin code does not run with sufficient privileges to reload Apache. So, the next best thing is a Bash script and CRON. Every 5 minutes CRON runs a Bash script that checks the SVN config folder where the config files are stored and if a new file exists, it reloads apache.

view plain print about
1#!/bin/bash
2
3# submin svn conf folder
4
5CONFFOLDER='/var/lib/submin/conf/'
6
7LASTFILE=`ls -tr $CONFFOLDER *.sh |tail -1`
8
9FILEDATE=`stat -c %Y $CONFFOLDER$LASTFILE`
10
11NOW=`date +%s`
12DATEDIFF=$((NOW-FILEDATE))
13
14if [ $DATEDIFF -lt '300' ]; then
15 ISGOOD=`/sbin/service httpd configtest`
16# if [ `echo $ISGOOD || grep 'System OK'` ]; then
17 RELOAD=`/sbin/service httpd reload`
18# fi
19fi

"Hooking" it all Together
Mark must have been feeling left out of the fun, so he decided to secretly tie the in-house tracking system to the SVN. Previously, I had figured out a post-commit hook to trigger a Hudson CI job. Mark said "Hey! I can do the same thing and send the SVN commit info to the in house tracking system." He spent all of his 4th of July weekend coding an API into the system. We both spent some time on the hook and debugging the http issues, but he got it working. Deciding he also wanted to play with Python, Mark went about customizing the Submin a couple steps further. Now when a new repository is created the pre and post commit hooks we use by default are copied into the hooks folder and the base SVN folders; trunk, branches and tags are added to the repository by default.

The end result is that it is super easy for any CF Webtools developer to setup new client in our SVN server. No more command line VIM and manually editing Apache config files and using the $> svnadmin command to create a repo. They now just use this Submin web interface and create a new repo then import the new clients code.

When we are working on code and are ready to commit the code, we use any SVN client and commit the code with a comment that follows a very simple format.

view plain print about
1track:nnnnn
2hours:
3[notes]
4Comments about the code and what you did.

This is the basic template, but there are options for more information such as admin notes or type of task and a few other items specific to our tracking system.

Fully Operational SVN, Publishing and Tracking System
Upon successful commit the code is pushed to the staging (or production) server by Hudson CI and our tracking system gets updated with the same SVN notes so everyone including the client can see work is progressing. No more double entry of notes. No more having to FTP code manually or copy code across a network mapped drive. And best of all, no more having to figure out which dev or staging server the clients code is being tested on (we have several of these servers) Hudson publishes the code to the right place.