Showing posts with label versioning. Show all posts
Showing posts with label versioning. Show all posts

Monday, 11 March 2013

Separate Build and Deploy Configs with Team City and MS Web Deploy

Finally, after a nearly two years of using the technique laid out in Troy Hunt's Blog Post, I've finally learned how to split out Building and Deployment into separate build configurations.

As in the extremely detailed post, up until now I've only been able to build and deploy in a single, immutable step. And to be fair, it's worked pretty well. Deployments have been relatively fast, predictable and repeatable. It never really bugged me until we had to create a new deployment internally that couldn't live in AppHarbor. This time, this configuration, it had to be right.

The reason having separate, distinct build and deployment steps in your deployment pipeline is a good idea is because it makes the your application build output a single atomic unit. The build can then have its second-phase acceptance tests run in parallel against the same build, so that you get feedback sooner and fail faster. The same applies to subsequent phases. More information on can be found in Jez Humble's free chapter of Continuous Delivery.

The other benefit is that it makes deploying the build very quick. The deployment step itself, at the lowest level, is about transferring files. If you can reduce the deployment step to this then deploying should only take moments. Web Deploy is smart enough to only deploy the files that have changed. So only the minimum amount of network traffic and IO  has to be tolerated. This comes in especially handy if, a bug makes into production that cannot be fixed by rolling forward with a fix. When you need to roll back, the ability to quickly deploy a previously built package without having to compile again is valuable.

The Build Configuration

The Build Config should have a number of steps: build the application, run any tests, potentially generate meta data statistics, and, most importantly, generate deployable output - known as Artifacts. Team City affords a way to access Build Artifacts by letting you address them in the general settings of the build.

In your Build Configuration, find the Artifacts Paths of your General Settings and add the following line:

MyWebApplication\obj\%system.Configuration%\Package => DeployPackage

This places the deployable package in your collection of artifacts in a folder called DeployPackage. Now we have to tell MSBuild to create a package for us when we build the solution. Add a Visual Studio build step, and make sure the solution file path is correct.  Enter the Configuration as and then enter the magic Command Line parameters:

/p:DeployOnBuild=true;DeployTarget=Package

You just need to add the the value of the system.Configuration to the Build Parameters collection of your configuration and this Build Config is complete.




The Deploy Configuration

The deploy configuration has as lot less to do. It only needs to deploy the package that was created in the first build configuration. In Team City, to enable the Deploy Configuration to see the artifacts of another configuration, it needs an Artifact Dependency. Add a new one in the new Deploy configuration by selecting the first Build config in the 'Depend On' drop down. Choose the Last Successful build, and lastly, specify the Artificats Rules. If you provide the line below, you will copy the Artifacts from the DeployPackage folder into a local folder that the Deploy Config can use.

DeployPackage => DeployPackage



If you peek inside the contents of the Deploy Package Contents the Build Config generates, you'll see an executable inside the root folder, with the same name of the web project you want to deploy. This is the exe that will do the heavy lifting of file copying and web config transforming (if you have environment specific configs).

You need to add a single Command Line Build Step to your Deploy Config to run this executable. Importantly, specify the Working Directory to be the path of the Artifacts we copied over from the Dependency we added: DeployPackage. Provide the Command Executable name and lastly, the necessary parameters:

/y /M:https://stage.environment.com:8172/MsDeploy.axd /u:username /p:password /A:Basic -allowUntrusted

I won't go into the specifics of what the M parameter is, but you should have installed Web Deploy on your hosting server already, this is the Web Deploy listener address of that host. The remaining parameters are pretty straight forward.




The Deploy Config will now take whatever was generated from the Build Config and deploy it to the host web server. Two. Separate. Steps. For an extra touch of Auto-Magic you can add a Trigger to your Deploy Config so that it will run whenever the 'dependee', Build Config succeeds. If your Build config is triggered by a change in source control, this results in a deployment after each git push or svn commit. This can be handy, but is not always desirable in production or if you have testers working on specific builds.




Bonus: Custom Builds

If you need to roll back to a previous version, or you need to deploy to a new host server there is a way to make good use of your Deploy Config: the Custom Build. By clicking the '...' next to the Run button you can execute the build with specific, one-off, configuration. You can override the build parameters, for example, to point to a different server (you will need to update your command line properties to read from a build parameter). In the Dependencies tab you will find the option to deploy builds from any of the previous versions of the Build Configuration output, pictured below. This can save the day in an emergency, arms-flailing-hair-on-fire-roll-back scenario. Enjoy.




Thursday, 13 December 2012

ClickOnce Automatic Update with Continuous Deployment

Problem

We need a task-scheduled desktop application to force update itself on start-up every time it runs, so that it always executes the latest version. There may or may not be updates available for the application. This should be part of an automated deployment process, such that the developer does not need to remember to 'bump' the version number on every release.


Solution

A console or windows forms application published as a ClickOnce application has the ability to solve this. We just need to configure the application accordingly. The other element of the solution is Continuous Deployment using Team City. This will provide the automatic versioning.


Click Once

Add the following to the .csproj file to be deployed in the first property group. The following settings worth noting:






<IsWebBootstrapper> & <BootstrapperEnabled>
Gives the application the ability to download other requirements of your application.


<Install>
States that the application will run from the installed files (as opposed to downloading a new executable each time - this is not possible in this scenario as we need the task to be automated).


<InstallFrom>
Tells the application where to look for installation source files. Could alternatively be CD-Rom based.


<UpdateEnabled>, <UpdateMode> & <UpdateRequired>
Needed to make sure the application will check for updates and to do so prominently on screen when updates are required.


<ApplicationVersion>
Tells the application which version it is. This setting will be overridden in when configuring continuous deployment. 


We could run the publishing wizard at this point and install the application locally. However we need this to run on a client/target machine. This deployment aspect needs to be handled by Team City.


Team City

We will assume a Build Configuration is already in place and that the files are made available from your source control. We can then start by adding a build step to 'Publish' the project in the ClickOnce format.


Build Number configuration under General Settings
Here we are setting up the build number to comply with [major].[minor].[build].[revision] format required to apply to .net assemblies. This build number will also be used to tell the published ClickOnce application which version it is currently running.



Assembly Info Patcher Build Feature
Under Build Steps you will need to enable the Assembly Info Patcher as an Additional Build Feature. This will set the assembly version of our project (and all projects in our solution) to be the Build Number set by Team City.





Build Step 1 (Publish)
Here, the only important setting is to specify the target of the MSBuild task is to 'Publish' the project we want to deploy.




System Properties under Build Parameters
These properties tell the build to set the Application Version and the Minimum Required Version to be the same property. This is what keeps the application up-to-date. By specifying that the minimum required version is the same as the latest version, the application always stays up to date.




Also use: system.Configuration = Release



Publish Url
The remaining element of this approach is to publish the necessary installation files. In the example I have specified http://mypublishurl.com/ as an example. In reality, this url could simple be the address of a virtual directory, pointing to a folder where the all the output of the build is copied to.


Build Step 2 (Copy files to Publish Path)
Therefore, the last step of the Team City build process is to copy the output to the directory our Publish Url is serving. The output required is found in the app.publish folder of our bin directory. 



Installing

You should now be able install your application. This is done by accessing the setup.exe generated by the Publish build step. Hit http://mypublishurl.com/setup.exe and you should be greeted with a download dialog. After continuing with the install the application will run immediately and you should be left with a start menu entry under the publisher name you specified.




Updating

Trigger a new build of the build configuration in Team City. This will increment your build number and re-deploy the application to the publish path. Wait for the build to complete and open your application from the start menu again. It should now attempt to update itself.




Scheduling

This is easily achived with windows task scheduler. You will just need to point to the 
.application file in your start menu.