Versioning a Multi-Component SystemJan21

Thursday, 21 January 2010 by Haemoglobin

1  A lot of the systems that I have worked on have involved more than one component. For example, instead of just an ASP.NET website, there would also be some sort of windows service, maybe a windows forms component, or independent modules and libraries working within those components – all working together to form a final solution.

This tends to create a bit of a versioning and deployment nightmare and you need to have a good solid strategy around it before launching into things. I have tried a couple of approaches.

For one project, I had an automated build script that would go through and modify the version number of all the assemblies, build all the components and label the version from the root in source control. All components would then be redeployed for every release, regardless of whether they have changed or not. This removed human error in deployments as everything was automated, and the deployment steps were always exactly the same for each release so even those could be automated.

This worked pretty well for this project, because there were so many developers that it would have been too time consuming to do a full version to version diff to figure out which components have changed for each release and to deploy only those. Yes there would be release notes on what has changed for each of the components as written by project management or the developer, but that would be reliant on how dutiful Mr developer happened to be at the time, and it’s possible little “tidy” ups were done, or refactorings in components that do not end up appearing on release notes. So one answer is just to test and redeploy everything (this is where automated testing can be very useful also to test for regressions across the system). The only problem with it is you potentially end up deploying a lot of unchanged stuff – albeit just with updated version numbers, all for potentially one small change in one of the components.

For another project – there were far fewer developers, and it was quite easy to just know what components were being changed for each release – so it was possible to just deploy those that were being updated. I came up with the concept of a system version.

Say if you have the following structure in your source control repository for your software solution:

  • MySolution
    • ASP.NET Website
    • Windows Forms Application
    • Windows Service
    • Reporting Services Reports
    • Database Scripts

When you deployed the first version to production, imagine everything was versioned at 1.0.0. All assemblies / exe’s would have been deployed as version 1.0.0 (or using other techniques for database scripts like updating the database version row to this), and the label Version_1_0_0 (or similar) then applied to the MySolution root in source control.

This is in contrast to labelling each subcomponent separately in source control and keeping a configuration management register updated with what versions are deployed where and what versions are all working and tested with what other component versions – uggh.

Now – say that a bug in the windows forms application is reported – it makes sense to just send out a new version of just that, not everything. You make the change, and update the windows forms application’s version to 1.0.1. Now, the solution is is labelled with Version_1_0_1 from the root where 1.0.1 is effectively the new system version. Note however that the rest of the sub-components are still set at version 1.0.0 (literally within the AssemblyInfo.cs classes) – but the 1.0.1 label spans across them, effectively grouping the various current sub-component versions under the 1.0.1 system version umbrella.

Now – lets say a whole lot of work is done across all the different components to create a new feature asked for that will become version 1.1.0. During this time, another small issue is found in production – this time in the windows service. Since we are in the middle of development of version 1.1.0, which is subsequently unstable – we must branch the solution from version 1.0.1 (using the source control branching functionality). Here we make our change to the windows service, update it’s assembly version to 1.0.2 and then label the root of the branch as system version 1.0.2. We then deploy just the windows service to the client.

If we were deploying this solution to multiple clients, who for some reason were running on different versions, you can easily recreate in the development environment the version that they have running in their environment as long as you know their system version. Note that this must be recorded somewhere – but in this case it’s just one number per system deployment, as opposed to a complex set of versions of all the components installed. Pulling that label out of source control will retrieve all the subcomponents in their correct version as deployed for that system version, and consequently retrieve exactly what is running in production for each component.

The only danger with this technique is the possibility of a component being changed (maybe a developer deciding to re-factor some previous work), and not having this component deployed along with the next system version. This would effectively create a mismatch between what is deployed and running on the client’s system and the code associated with that system version in source control. This creates unreproducible bugs and other issues. To solve this, a quick and easy technique should be devised to query source control to see what components have been “touched” since the last release.

I would be interested to hear how others go about versioning in these sorts of situations. I may make a follow up post at some point about database versioning, and UAT deployment techniques.

Categories:   Development
Actions:   E-mail | Permalink | Comments
blog comments powered by Disqus