Previously, I had talked about why continuous integration (CI) is the best approach to software development in terms of improving software quality and saving time and effort for developers on a team. Now I want to explain how I maintain this page among other projects using continuous integration and continuous deployment and why this is beneficial even for one person projects. I should note that what I am about to describe I would not exactly recommend using in a business environment, I’ll describe that a later (however, if you don’t have any CI environment, this would be a huge improvement).

First, I use the following software:

  1. IIS – Microsoft’s Web Server.
  2. Subversion (svn) – Source Control
  3. Team City - an application specifically built for CI and build management.
  4. Subversion plug-in for Visual Studio.

I have my own windows server set up, which is running the svn server, the Team City server, and IIS. I have various Team City builds monitoring different parts of the source tree. Whenever I make a change and commit it, the build that monitors kevinkinnett.com will see the change and get kicked off. I’ve configured the build with the following steps:

  1. Pulls down a new copy of the source into a temporary build directory
  2. Builds the entire solution
  3. If, and only if, the solution compiles then a series of unit tests are run against the compiled project.
  4. If, and only if, all of the unit tests pass then the solution compiles then a MSBuild script runs which does the following:
  5. Stops IIS
  6. Deploys the artifacts specifically needed to run the application (aspx pages, dlls, etc) to where the directory that IIS is running the site out of.
  7. Restarts IIS

If any of the steps fail then Team City tray notification application gives a dashboard display of the status of the builds (see the picture). I can easily see if any changes I have made have caused any deployment issues, and if not, it informs me of when the changes have made to the live environment.

You can really see the benefit if you consider another project I have that are a series of windows services that monitor various things like rss feeds and host their own WCF services. The steps in this build are as follows:

  1. Pulls down a new copy of the source into a temporary build directory
  2. Builds the entire solution
  3. If, and only if, the solution compiles then a series of unit tests are run against the compiled project.
  4. If, and only if, all of the unit tests pass then a MSBuild script runs which does the following:
  5. Stops the correct windows service
  6. Uninstalls the windows service
  7. Deploys the new service
  8. Starts the new service

For either the webpage or the windows services, if I wanted to deploy by hand it would take fair bit of time and trouble each time I wanted to do it. This automates the entire process, freeing me to continue to work while the new versions are being pushed out there for me. If I made any mistakes and I have done my due diligence writing tests that cover those cases, then I will have a helpful error message in the tray notification icon soon after I deploy (remember it is easier to track down recent mistakes) and prior to it going out into the live system (fixing bugs before they make it to production).

I think took me somewhere in the neighborhood of 3 to 4 hours to set up and maintain this process. But how much time did this save me? You can see from the picture that I have done something like 96 deployments of this page alone. It would have taken may times that initial investment to have done all those deployments by hand. What I’ve been able to do is make small incremental changes whenever I want and deploy them without any pain at all.

Here are some other benefits:

  1. I can easily track the changes I have made through the project and revert them if necessary and have the reverted site live within minutes.
  2. If I wanted to work on my projects on another machine, I could just pull down the latest version of the project and start working almost immediately.
  3. If I wanted someone else to start working on my project tomorrow, I’d simply have to give him access to the svn server, and he could pull down the code and start working immediately. Any time he made changes, I’d have higher level of assurance that his code would work and not take down the live environment. Plus, he would have the ability to deploy his changes without needing to know how to log into the box and do it himself.

If you were doing this in a business environment then you should definitely maintain a separate build environment from your production environment, plus you should have separate development and quality assurance environments as well.

Here is one potential real-world scenario:

  1. Your continuous integration environment builds you project.
  2. Runs unit tests against the compiled project.
  3. Creates deployment artifacts (such as a MSI).
  4. Uses those artifacts to deploy the entire project to a separate test environment.
  5. Run integration tests against that test environment (such as database tests, or automated UI tests).
  6. Later, if those tests are successful, another build target takes the deployment artifacts of the most recent successful build and test (or one that you specify) and deploys it to the Quality Assurance environment.
  7. QA engineers then run manual functional and regression tests against it.
  8. If these tests are successful then the same deployment artifacts can be used to make a deployment to production.

If you have a reasonable facsimile of the production on your dev and QA environments then this can help ensure a success deployment with less potential for bug being introduced.

I’ve heard of people having a process similar to the above example but instead using the API provided by VMware to create actual running VMs with the product installed on them as a build artifact. It is the actual VM itself that is tested, passed to QA, and deployed to production. This way you are guaranteed that your environments are identical, and what you deploy to production is the same as what you have tested.