January 6, 2017

Continuous Integration and Deployment Basics for .NET Developers - Part 2

Okay, so as a .NET developer, the first thing I didn't understand were the major components of a deployment of a .NET application. Some of which you will already be familiar with in passing - such as dependency resolution. If you've already used NuGet, you'll be somewhat familiar with this. You may be familiar with Build in some sense, we'll go into more detail as just understanding how to hit F5 to compile your application is only the very topmost tip of the iceberg. You're likely also familiar with unit testing. So here are the major pieces as I've come to know and understand them:
  1. Dependency Resolution - Obviously our application has prerequisites and libraries it needs to compile. These dependencies are usually satisfied by Visual Studio when you compile, but our build server needs to resolve these dependencies ahead of attempting to compile our code as it doesn't use Visual Studio to do the build.
  2. Version Numbering - Our assemblies will need a unique version number assigned prior to each build. We need to be able to trace which assemblies have been tested and signed off for release. We can't do that without assemblies having unique version numbers assigned.
  3. Build - Our code obviously needs to compile. Without compiled code, we've got nothing to deploy. This will include applying version numbers, unit testing and some limited integration testing. It will be handy if we get to understand the content of our project files which contain the file references, targets and property definitions required to load and compile our application in the correct order.
  4. Testing - Now that we've build our code, we need to test the assemblies for correctness by running our unit and integration tests. Because the application hasn't yet been deployed, any tests that run at this stage cannot require access to infrastructure.
  5. Configuration Transform - Configurations are different for each deployment environment, transforms are run to turn configuration files into templated files that can have environment specific values applied at deployment time.
  6. Packaging - Now our code is built and tested, it needs to be packaged for deployment. This packaged artifact is immutable, it contains the exact binaries that were built and unit tested in step 3, no exceptions.
  7. Deployment - The artifacts get deployed to your test environment where your automated test suite will run the functional tests to prove that the feature changes you made do so successfully and without any regression. Upon success, they may be further deployed to subsequent environments including staging and production.
  8. Functional Testing - Some testing requires infrastructure, and so it can't be completed until the application has been deployed to an environment. So now we're deployed to our target environment, we can run our functional tests. Obviously these will need to be packaged up and deployed and run on a server in our target environment.
As I understood some of these pieces prior to my foray into the DevOps world, it turns out that my understanding as a developer didn't really cut it when it came to deployment. There are some caveats to various pieces that as a developer, I never really had to pay attention to - for instance:
  • Versioning using the 1.0.* that we've all come across just doesn't quite cut it in most deployment environments. If you need to be able to track versions back to a release on your deployment server or a specific build on your build server, your version numbering needs to incorporate these facts.
  • Build well, there is so much more to building your application than just hitting F5 and hoping it compiles. Your project files are highly configurable if you take the time to grok them.
  • Integration Testing can only run on the build server if it has no infrastructure requirements, thus any integration tests must have their own mock repositories or they will only be able to be run post-deployment in a target environment.
  • Configuration Transforms aren't to populate settings with environment specific values. They're to sanitize your configurations so that your deployment system can hydrate the settings with environment specific values - many of which for security purposes will never be visible to developers.
As I continue with future posts, I will go over my notes for each of these pieces and discuss things that need to be considered to get a deployment up and running.

Continue to Part 3 - Dependency Resolution

No comments:

Post a Comment