Add context field to GitHubStatus updates
https://github.com/buildbot/buildbot/pull/1721
--- buildbot/status/github.py.orig
+++ buildbot/status/github.py
@@ -59,7 +60,7 @@ class GitHubStatus(StatusReceiverMultiService):
 
     def __init__(self, token, repoOwner, repoName, sha=None,
                  startDescription=None, endDescription=None,
-                 baseURL=None):
+                 baseURL=None, context=None):
         """
         Token for GitHub API.
         """
@@ -71,6 +72,7 @@ def __init__(self, token, repoOwner, repoName, sha=None,
         self._sha = sha or Interpolate("%(src::revision)s")
         self._repoOwner = repoOwner
         self._repoName = repoName
+        self._context = context or Interpolate("buildbot/%(prop:buildername)s")
         self._startDescription = startDescription or "Build started."
         self._endDescription = endDescription or "Build done."
 
@@ -166,10 +168,11 @@ def _getGitHubRepoProperties(self, build):
         """
         Return a dictionary with GitHub related properties from `build`.
         """
-        repoOwner, repoName, sha = yield defer.gatherResults([
+        repoOwner, repoName, sha, context = yield defer.gatherResults([
             build.render(self._repoOwner),
             build.render(self._repoName),
             build.render(self._sha),
+            build.render(self._context),
         ])
 
         if not repoOwner or not repoName:
@@ -185,6 +188,7 @@ def _getGitHubRepoProperties(self, build):
             'sha': sha,
             'targetURL': self._status.getURLForThing(build),
             'buildNumber': str(build.getNumber()),
+            'context': context,
         }
         defer.returnValue(result)
 
@@ -200,6 +204,7 @@ def _sendGitHubStatus(self, status):
             state=status['state'].encode('utf-8'),
             target_url=status['targetURL'].encode('utf-8'),
             description=status['description'].encode('utf-8'),
+            context=status['context'].encode('utf-8'),
         )
 
         success_message = (
--- buildbot/test/unit/test_status_github.py.orig
+++ buildbot/test/unit/test_status_github.py
@@ -132,6 +132,8 @@ def test_initialization_required_arguments(self):
         self.assertEqual(status._sha, Interpolate("%(src::revision)s"))
         self.assertEqual(status._startDescription, "Build started.")
         self.assertEqual(status._endDescription, "Build done.")
+        self.assertEqual(status._context,
+                         Interpolate("buildbot/%(prop:buildername)s"))
 
     def test_custom_github_url(self):
         """
@@ -271,6 +273,7 @@ def test_sendStartStatus_ok(self):
             'sha': '123',
             'targetURL': 'http://example.tld',
             'buildNumber': '1',
+            'context': 'context',
         }
         self.status._sendGitHubStatus = Mock(return_value=defer.succeed(None))
         self.build.getTimes = lambda: (1, None)
@@ -286,6 +289,7 @@ def test_sendStartStatus_ok(self):
             'sha': '123',
             'targetURL': 'http://example.tld',
             'buildNumber': '1',
+            'context': 'context',
             # Augmented arguments.
             'state': 'pending',
             'description': 'Build started.',
@@ -330,6 +334,7 @@ def test_sendFinishStatus_ok(self):
             'sha': '123',
             'targetURL': 'http://example.tld',
             'buildNumber': '1',
+            'context': 'context',
         }
         self.status._sendGitHubStatus = Mock(return_value=defer.succeed(None))
         self.build.getTimes = lambda: (1, 3)
@@ -346,6 +351,7 @@ def test_sendFinishStatus_ok(self):
             'sha': '123',
             'targetURL': 'http://example.tld',
             'buildNumber': '1',
+            'context': 'context',
             # Augmented arguments.
             'state': 'success',
             'description': 'Build done.',
@@ -398,6 +404,7 @@ def test_getGitHubRepoProperties_ok(self):
         self.status._repoOwner = Interpolate('owner')
         self.status._repoName = Interpolate('name')
         self.status._sha = Interpolate('sha')
+        self.status._context = Interpolate('context')
         self.status._status = Mock()
         self.status._status.getURLForThing = lambda build: 'http://example.org'
         self.build.getNumber = lambda: 1
@@ -411,8 +418,8 @@ def test_getGitHubRepoProperties_ok(self):
             'repoOwner': 'owner',
             'sha': 'sha',
             'targetURL': 'http://example.org',
-        },
-            result)
+            'context': 'context',
+        }, result)
 
     def test_getGitHubState(self):
         """
@@ -435,6 +442,7 @@ def test_sendGitHubStatus_success(self):
             'state': u'state-resum\xe9',
             'targetURL': u'targetURL-resum\xe9',
             'description': u'description-resum\xe9',
+            'context': u'context-resum\xe9',
         }
         self.status._github.repos.createStatus = Mock(
             return_value=defer.succeed(None))
@@ -450,6 +458,7 @@ def test_sendGitHubStatus_success(self):
             state='state-resum\xc3\xa9',
             target_url='targetURL-resum\xc3\xa9',
             description='description-resum\xc3\xa9',
+            context='context-resum\xc3\xa9',
         )
 
         self.assertLog(
@@ -468,6 +477,7 @@ def test_sendGitHubStatus_error(self):
             'state': u'state',
             'targetURL': u'targetURL',
             'description': u'description',
+            'context': u'context',
         }
         error = MarkerError('fail-send-status')
         self.status._github.repos.createStatus = Mock(
--- docs/manual/cfg-statustargets.rst.orig
+++ docs/manual/cfg-statustargets.rst
@@ -1564,10 +1564,12 @@
     repoOwner = util.Interpolate("%(prop:github_repo_owner)s")
     repoName = util.Interpolate("%(prop:github_repo_name)s")
     sha = util.Interpolate("%(src::revision)s")
+    context = util.Interpolate("buildbot/%(prop:buildername)s")
     gs = status.GitHubStatus(token='githubAPIToken',
                              repoOwner=repoOwner,
                              repoName=repoName,
                              sha=sha,
+                             context=context,
                              startDescription='Build started.',
                              endDescription='Build done.')
     buildbot_bbtools = util.BuilderConfig(
@@ -1599,6 +1601,9 @@
 
 In case any of `repoOwner`, `repoName` or `sha` returns `None`, `False` or empty string, the plugin will skip sending the status.
 
+The `context` argument is passed to GitHub to differentiate between statuses. A static string can be passed or :class:`Interpolate` for dynamic substitution.
+The default context is `buildbot/%(prop:buildername)s`.
+
 You can define custom start and end build messages using the `startDescription` and `endDescription` optional interpolation arguments.
 
 Starting with Buildbot version 0.8.11, :class:`GitHubStatus` supports additional parameter -- ``baseURL`` -- that allows to specify a different API base endpoint.