Tuesday, February 24, 2009

PowerShell to save the day!

I have been doing a fair bit of build script stuff over the last couple of months. I guess it started when we were having big problems dealing with the build process at my last contract. (I had been using Nant for about a year prior but it never really did anything other than clean rebuild and run my tests. That's cool, it's all it need to do.)
We really need to look at our build process as it took about 3 hours to do a deploy, which we were doing up to 2 times a week…. 6 hours a week of a London based .Net contractor: that is some serious haemorrhaging of cash. I started really looking in to build server and properly configuring build scripts. As most places I work at are very M$ friendly and not overly fond of OSS, so I tend to be stuck with MSBuild if it is a shared script. So goodbye Nant.
Fast forward to a few weeks ago and I have moved country and company and am working with a great team of developers that are incredibly pragmatic and receptive to new or different ideas. We set up a build server and installed Jet Brain TeamCity to point at VSS and a basic MSBuild script that was a basic port of my Nant script. It worked, it did what we need, which was take what was checked in, rebuild, test and send a zip of the output to a network folder and let us know if the whole process succeeded or not. Simple and sweet.
Enter ClickOnce. Ahhh. Ok, so ClickOnce is a great idea in that it manages your companies deployments of smart client software. No longer do you have to worry if the users are using the correct version of your software, the latest will always be on their machine. Personally I think this is a great idea and can see why mangers would love the idea. Its also really easy to deploy… if you are using Visual Studio… and if you only have one deployment environment. Unfortunately I don’t want to use VS (I want to do this from a build sever using a potentially automated process) and we deploy to Dev, Test, UAT and Prod. MSBuild really struggles when it comes to this… it basically just cant do it.
The biggest problem was I need to be able to change assembly names so the ClickOnce deployments don’t get mixed up (I want o be able to install Test and Prod on the same box). Changing the exe assembly name in MSBuild changes all the assembly names, which is not too good.
After struggling with MSBuild I realised I was hitting the limits of what MSBuild is supposed to do, it was either change my approach or enter hack town.
Initially I thought Boo, Python or Ruby would be my saviours… then quickly rethought. Although they would be good in MY mind, other people have to use this and those options are not real M$ friendly… yet. I don’t know why I didn’t think of it earlier but PowerShell was the obvious answer. I downloaded PowerShell and after playing with it for a couple of minutes I was super impressed. All the stuff I was struggling with in my bat files or my MSBuild scripts were trivial in PowerShell.
Variable assignment, Loops, switches etc are all trivial. It extend .Net so you can handle exceptions, interact with Web service Ado.Net Active Directory… the sky is the limit.

Anyway if you haven't played with PS go download it, get the manual and get the cheats sheets


Cheat Sheets

And Check out PSake from James on codeplex if you are keen on incorporating PS into your build cycle.


NB: I hope to post my revised ClickOnce build strategy… as my last one was a bit of a failure, sorry if I lead anyone astray.

EDIT: Check out Powershell GUI if a nice free IDE


chnicola said...

Would be very interested to see your solution as I am almost exactly the same situation you were in.

I want to let this company keep their click-once deployment strategy if at all possible as they are very comfortable with it.

RhysC said...

Unfortunatley i can not post those scripts as there were written on compnay time, which mean they have company IP.
I can however explain what i did.
I have a PowerShell script that takes in the application name, display name and version (supplied by the build server).
The script does some checks (ie do files exist is the version in the right format etc). The powershell file calls an MSbuild file which does a basic build and test (using gallio) running my tests (unit integration etc).
Next it prepares the solution for staging. we push our versioned environemnt specific clickonce builds to a staging area so we have at any given time the dev test uat and prod version of the software. why? we are not a very mature department and this mean we have on the network share a back up and can quicly release application or push out a build toi the next environment quickly. this has work very well for us.
As we have 4 environments we loop thru this process 4 times.
Firstly we copy over the env specifc configs, then update the assembly info (uisng MSBuild Com ex tasks)
We then publish to the staging folder again using msbuild.
Ideally i will be pushing this to a PSake script for more clarity but it can/is easily done with naitve PS. its actually quite simple code, its just facilitating a process. Without a decent process then it doesnt mean much