The first step uses MSBuild to do a complete rebuild of the application in release mode (separate pdb symbols and compiler optimizations enabled). Next we run database migrations to prepare our test db environment for database integration testing. Following that the unit tests are run with dynamic analysis by dotcover followed by static code analysis with FxCop.
Below are the current steps in our Continuous Integration process:
Publish the Deployment Package
The final step in this build configuration actually packages / publishes the front-end web application. This is the step which will package and publish the web application and create the build artifact that will later be used for deployment.
Let’s take a closer look at what this step is doing:
Based on the settings, this step is running the MSBuild target “Publish” with a configuration of “Release” and a platform of “AnyCPU”. Let’s a take a look at the .msbuild file detail:
|<?xml version="1.0" encoding="utf-8"?>|
|<Message Text="Configuration: $(Configuration)" />|
|<!– Platform=Any Cpu for Solution Files, Platform=AnyCpu for project files–>|
|<MSBuild Projects="$(Projects)" Properties="Platform=AnyCPU;|
The publish target is going to create a package for our web application (because of the DeployOnBuild=True and DeployTarget=Package properties) using the release configuration and drop the results of this package / publish into a folder (PackageLocation) that is specified in the above build task. This task takes very little time (< 15 seconds) since the project was already built in the first step of the build configuration. The only thing MSBuild needs to do for this step is to package up the files actually needed to run the application on the target environment.
As you can see, there are no tasks in this build configuration that deploy the application. This is because the application is not being deployed as part of this process. Instead, the published package has been created and is ready to be deployed to multiple environments.
A key point here is that we will have one set of build artifacts for our deployments. The package we just created will be deployed to all of the environments. Our deployment steps will not need to do any compilation or packaging before deployment.
Now we just need to add this package as a Team City build artifact so we can use it in subsequent build configurations. Using the first form for a Build Configuration in team city (1 General Settings), the saved artifacts of the build may be specified:
Here is a closer look at the defined artifact paths:
We are creating three sets of artifacts in this step:
- The packaged version of our application built in the package build target in step five of our build configuration. You will notice that this pulls from the PackageTmp directory. This is the directory MSBuild uses as a temporary folder for publishing the files. At this point the transforms have not been applied, but the compilation and selection of necessary files has been completed. It is also possible to use the actual packaged zip file as the artifact for your build and you may have reasons that this would work better in your situation. In this case the PackageTmp has all of the files we need in a convenient file path with no extraneous directories or command scripts.
- An artifact that contains the base web.config file and all of the transforms in the original solution. This will be used to perform config transformations on deployment.
- An artifact that contains deployment artifacts from our original solution. In this case it contains two MSBuild files: Publish.msbuild and Transform.msbuild.
Debug and Release Mode Only Please
For our deployments we really only have two valid build configurations: release and debug. From an application deployment standpoint there are two major compiler differences between these two configuration. The two compiler switches in questions may be found in the project file as properties on the given configuration property group: DebugType and Optimize. You can find more information for these compiler options at MSDN.
DebugType allows you to specify how the compiler should handle symbols for the application (full, none, pdbonly). For our application we have this set to full in the debug configuration (the symbols are compiled in to the target assembly) and pdb only (separate symbol files) for the release configuration.
Optimize tells the application whether to optimize the code or not. For reference, here is a list of optimizations that Eric Lippert on the C# compiler team has created.
The Debug configuration is great for running on a development system where the Visual Studio debugger is used to attach to the source for step-through debugging. On our deployment targets we almost always deploy in Release configuration so that our system testers and end users get the performance advantages.
Because of this we only need to create one package to deploy to all of our test and production environments. This package is built in Release mode and the configuration differences between the target deployment environments are specified in the web.config transformation for that environment. These transformations are applied during the transform and deploy build configuration.