Continuous Integration with GitHub, TeamCity, Azure Websites and IIS7
The CI objective is to continuously and frequently incorporate changes to the codebase into a centralized build process which may include the automated running of tests, analysis of the code and deployment to target environment(s). Pivotal to this is the version control system as this should be the source of truth for the code base. As a result, effective CI is only achieved through effective use of VCS.
In order for this to work successfully, developers need to apply the good development practices, they’re probably already aware of, but may not have previously had the impetus to adhere to. Committing source code regularly, taking updates from team members as frequently as possible and only putting working code which doesn’t fail tests into VCS are all just common sense and good practice. The difference being that if they don’t do this in the CI world, lots of flashing red lights go off and other people get inconvenienced. Let’s just say they should be a lot more motivated now!
Impact on Development Practices
Forcing developers to only release code – even to a development or test server – via a continuous integration and deployment process can be a fundamental change of working for some people. It means moving away from casual VCS and release practices and having to take a much more structured approach to work.
This is a good thing, and if someone tells you otherwise it’s probably because they’re following less than ideal practices to begin with. This really forces you to modularize work into smaller, more atomic units than you might have done in the past. If you don’t commit code atomically, for example by submitting the code behind but not the ASPX with controls it references, your build breaks and now nobody can push it through to the development server until it’s fixed.
Likewise if you go long periods without committing to source control you start to dramatically increase the risk of conflicts with others. Plus you also increase the duration between releases to a server environment which consequently increases your risk of features not working outside your own PC. Everyone’s familiar with this, I assume.
So in summary, release early and release often. Yes, even if you’re not practicing CI!
Choosing A Build Server
This concept is equally applicable to a whole range of build server products that support the principals of CI. Within the .NET space the products most commonly seen include (but are not limited to) CruiseControl.NET(CC.NET), Microsoft’s own Team Foundation Server (TFS) and the topic of today’s discussion, TeamCity from JetBrains (the good folks who bring us ReSharper).
Much discussion about the various merits of each is available on the web but there are a few key and decisive factors in favor of TeamCity. Firstly, the Professional Edition is free and more than capable of providing sufficient features to get very intimate with how it runs before needing the scale of the Enterprise Edition which even then, is only a couple of thousand dollars.
Since abandoning TFS for Git and GitHub, due to a job change, I’ve been looking for some kind of CI workflow. Actually, I think TFS is a very impressive product. What it’s done with the whole application lifecycle management (ALM) and particularly the testing and lab environment is mighty impressive.
Finally, I just like JetBrains! ReSharper is a raging success (over 250,000 licenses sold) and every interaction I’ve had with them both professionally and via medium like Twitter has been profoundly positive. They give me a high degree of confidence that they understand the development process and the tools software developers need to be successful.
Project Background
I was recently transferred to a new project. It’s a project which currently has a Silverlight CRUD client to some business intelligence (BI) warehouse, which is responsible for creating weekly reports to customers. The task was to migrate the current Silverlight client to a web client deployed as an Azure Website.
At my current workplace, we’re profound fans of Git as version control system, and use GitHub, as hosting service. On some of our projects we use TeamCity server for continuous integration.
Setting Up Continuous Integration with TeamCity
We need to setup a build configuration that is triggered by a VCS check-in. First, of is some general settings for the build configuration. Important notice is to remember the artifact path. This path describes which parts of the VCS repository is included in this build. The ‘**’ is a wildcard to include everything.
The next step is to setup source control. This is done in two steps. We need to attach Git as our VCS for this build configuration:
As highlighted, this build configuration is fetching from the master branch from Github. It is also possible to supply different filters for fetching other branches. It also makes it possible to have other build configuration for other primary branches, such as test, staging, release,… Then we need to setup how VCS checkout is done and where to checkout:
An important notice is to set the checkout mode as ‘Automatically on agent’. Default is on server.
So now we have setup VCS, we then move on to setup how the codebase is build and tested. This is done in two seperate steps:
As highlighted I’m using the build-in MSBuild to perform the actual build of the codebase. A number of options are available. The second, dependent on a successful build, is the testing step:
As highlighted, I use NUnit, but there is support for MSTest. I’m not sure about xUnit. Also highlighted is the assembly list. I usually have a number of test assemblies, unit tests, acceptance tests, and integration tests. Supplying a wildcard, all test assemblies will be run.
We then need to supply a build trigger. A build can be run manually, but by setting up a build trigger we can execute the build on a VCS check-in:
You can trigger builds based on a number of variety of different events such as on a schedule (i.e. nightly) or on the success of another build.
That’s it, whenever we make a Git push on our master branch, a build is triggered. There is a ton of other options available in TeamCity. I have also a build configuration for my test branch and one for my release branch. This setup does not avoid developers from checking in a revision which does not build or have failing tests, but it highlights issues, and makes the team aware of issues on the latest check-in. By making the steps dependent on each other, we can make assure that we don’t deploy a revision with failing tests. In the next section, I’ll setup a deployment step, where TeamCity deploys the, now building and fully-tested codebase, to an Azure Website.
Setting Up Deployment to Azure Websites using TeamCity
We start by creating a new build configuration for deploying to a Azure Website:
In the source control settings, we attach the same VCS root as for building and testing the master branch, shown in the previous section. In the build step section, I’ll setup a command line build step.
It is actually pretty trivial. From command line, we make a Git push to a Azure Website specific URL, on the master branch. This URL can be found on your Azure Website on the Configure tab:
Copy the Deployment Trigger Url to your TeamCity build configuration. The branch needs to be the same on both Azure and in the Git push URL. As shown in the previous section, we can use different branches in different builds, and therefore deploy to different environments. In this project, I have a development environment, which is deployed using the master branch, a test environment using the test branch, and finally a production environment using the release branch. I then have completely separate environments, controlled by Girt branches.
To trigger the Azure deployment, a build trigger is specified:
This triggers the deployment to Azure on a successful build step, shown in the previous section. Basically, this guards any deployment of faulty revisions.
There are two additional settings that we need before we have automated Azure Website deployment. We need to setup two dependencies for the build:
I need a snapshot dependency and an artifact dependency. The snapshot dependency, is a indicating that this build will use the latest successful Build & Test Master build. By doing this we can avoid, that another team member makes a check-in, just after the previous check-in, and thereby invalidates the first check-in. This makes sure that build and revision is in line. The artifact dependency, has the same meaning as the snapshot dependency, but at at artifact level. Making sure that none of the artifact is invalidated by a successive check-in.
This is all that it takes to make your Github repo, being build, tested and deployed to an Azure Website. In the current project, I have also created another build for IIS deployment.
Setting Up Deployment to IIS7 using TeamCity
This is done by using pushing a Web Deploy package to the IIS. A Web Deploy package contains everything that is needed for a deployment. On the server, running the IIS, we need to make sure that the Web Deployment Agent Service is running and always will (automatic startup). On the General Settings page, make sure to provide the correct artifact path:
This indicates where the Web Deploy package is located, dependent on the build configuration used.
Then I’ve setup a MSBuild command line build step:
The important part is the command line parameters. These parameters tells MSBuild that it should build, package, and deploy using Web Deploy. As with the Azure deployment, this build is triggered after a successful Build & Test Master build. I’ve provided two build parameters, %env.Configuration% and %env.TargetServer%, these are provided at the Build Parameters page.
That’s all. Now when a team member makes a Git push to master, the master branch is build, tested, and the client is deployed to an Azure Website and the backend is deployed to an IIS7.
Tweetcomments powered by Disqus