I’ve been working on continuous integration and automated builds/deployment lately. I put together a MSBuild script that does a whole bunch of typical stuff including getting code from my repository, compiling, and running tests. I also want to create a Tag in my Subversion repository so I know which code was deployed. That wasn’t too hard to do either. The tricky part was that I want my build to fail if I try to make a Tag that already exists!
I fumbled around with this for a while trying a wide variety of ideas. In the end, it turned out to be pretty simple. There may be better ways to accomplish this, but here is how I am doing it…
I’m using the SvnClient task (it’s part of the MSBuild.Community.Tasks download) and executing a command: “ls $(SvnRepository)/tags/$(SvnTagName)”. Of course, my MSBuild script already has the variables $(SvnRepository) which is the path to my repository and $(SvnTagName) which is the name of the Tag I hope to create. You may have to tweak this stuff depending on the layout of your SVN repository. The command “ls” will actually list the contents of my Tag. Since I know my tag just has a few folders in it (it isn’t a recursive task), it isn’t too harmful if it succeeds. If the Tag does not exist in my repository, the command actually fails. Oddly, I actually want this task to fail! Yes, in my case, I am hoping the task does not find the Tag with the specified name. When the task is executed, it returns an ExitCode which is 0 for success or 1 for failure. Next I just check the returned code and if it is successful I generate an error. Sure this feels a bit odd. I don’t love using this kind of logic, hoping for an error to occur. I’d much rather have some subversion command I could execute to see if the Tag exists but I couldn’t find anything like that. Here is the actual xml from my Build file to check for the Tag:
<Target Name="CheckSvn"> <Message Text="*** Checking to see if the tag already exists"/> <!-- this task will look up the tag supplied. If it exists it will return a code of 0 Technically this is a success but for this instance, it is a failure because we don't want to find it! --> <SvnClient Command="ls $(SvnRepository)/tags/$(SvnTagName)" Username="xxx" password="xxx" ContinueOnError="true"> <Output TaskParameter="ExitCode" PropertyName="CommandResult"/> </SvnClient> <Message Text="*** ExitCode = $(CommandResult)"/> <Error Condition="$(CommandResult)=='0'" Text="This Tag already exists!"/> <Message Text="*** Finished Checking to see if the tag already exists"/> </Target>
Working with MSBuild is becoming a love/hate relationship for me. I really love the power of what you can do to automate tasks. But it can be a real pain to write, test, and debug these scripts. I hope my sharing this code will make your life a little easier.