Ayende @ Rahien

Refunds available at head office

How do you deploy

After suffering the agony of deployment (a deployment that took effort from the whole team, for a looong time), I decided that I really believe in automated deployment. Not just a build script or continious integration, but automatic deployment.

I just recently finished documenting the deployment tactic (which I still consider flawed) in the current project. It goes like this:

  • Verify that (all of it was missing when I first tried it):
    • The machine has .Net 3.0 and IIS
    • That you have a database server
    • That IIS is running
    • That ASP.Net 2.0 is the registered on IIS
  • From the machine you deploy to:
    • Run>Start>CMD
    • cd \
    • md ProjectName
    • cd ProjectName
    • \\tools-srv\subversion\svn co svn://subversion/ProjectName/trunk .
    • msbuild default.build /p:EnableTest=False /p:ConnectionString="Data Source=..."
      /p:VirtualDirectoryName="ProjectName" /p:RebuildProdDatabase=True
    • Wait...

It is flawed because I need to log on to the destination machine, and it is more than a single step. Ideally, we would be able to do it with a single command. The effort pays off the moment I able to push new changes to staging and QA in a matter of minutes.

Comments

Colin Ramsay
03/16/2007 04:34 PM by
Colin Ramsay

I have my build server send a zip of each build that succeeds up to the deployment server. The zip is named after the subversion revision that triggered the build. To deploy I jump on the server and type "deploy xxx" where xxx is the revision number, and that handles everything.

I'm sure I could do that last step from a remote shell somehow (WMI?) but it's no trouble for me to log on.

http://www.colinramsay.co.uk/2006/12/13/my-deployment-process/

Andreas Öhlund
03/16/2007 06:57 PM by
Andreas Öhlund

"TFSDeployer" solves this in a nice way, in short:

A service on the target machine that monitors build status in Team Foundation Server. When status changes to some configured value the service downloads the build output and runs a powershell script.

Check it out here:

http://notgartner.wordpress.com/tag/projects/tfs-deployer/

Ayende Rahien
03/16/2007 07:01 PM by
Ayende Rahien

Sorry, I am not talking about continuous integration, I use CC.Net for this.

I am talking about "pushing to production".

Jeff Brown
03/16/2007 08:04 PM by
Jeff Brown

In our case the CI build server produces a ZIP file containing the build image. Then we run a command on a master deployment machine which pulls the latest build ZIP (or a specified version) and uses the WSHController COM object to fire off commands on the individual servers to deploy that version, also providing additional information about the environment.

I wrote a prototype batch deployment tool using Ruby on Rails two weeks ago which will eliminate the step of remoting into the master deployment machine. This needs to be under partial manual control because we use the same process in production, so it's not just for CI.

The CI integration deployment is much simpler. The CCNet instance on the build server fires a message over to force the CCNet instance on the integration server to deploy the latest build image and run the tests. Pretty simple.

The remote deployment trick with WSHController has worked fine for 5 years. Unfortunately we started having reliability issues with WSHController which occasionally crashes or hangs (apparently due to a buffer overflow in its handling of environment variables). Yesterday I spend 2 hours rewriting the remote deployment script to use PsExec instead. Then I spent 14 hours trying to figure out why it also crashes (C0000409) or hangs (when its output is redirected to a pipe). And today I've spent a couple more hours. It really makes me wish we were just deploying to a Unix environment via SSH! I'm left wondering which patch, upgrade, or service pack might have caused my current woes.

So... now I'm going to take a break, take a walk, try to do something about my sinus headache and get down to working on MbUnit v3.

Andreas Öhlund
03/16/2007 09:39 PM by
Andreas Öhlund

I don't see why a "TFSDeployer"-like solution can't be used to deploy to production.

  1. Install the service on your production machine(s)

  2. When a build quality is changed to "production" (i don't know of CruiseControl have the notion of "build qualities") the service will download the build-output and execute the powershell script associated with "production" on the specific server.

(TFSDeployer is not about CI, we are using "TFSIntegrator" for CI)

Ayende Rahien
03/16/2007 09:46 PM by
Ayende Rahien

What you describe is a CI process. Watching the source repository and running a script when it changes.

Part of the CI process in your case is to deploy to a server.

I am not sure that I would want production deployment to happen just because I changed something. I would want to start the process manually. (And sure as hell the first step of this script is going to be a full backup).

Bil Simser
03/17/2007 12:06 AM by
Bil Simser

I'm pretty happy with our process. We build Smart Client apps using the CAB framework along with some other 3rd party tools. Took me a few tries and lots of pain but finally came up with a combination of NAnt tasks and an MSBuild script and some additional files but it's now one command line option:

tools\NAnt\Nant.exe deploy-XXX

where XXX is localhost, QA, UAT, or Production.

It syncs up with a configuration in the solution for each environment (which will pull in the appropriate settings and connection string files for each environment).

Used to take 4 hours to deploy, takes 5 minutes now.

Luke Melia
03/17/2007 03:05 AM by
Luke Melia

You might take a look at Capistrano in the Ruby on Rails world. It's a great solution for doing what you're after. If you're willing to install ssh and learn how to use it, it can be used for Windows deployments of non-Rails app. Or, it might just be good for inspiration.

Andreas Öhlund
03/17/2007 12:13 PM by
Andreas Öhlund

In TFS changing build quality is something that is done manually and can also be restricted to certain users so it's nothing that happens "automatically" and I can't see that it has anything to do with CI.

Eg. when the testmanager reports that all changes has been verified successfully in acceptance test the release manager will decide when it's appropriate to deploy to production. And at that time change the build quality to "Production" -> and there by starting the deployment. (which of course should start by backing up everything). But I agree that the most appropriate use for this is deploying the different test environments...

Just my 50 cents....

Marius Popescu
03/17/2007 12:49 PM by
Marius Popescu

Hi,

We're using a visual deployment tool called FinalBuiilder. It has lots and lots of actions you can use, lets you add your actions, it runs o Windows only, can get sources from a lot of source servers, can check .Net, IIS, start and stop services, install, start and stop COM+ objects, upload to FTP, send msn messages and use VisualStudio, Java or Delphi IDEs to build or compile projects and a lot of other stuff.

Plus, the editor is reaaaaly great, you can extract actions in a kind of procedure, you can surround groups of actions with try..catch - like actions, etc.

There is another benefit from using it, the build script can be printed and attached to project documentation, as a deployment procedure.

It costs about $400/$1000 depending on versions.

Try it for 30 days, we did it and never regret it.

Regards,

Marius

Jay Flowers
03/18/2007 07:59 PM by
Jay Flowers

I have had years of success with rcmd and rcmdsvc. They are Windows Resource Kit tools. Normally I copy a set of scripts to the remote machine and execute it with rcmd. The trick to rcmd is you have to pipe all the commands that you want to execute to it from a file. Like this:

rcmd \machinename <InstallCommands.txt

Hope that helps.

Jay

Josh Robb
03/23/2007 12:42 PM by
Josh Robb

Are you using web deployment projects for the msbuild task?

Comments have been closed on this topic.