Automatically Building Pull Requests from GitHub with TeamCity

Scenario

You’re running an OSS project* and someone makes a pull request. You’ve got two choices:

  • Merge and Pray
  • Pull to local branch, build, run tests and merge if all OK

What do you do? Well, what is it going to be?

Dealing with Pull Request

I know what I’d like to do, and GitHub makes it so so tempting:

Merge Pull Request

But unfortunately I go with the second option.

That’s a pain, specially if you do a quick code-review and things look decent. Yet you still need to make sure that it builds and all tests pass.

Well, luckily for me, and my ability to continuously interfere in conversations, I found out that there is a better way. And what’s even nicer, is that it’s also possible with TeamCity.

*This applies to non-OSS too

Automatically Building All Pull Requests

What I want to do is have TeamCity automatically build all Pull Requests for me of my main repository, and notify me if it is successful. And I want this to happen without me having to configure every single fork as a repository in TeamCity, because like that, it wouldn’t be manageable. Here’s a diagram explaining it:

TC Flow Diagram

This will drastically improve the workflow since we no longer have to manually create a local branch of the pull request, check it, build it and only then merge it.

Configuring TeamCity

Setting up TeamCity to do this is really simple. It actually only requires one thing: configuring the Branch Specification under the VCS root:

TC Git Config

Let’s see what this means and why it works. When a pull request is made, GitHub automatically creates a reference that holds the pull request as well as one that is a merge with the master branch. What we’re saying to TeamCity is to monitor this branch, in addition to the main branch. In this syntax, pull refers to the pull request. The * refers to ANY pull request, and the merge indicates that we’re interested in the pull request merged with the master branch. This means that when TeamCity builds, it will build the branch that was merged. If we want to build the branch, without merging, we could use the following:

+:refs/pull/*/head

So to recap, adding merge builds the result of the merge, and adding head, just the pull request without the merge.

The result of these builds show up in TeamCity like so:

TC Result 1

where the number denotes the pull request. Now, we can actually make this a bit nicer by allowing us to see whether the particular request was the result of a merge or just the branch itself. For that, we can specify the following in the Branch Specification

TC Alt Config

with TeamCity now indicating whether this was a merge or head:

TC Result 2

In addition, TeamCity also provides us with a Dropdown, where we can filter all the different pull requests:

Filter

Seeing notifications on the Pull Request

As this is a normal build, like any other build, we can configure TeamCity to receive notifications via email, tray icon, etc, both on successful builds as well as failed builds. However, there is one other thing that we can do: see the result of the build on the Pull Request page on GitHub. In order for this to happen, we do need to install a plugin for TeamCity which currently doesn’t ship out of the box. This plugin, written by Eugene Petrenko uses some hooks GitHub provides to add notification information on the Pull Request page.

To install it, download the plugin as a zip file and place it in the plugins folder of the server and restart the server.

Once that’s installed, we can now display build status information on the GitHub pull request by adding a Build Feature to our Build Steps:

Build Feature

and filling in some simple configuration parameters:

image

And with that, we can see the status on the Pull Request page on GitHub.

image

* If you’re running your OSS project on TeamCity at CodeBetter, you now have this plugin available.

Summary

Although my example was based on TeamCity 8.0 which is currently in EAP, this feature also works with TeamCity 7.1.3+ (and even previously covered by others). The examples are also based on OSS projects, but you can apply the same workflow to private repositories also, hopefully making things a little bit easier.

18 thoughts on “Automatically Building Pull Requests from GitHub with TeamCity

    1. Hadi Hariri Post author

      It does both. That’s what I was outlining in the section about how you define your branch spec. If you use /merge, it uses the merged branch. If you specify /head it uses the pull request branch without the merge. In fact you can have both at the same time if you like.

      Reply
  1. Laurent Kempé (@laurentkempe)

    That’s fantastic Hadi! It remember me a discussion with Yegor exactly about what you present in this post! At that time Github was just introducing the Commit Status API and my only concern at that time was that it was only the result of a build on the branch and not with the merged branch.

    This is just great, thanks for sharing and btw Happy Birthday!

    Reply
  2. Adam Ralph

    The only problem I have right now is that the status reporting plugin only reports on the status of PR head builds and not PR merge builds. Ideally, I’d like both to be reported, but the more useful one of the two is definitely the merge. I don’t see how the status can be reliably reported as ‘Good to merge’ on the basis of the head build. There is an issue raised for this https://github.com/jonnyzzz/TeamCity.GitHub/issues/9

    Reply
  3. Brandon

    I am having a problem. I am assuming that something is configured incorrectly.
    TeamCity is not automatically building on the pull request. I see that TeamCity detects the pending changes, but no build is ever triggered.

    I have the TeamCity hook configured on the master project and builds are automatically triggered when I push to the master project. However, when I do a pull request from the forked project, no TeamCity builds are being run. What do you think I might be doing wrong?

    Also, as a side note, when I manually run the build for the changes detected by the pull request, the plugin never reports “good to go” back to github it always reports “determining status”.

    I suppose I should also mention that we are using github enterprise not github.com.

    Brandon

    Reply
      1. Brandon

        Hi, thanks for your reply and taking the time to help.
        Yes, I configured the branch specification as described above in your blog. +:refs/pull/(*/merge)
        My default branch setting is master.
        When I go to the TeamCity gui, it definitely recognizes and lists the pull request branch just like in your blog. However, the builds don’t automatically run they just show up as pending changes. I have to manually trigger them. The agent is running and builds trigger when I push to the master. So I take it that that you didn’t configure anything else other than the branch specification and your builds automatically run when you do the pull request? You didn’t have to configure a build trigger? I even tried with the latest EAP build like you.

        As a side note, I found out why the plugin was always reporting ‘pending’. The build was running too quickly and while the status ‘success’ status was being reported, github was either receiving them out of order or couldn’t decide which one to use since they had the same timestamp or something like that. The issue of status not working for merged builds has been fixed.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s