Modelling Deployment Pipeline with JetBrains TeamCity

Deployment Pipeline is a concept of Continuous Delivery. In the simplest way possible explaining Deployment Pipeline I would say that it is an automated way of getting the software from version control into the hand of end user.

The process of getting the software from the version control such as Subversion or Git into the end user typically involves traveling through checkpoints. Those checkpoints (or steps) could be: Building the software -> Unit testing -> Automated acceptance testing -> Deployment into QA/UAT/Staging environment -> Manual QA -> Release into production.

Example of Software Delivery

Example process diagram for changes moving through the Deployment Pipeline.

For more detailed description of Deployment Pipeline I recommend this article http://www.informit.com/articles/article.aspx?p=1621865  from Continuous Delivery gurus (Jez Humble, David Farley).

No matter what is the process there is a need for tools to automate and support the Deployment Pipeline. This automation is typically handled by the Continuous Integration servers. Some of the CI server out there:

I’m going to take a closer look on the way TeamCity supports modelling the Deployment Pipeline.

How to setup TeamCity

Step dependencies

When designing the Deployment Pipeline it is very important to create number of steps reflecting delivery process that have dependency on a previous Steps (checkpoints) of the process. Among many features that TeamCity have, exists the one for adding Snapshot Dependency between different builds.

Picture below shows example of two TeamCity builds representing two steps in my project delivery.

Build dependencies

Build called Acceptance tests on Staging has dependency on Deploy to Staging.

What this mean in practice is that TeamCity will execute the Acceptance Test on Staging build only if there is a successful Deployment to Staging environment.

Triggering subsequent builds

Subsequent build could be triggered automatically when previous build in the Deployment Pipeline was successful. For example, in out configuration Automated Acceptance tests on Staging environment are triggered automatically as soon as deployment finishes.

This is achieved by setting up TeamCity build to be triggered on Finished build, just like in the next screen cap example.

Trigger

There are steps in the Deployment Pipeline that require and should be manually triggered. In our case the Deployment to Staging environment is manually triggered by user. This happens as we only want some versions and control when they are released into that environment. It is enough to remove any triggers from the Build Triggering configuration to make it manually triggered.

Viewing the build pipeline

Latest version of TeamCity (I’m using TC 7.1.3) has a nice feature in the project view called Build Chains. It’s nothing else but a unified single view of dependent builds (Deployment Pipeline).

Example pipeline from my project:

Deployment pipeline

In our Deployment Pipeline, every commit of a code will trigger first build Clean and Compile the project. Pipeline stops at the deployment into smoke environment. Once confirmed the next station is a deployment into Staging. Final stop is the Release into production.

In our case the view of a build chain is the exact representation of our automated Deployment Pipeline.

19 thoughts on “Modelling Deployment Pipeline with JetBrains TeamCity

  1. How did you get the build chain view to wrap so that the long chain of build jobs is all visible on the screen at once? We are doing the same thing but for us, we can only see the first two or three jobs and have to scroll to the right. We are also on 7.1.3.

    1. Hi Brian
      I actually didn’t. It’s just an image edit so I could show the idea. You are right, the build chain will blow out of the screen to the right side.
      Perhaps JerBrains would care to address the issue at some point

  2. Hi Greg,

    was there a reason you chose snapshot dependencies over artifact dependencies?
    Looking at the TC docs I got the impression that the latter would be more suited for a CD pipeline:
    “Artifact dependency is just a way to get artifacts produced by one build in another. Without corresponding Snapshot dependency they are mainly used when the build configurations are not related in terms of sources. For example one build provides a reusable component for others.
    Snapshot dependency influences the way builds are processed and implies that the builds are deeply related with one build being a logic part of another one.”

    Cheers,
    Chris

    1. Hi Chris
      I think I didn’t care in my builds about the produced artifacts, as they are put in Binary repository. However I do care about the relationship between builds. I hope this is making sense 🙂
      Greg

      1. It makes sense if you have a unique identifier for each artifact that you then use to retrieve the artifact from the binary repo for your deploy steps. I’m wondering what the pros and cons are when compared to just leaving the artifact with TC. With a complete CD pipeline, there’s no real use for an external binary repo. Except for caching 3rd party libs and such.

      2. It is true Chris. However, within big Enterprise where control is a must, CD is not a complete pipeline. Thats where the binary repo is useful. Once prepared packages can be used in the production deployment when it is required. It also makes sense when your releases are shared libraries used by many teams, not a deployable software. CI environments are not build to store software releases. I think you need to make a call on this.
        Perhaps your artifacts can stay in TeamCity 🙂

  3. Hi Greg,

    Maybe this isn’t so connected to the pipeline modelling but still bothers me a bit: Do you somehow put your build server configuration into TeamCity? All in all is it possible? Or maybe you have never been tempted to do so.

    I worked both with TeamCity and CruiseControl. CC allows you to have build.config file where you store build configuration which I think is great as I’m a big fun of the idea of versioning everything that changes. I cannot see such option in TeamCity. The only think possible is to have TeamCity backup which isn’t actually what I want.

    1. Hi Chris

      You could say that it’s a TC feature. A nice UI that one can use for configuration vs xml file that you can easily make mistake in 🙂

      On the other hand, as you are saying, there is no easy way of moving or versioning build configuration.

      1. …quirk of fate. Yesterday night because one of one of my builds hang I decided to restart TeamCity Server. After that TC said that database is corrupted. I tried to recover but failed. Unfortunately I had no backup. Whole pipeline is gone. This is the case when versioned XML file is safer.

        Lesson learned: always do backups as fast as possible (I planned to do this today but it broke).

    2. Hi,

      not sure if I understood you correctly, Chris, but there’s an audit log in TC with a visual diff. You can access it from the page where you edit the build config settings, in the lower right corner (“view history”)

      chris

      1. Thanks for a tip, I didn’t know it 🙂 But it’s not what I wanted – I want my pipeline be a part of my solution so that I track changes of the pipeline together with changes of my code. This could be also easier to move from TeamCity to other awesome tool (if exists).

        The only option I see is to follow advices proposed here: http://stackoverflow.com/questions/3136165/how-does-one-version-control-the-configuration-of-a-teamcity-project

        As I understand I need to have every build configuration in a separate file without parameters (i.e. MSBUILD file) and execute it by TC as a step of my pipeline.

  4. One thing I do notice now is that the custom run dialog will preselect the “changes” tab if there were any changes in the dependencies. Now, this is because the snapshot dependencies weren’t meant for implementing the CD pipeline in the first place. They work quite well for it, but they’re geared towards working with snapshots of the codebase. Thus, displaying changes is important for a dependent build config.

    In a proper CD pipeline, though, one of the rules is to NOT work with sources but rather build binary artifacts once and then work with those artifacts. Not a huge difference, but still I’ll have to explain to somebody why they need to ignore the changes tab if it pops up. I think Jenkins does a better job here with some plugin that’s really meant for modelling CD pipelines but I never worked with it.

  5. Hi Greg,

    One thing I’m struggling with is using an external tool to trigger the next stage in an existing pipeline. In your example, kicking off the deploy to production of a particular build that passed acceptance test. I don’t see a way through the API to do this, only through the UI.

    Another problem is the user could use Promote to skip directly to running the deploy to production step which would execute all the previous steps automatically. This doesn’t allow proper approval or governance over the process.

    I also don’t see a way to limit who can execute a particular step in the process. Deploy to production should only be allowed for a limited number of people.

    Any ideas how to overcome these problems?

    Thanks.

    1. You can trigger build via REST API Call, follow this link for info: http://confluence.jetbrains.com/display/TCD8/REST+API#RESTAPI-TriggeringaBuild

      There are things you could to in TeamCity to enable only certain people do certain things. You are going to have to play with custom roles, groups, per project permissions, etc.

      TeamCity is a simple CI server, I don’t think you can expect proper Governance support from the tool. I guess there is some work you could do around custom TC Plugins, or write a little application that serves as a facade to TC and calls to REST API.

      There is no simple solution, unfortunately.
      Greg

      1. Thanks for the responses, Greg. I have been looking at the REST API for triggering builds, and I’m hoping there is some incantation to trigger a build in an existing chain by specifying the artifact dependency build id of the previous build in the chain. I can stash away that ID using the %teamcity.build.id% variable. But I don’t know how to specify that on the call to /rest/buildQueue. Their examples are very limited and I can’t find a schema that defines the build.xml. Do you know what I would need to specify the artifact dependency in the below:

        <buildType id="
        ???

        Thanks.

      2. (Oops, looks like the XML in my previous comment got munged. There wasn’t much there anyway…)

      3. You need to send a POST request to http://teamcity.url:8111/httpAuth/app/rest/buildQueue with a POST content of the XML you were trying to paste in the comment.
        It’s as simple as that.
        For example, using CURL:

        curl -X POST --user user:password --data "<build><buildType id="buildConfID"/></build>" http://teamcity.url:8111/httpAuth/app/rest/buildQueue

        Trying that from the browser is only going to work with some kind of a REST plugin like Postman for Chrome.

  6. Yes, I know how to do a post to the API, the problem was what to pass to it. Your example would submit a new build and build all previous builds in the chain. I figured out how to do it by trial and error. I’m not sure how to post the example here without the XML characters getting garbled, but I’ll try:


    Where 42 is the %teamcity.build.id%

    1. Try again:

      <build>
      <buildType id="DevOps_DeploytoProduction"/>
      <snapshot-dependencies>
      <build id="42" buildTypeId="DevOps_RequestProductionDeployment"/>
      </snapshot-dependencies>
      </build>

Leave a comment