Automatically Building Pull Requests from GitHub

Hadi Hariri

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?

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 there is a third 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.

banner_blog@2x

Comments below can no longer be edited.

28 Responses to Automatically Building Pull Requests from GitHub

  1. Brandon Donnelson says:

    February 8, 2013

    Thanks for the walkthrough.

    But I can’t get the Github notifications plugin to work in 7.1.4. Could you add more logging to the plugin and help get it fixed?

    https://github.com/jonnyzzz/TeamCity.GitHub/issues/7

  2. Eugene Petrenko says:

    February 9, 2013

    Brandon, please find my answer on GitHub issue

  3. Or says:

    February 11, 2013

    Can you setup something similar with Perforce?

  4. pavel.sher says:

    February 11, 2013

    Unfortunately no, as Perforce did not provide such abilities (pull requests, auto merge, easy branching, etc). Or does it now?

  5. Harry McIntyre says:

    February 13, 2013

    Is this safe? Sounds like a good way to let a 3rd party execute code on your server…

  6. John says:

    February 13, 2013

    Does it differentiate between Opened vs Closed pull requests?
    I’ve enabled this but it looks like it is building all the pull requests not just the Opened ones!

  7. John says:

    February 13, 2013

    Another question, I have setup build chains so that the last step on the chain is to create a nuget package and upload it to nuget, obvioulsy I do not want this to run if all I’m doing is testing a PR.
    So how do I tell TC to not do a certain build chain?

  8. Ricky Clarkson says:

    February 14, 2013

    Isn’t this a security risk at least for public repositories? A build could involve executing arbitrary code, and you wouldn’t want to execute arbitrary code on your build server that people you don’t know send as pull requests.

  9. Hadi Hariri says:

    February 14, 2013

    @Harry, @Ricky

    Any code that runs on your agent will potentially put your agent at risk unless it’s run under the current permissions. So essentially yes, this can cause a security risk, but this will happen with any system that does the same thing.

  10. Dmitry says:

    February 15, 2013

    @John,

    yes VCS trigger builds all the pull requests, because it doesn’t know anything about github. To build only new ones we probably need a dedicated github trigger that watches pull requests in repository. It can also run the builds only for pull requests from the specified trusted users, solving security problem.

    To skip publishing nuget package you can analyze a config parameter ‘teamcity.build.branch’ in your build script. It has a value ” for builds from the default branch.

  11. Dmitry says:

    February 15, 2013

    I meant <default>

  12. Behrang says:

    September 27, 2013

    Would this also work with GitLab?

    • Hadi Hariri says:

      September 27, 2013

      Not tried it unfortunately.

      • Adam Ralph says:

        July 2, 2014

        Second that. We’re in the process of switching from GitHub enterprise to GitLab so really interested to see if we can get it working. Building PR’s is fundamental to our workflow.

  13. Pencho Ilchev says:

    November 16, 2013

    Great article! We use this in our CI process. I potential gotcha is the use of a build trigger that fires on commit. GH will force a commit in refs/pull/xxx/merge whenever the status of the pull request is changed (reported to GH as a suspected bug). If refs/pull/*/merge is used as a branch specification, teamcity will pick up the change (different commit hash) and the trigger will fire another build…and so forth.

    • Rob Tetlock says:

      November 18, 2013

      Thanks Pencho, running into this myself. Did you come up with a way to trigger the build only once per commit?

  14. Mohammed A says:

    December 11, 2013

    This seems to be the case for Teamcity 7.1. Does this work on Teamcity 8.0 and with enterprise github?

    • Hadi Hariri says:

      December 11, 2013

      Yes

  15. Dmitry Filatov says:

    January 21, 2014

    Hello!

    Thank you for detailed article! I made the setup for TeamCity 8.0.4, but unfortunately it doesn’t work =(. TeamCity successfully picks up individual branches, but not merged pull request branches.

    Here is what I have: http://d.pr/i/98Tv and at Trigger http://d.pr/i/QxD8

    At the same time I see merged pull requests in Pending Changes – http://d.pr/i/xvYs

    Thank you in advance for help!

    • Hadi Hariri says:

      January 21, 2014

      Hmm. That should work. Can you email teamcity-feedback@jetbrains.com? We can handle it via support.

    • Andrey says:

      April 11, 2014

      Hello!
      Have you solved the issue? I have the same now 🙁

  16. Patrick Anarna says:

    January 23, 2014

    I’m doing this but I’m getting flooded by builds from closed merge branches.

  17. Lasse Westh-Nielsen says:

    February 6, 2014

    There are two blockers for me here (from https://blog.jetbrains.com/teamcity/2013/02/automatically-building-pull-requests-from-github-with-teamcity/#comment-290):
    – dedicated github build trigger
    – running builds from trusted users only

    I can’t find any info on whether this has improved in the last year?

  18. Gleb says:

    February 28, 2014

    Thanks for the article.
    Is there any way to access the branch name that is parent to a pull request? Or at least to get the pull request number? May be there is some TC variable or something.

  19. Daniel Jimenez says:

    June 27, 2014

    A shame, it seems Bitbucket does not expose pull requests via the git refs. 🙁

  20. Jonas Mosbech says:

    October 3, 2014

    Troubleshooting tip that might come in handy: The GitHub user must have _write_ access to the repo in order for the PR’s merge status to update properly (at least when using the Personal Access Tokens as auth method). This caused us quite a bit of head scratching, and may be useful to others as well.

Subscribe

Subscribe for updates