diff --git a/README.rst b/README.rst index efd90256..619447cc 100644 --- a/README.rst +++ b/README.rst @@ -20,6 +20,7 @@ Starting today (September 5th, 2013), we now need more than 8 bits to store the ----------------------------------------------------------------------------------------------------------- * `Implement `_ ``Github.get_hook(name)``. Thank you `klmitch `_ for asking +* In case bad data is returned by Github API v3, `raise `_ an exception only when the user accesses the faulty attribute, not when constructing the object containing this attribute. Thank you `klmitch `_ for asking What's missing? =============== diff --git a/doc/utilities.rst b/doc/utilities.rst index ed286cef..7bcba900 100644 --- a/doc/utilities.rst +++ b/doc/utilities.rst @@ -9,11 +9,7 @@ Logging Error Handling -------------- -.. autoclass:: github.GithubException.GithubException() -.. autoclass:: github.GithubException.BadCredentialsException() -.. autoclass:: github.GithubException.UnknownObjectException() -.. autoclass:: github.GithubException.BadUserAgentException() -.. autoclass:: github.GithubException.RateLimitExceededException() +.. automodule:: github.GithubException Default argument ---------------- diff --git a/github/GithubException.py b/github/GithubException.py index 02e7a75e..26057f41 100644 --- a/github/GithubException.py +++ b/github/GithubException.py @@ -27,7 +27,7 @@ class GithubException(Exception): """ - Error handling in PyGithub is done with exceptions. This class is the base of all exceptions raised by PyGithub. + Error handling in PyGithub is done with exceptions. This class is the base of all exceptions raised by PyGithub (but :class:`github.GithubException.BadAttributeException`). Some other types of exceptions might be raised by underlying libraries, for example for network-related issues. """ @@ -77,3 +77,34 @@ class RateLimitExceededException(GithubException): """ Exception raised when the rate limit is exceeded (when Github API replies with a 403 rate limit exceeded HTML status) """ + + +class BadAttributeException(Exception): + """ + Exception raised when Github returns an attribute with the wrong type. + """ + def __init__(self, actualValue, expectedType, transformationException): + self.__actualValue = actualValue + self.__expectedType = expectedType + self.__transformationException = transformationException + + @property + def actual_value(self): + """ + The value returned by Github + """ + return self.__actualValue + + @property + def expected_type(self): + """ + The type PyGithub expected + """ + return self.__expectedType + + @property + def transformation_exception(self): + """ + The exception raised when PyGithub tried to parse the value + """ + return self.__transformationException diff --git a/github/GithubObject.py b/github/GithubObject.py index 342cfbac..fa4eaa78 100644 --- a/github/GithubObject.py +++ b/github/GithubObject.py @@ -38,11 +38,22 @@ class _NotSetType: NotSet = _NotSetType() -class ValuedAttribute: +class _ValuedAttribute: def __init__(self, value): self.value = value +class _BadAttribute: + def __init__(self, value, expectedType, exception=None): + self.__value = value + self.__expectedType = expectedType + self.__exception = exception + + @property + def value(self): + raise GithubException.BadAttributeException(self.__value, self.__expectedType, self.__exception) + + class GithubObject(object): """ Base class for all classes representing objects returned by the API. @@ -97,48 +108,28 @@ class GithubObject(object): @staticmethod def __makeSimpleAttribute(value, type): if value is None or isinstance(value, type): - return ValuedAttribute(value) + return _ValuedAttribute(value) else: - return BadAttribute(value, type) + return _BadAttribute(value, type) @staticmethod def __makeSimpleListAttribute(value, type): if isinstance(value, list) and all(isinstance(element, type) for element in value): - return ValuedAttribute(value) + return _ValuedAttribute(value) else: - return BadAttribute(value, type) + return _BadAttribute(value, [type]) @staticmethod def __makeTransformedAttribute(value, type, transform): if value is None: - return ValuedAttribute(None) + return _ValuedAttribute(None) elif isinstance(value, type): try: - return ValuedAttribute(transform(value)) - except exception, e: - return BadAttribute(value, type, e) + return _ValuedAttribute(transform(value)) + except Exception, e: + return _BadAttribute(value, type, e) else: - return BadAttribute(value, type) - - @staticmethod - def __makeTransformedListAttribute(value, type, transform): - if isinstance(value, list) and all(isinstance(element, type) for element in value): - try: - return ValuedAttribute([transform(element) for element in value]) - except exception, e: - return BadAttribute(value, type, e) - else: - return BadAttribute(value, type) - - @staticmethod - def __makeTransformedDictAttribute(value, keyType, type, transform): - if isinstance(value, dict) and all(isinstance(key, keyType) and isinstance(element, type) for key, element in value.iteritems()): - try: - return ValuedAttribute(dict((key, transform(element)) for key, element in value.iteritems())) - except exception, e: - return BadAttribute(value, type, e) - else: - return BadAttribute(value, type) + return _BadAttribute(value, type) @staticmethod def _makeStringAttribute(value): @@ -184,10 +175,16 @@ class GithubObject(object): return GithubObject.__makeSimpleListAttribute(value, list) def _makeListOfClassesAttribute(self, klass, value): - return GithubObject.__makeTransformedListAttribute(value, dict, lambda value: klass(self._requester, self._headers, value, completed=False)) + if isinstance(value, list) and all(isinstance(element, dict) for element in value): + return _ValuedAttribute([klass(self._requester, self._headers, element, completed=False) for element in value]) + else: + return _BadAttribute(value, [dict]) def _makeDictOfStringsToClassesAttribute(self, klass, value): - return GithubObject.__makeTransformedDictAttribute(value, (str, unicode), dict, lambda value: klass(self._requester, self._headers, value, completed=False)) + if isinstance(value, dict) and all(isinstance(key, (str, unicode)) and isinstance(element, dict) for key, element in value.iteritems()): + return _ValuedAttribute(dict((key, klass(self._requester, self._headers, element, completed=False)) for key, element in value.iteritems())) + else: + return _BadAttribute(value, {(str, unicode): dict}) @property def etag(self): diff --git a/github/Issue.py b/github/Issue.py index 878dcaa2..c6872ccd 100644 --- a/github/Issue.py +++ b/github/Issue.py @@ -173,7 +173,7 @@ class Issue(github.GithubObject.CompletableGithubObject): if self._repository is github.GithubObject.NotSet: # The repository was not set automatically, so it must be looked up by url. repo_url = "/".join(self.url.split("/")[:-2]) - self._repository = github.GithubObject.ValuedAttribute(github.Repository.Repository(self._requester, self._headers, {'url': repo_url}, completed=False)) + self._repository = github.GithubObject._ValuedAttribute(github.Repository.Repository(self._requester, self._headers, {'url': repo_url}, completed=False)) return self._repository.value @property diff --git a/github/__init__.py b/github/__init__.py index 6a93391f..c86c41ad 100644 --- a/github/__init__.py +++ b/github/__init__.py @@ -34,7 +34,7 @@ All classes inherit from :class:`github.GithubObject.GithubObject`. import logging from MainClass import Github -from GithubException import GithubException, BadCredentialsException, UnknownObjectException, BadUserAgentException, RateLimitExceededException +from GithubException import GithubException, BadCredentialsException, UnknownObjectException, BadUserAgentException, RateLimitExceededException, BadAttributeException from InputFileContent import InputFileContent from InputGitAuthor import InputGitAuthor from InputGitTreeElement import InputGitTreeElement diff --git a/github/tests/AllTests.py b/github/tests/AllTests.py index f2f5c54b..36f9b85a 100644 --- a/github/tests/AllTests.py +++ b/github/tests/AllTests.py @@ -70,6 +70,7 @@ from RawData import * from ConditionalRequestUpdate import * from Persistence import * from ExposeAllAttributes import * +from BadAttributes import * from Issue33 import * from Issue50 import * diff --git a/github/tests/BadAttributes.py b/github/tests/BadAttributes.py new file mode 100755 index 00000000..fac9ab91 --- /dev/null +++ b/github/tests/BadAttributes.py @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- + +############################ Copyrights and license ############################ +# # +# Copyright 2013 Vincent Jacques # +# # +# This file is part of PyGithub. http://jacquev6.github.com/PyGithub/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +import datetime + +import Framework +import github + + +# Replay data is forged to simulate bad things returned by Github +class BadAttributes(Framework.TestCase): + def testBadSimpleAttribute(self): + user = self.g.get_user("klmitch") + self.assertEqual(user.created_at, datetime.datetime(2011, 3, 23, 15, 42, 9)) + + raised = False + try: + user.name + except github.BadAttributeException, e: + raised = True + self.assertEqual(e.actual_value, 42) + self.assertEqual(e.expected_type, (str, unicode)) + self.assertIsNone(e.transformation_exception) + self.assertTrue(raised) + + def testBadAttributeTransformation(self): + user = self.g.get_user("klmitch") + self.assertEqual(user.name, "Kevin L. Mitchell") + + raised = False + try: + user.created_at + except github.BadAttributeException, e: + raised = True + self.assertEqual(e.actual_value, "foobar") + self.assertEqual(e.expected_type, (str, unicode)) + self.assertEqual(e.transformation_exception.__class__, ValueError) + self.assertEqual(e.transformation_exception.args, ("time data 'foobar' does not match format '%Y-%m-%dT%H:%M:%SZ'",)) + self.assertTrue(raised) + + def testBadTransformedAttribute(self): + user = self.g.get_user("klmitch") + self.assertEqual(user.name, "Kevin L. Mitchell") + + raised = False + try: + user.updated_at + except github.BadAttributeException, e: + raised = True + self.assertEqual(e.actual_value, 42) + self.assertEqual(e.expected_type, (str, unicode)) + self.assertIsNone(e.transformation_exception) + self.assertTrue(raised) + + def testBadSimpleAttributeInList(self): + hook = self.g.get_hook("activecollab") + self.assertEqual(hook.name, "activecollab") + + raised = False + try: + hook.events + except github.BadAttributeException, e: + raised = True + self.assertEqual(e.actual_value, ["push", 42]) + self.assertEqual(e.expected_type, [(str, unicode)]) + self.assertIsNone(e.transformation_exception) + self.assertTrue(raised) + + def testBadAttributeInClassAttribute(self): + repo = self.g.get_repo("klmitch/turnstile") + owner = repo.owner + self.assertEqual(owner.id, 686398) + + raised = False + try: + owner.avatar_url + except github.BadAttributeException, e: + raised = True + self.assertEqual(e.actual_value, 42) + self.assertTrue(raised) + + def testBadTransformedAttributeInList(self): + commit = self.g.get_repo("klmitch/turnstile").get_commit("38d9082a898d0822b5ccdfd78f3a536e2efa6c26") + + raised = False + try: + commit.files + except github.BadAttributeException, e: + raised = True + self.assertEqual(e.actual_value, [42]) + self.assertEqual(e.expected_type, [dict]) + self.assertIsNone(e.transformation_exception) + self.assertTrue(raised) + + def testBadTransformedAttributeInDict(self): + gist = self.g.get_gist("6437766") + + raised = False + try: + gist.files + except github.BadAttributeException, e: + raised = True + self.assertEqual(e.actual_value, {"test.py": 42}) + self.assertEqual(e.expected_type, {(str, unicode): dict}) + self.assertIsNone(e.transformation_exception) + self.assertTrue(raised) + + def testIssue195(self): + hooks = self.g.get_hooks() + # We can loop on all hooks as long as we don't access circleci's events attribute + self.assertListKeyEqual(hooks, lambda h: h.name, [u'activecollab', u'acunote', u'agilebench', u'agilezen', u'amazonsns', u'apiary', u'apoio', u'appharbor', u'apropos', u'asana', u'backlog', u'bamboo', u'basecamp', u'bcx', u'blimp', u'boxcar', u'buddycloud', u'bugherd', u'bugly', u'bugzilla', u'campfire', u'cia', u'circleci', u'codeclimate', u'codeportingcsharp2java', u'codeship', u'coffeedocinfo', u'conductor', u'coop', u'copperegg', u'cube', u'depending', u'deployhq', u'devaria', u'docker', u'ducksboard', u'email', u'firebase', u'fisheye', u'flowdock', u'fogbugz', u'freckle', u'friendfeed', u'gemini', u'gemnasium', u'geocommit', u'getlocalization', u'gitlive', u'grmble', u'grouptalent', u'grove', u'habitualist', u'hakiri', u'hall', u'harvest', u'hipchat', u'hostedgraphite', u'hubcap', u'hubci', u'humbug', u'icescrum', u'irc', u'irker', u'ironmq', u'ironworker', u'jabber', u'jaconda', u'jeapie', u'jenkins', u'jenkinsgit', u'jira', u'jqueryplugins', u'kanbanery', u'kickoff', u'leanto', u'lechat', u'lighthouse', u'lingohub', u'loggly', u'mantisbt', u'masterbranch', u'mqttpub', u'nma', u'nodejitsu', u'notifo', u'ontime', u'pachube', u'packagist', u'phraseapp', u'pivotaltracker', u'planbox', u'planio', u'prowl', u'puppetlinter', u'pushalot', u'pushover', u'pythonpackages', u'railsbp', u'railsbrakeman', u'rally', u'rapidpush', u'rationaljazzhub', u'rationalteamconcert', u'rdocinfo', u'readthedocs', u'redmine', u'rubyforge', u'scrumdo', u'shiningpanda', u'sifter', u'simperium', u'slatebox', u'snowyevening', u'socialcast', u'softlayermessaging', u'sourcemint', u'splendidbacon', u'sprintly', u'sqsqueue', u'stackmob', u'statusnet', u'talker', u'targetprocess', u'tddium', u'teamcity', u'tender', u'tenxer', u'testpilot', u'toggl', u'trac', u'trajectory', u'travis', u'trello', u'twilio', u'twitter', u'unfuddle', u'web', u'weblate', u'webtranslateit', u'yammer', u'youtrack', u'zendesk', u'zohoprojects']) + for hook in hooks: + if hook.name != "circleci": + hook.events + + raised = False + for hook in hooks: + if hook.name == "circleci": + try: + hook.events + except github.BadAttributeException, e: + raised = True + self.assertEqual(e.actual_value, [["commit_comment", "create", "delete", "download", "follow", "fork", "fork_apply", "gist", "gollum", "issue_comment", "issues", "member", "public", "pull_request", "pull_request_review_comment", "push", "status", "team_add", "watch"]]) + self.assertEqual(e.expected_type, [(str, unicode)]) + self.assertIsNone(e.transformation_exception) + self.assertTrue(raised) diff --git a/github/tests/ReplayData/BadAttributes.testBadAttributeInClassAttribute.txt b/github/tests/ReplayData/BadAttributes.testBadAttributeInClassAttribute.txt new file mode 100644 index 00000000..6de4abcd --- /dev/null +++ b/github/tests/ReplayData/BadAttributes.testBadAttributeInClassAttribute.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/repos/klmitch/turnstile +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4968'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('x-github-request-id', '5351c17d-c8ac-4a49-b6f4-1dd0411bb9ae'), ('access-control-allow-credentials', 'true'), ('vary', 'Accept, Authorization, Cookie, Accept-Encoding'), ('content-length', '4587'), ('server', 'GitHub.com'), ('last-modified', 'Wed, 21 Aug 2013 16:04:54 GMT'), ('x-ratelimit-limit', '5000'), ('etag', '"aab62d006633c3842d38e20dc732a2c9"'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('date', 'Thu, 12 Sep 2013 08:38:57 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1378976739')] +{"id":3404510,"name":"turnstile","full_name":"klmitch/turnstile","owner":{"login":"klmitch","id":686398,"avatar_url":42,"gravatar_id":"3c505225c6f28a7702b318a991141495","url":"https://api.github.com/users/klmitch","html_url":"https://github.com/klmitch","followers_url":"https://api.github.com/users/klmitch/followers","following_url":"https://api.github.com/users/klmitch/following{/other_user}","gists_url":"https://api.github.com/users/klmitch/gists{/gist_id}","starred_url":"https://api.github.com/users/klmitch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/klmitch/subscriptions","organizations_url":"https://api.github.com/users/klmitch/orgs","repos_url":"https://api.github.com/users/klmitch/repos","events_url":"https://api.github.com/users/klmitch/events{/privacy}","received_events_url":"https://api.github.com/users/klmitch/received_events","type":"User"},"private":false,"html_url":"https://github.com/klmitch/turnstile","description":"A distributed rate limiting WSGI middleware.","fork":false,"url":"https://api.github.com/repos/klmitch/turnstile","forks_url":"https://api.github.com/repos/klmitch/turnstile/forks","keys_url":"https://api.github.com/repos/klmitch/turnstile/keys{/key_id}","collaborators_url":"https://api.github.com/repos/klmitch/turnstile/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/klmitch/turnstile/teams","hooks_url":"https://api.github.com/repos/klmitch/turnstile/hooks","issue_events_url":"https://api.github.com/repos/klmitch/turnstile/issues/events{/number}","events_url":"https://api.github.com/repos/klmitch/turnstile/events","assignees_url":"https://api.github.com/repos/klmitch/turnstile/assignees{/user}","branches_url":"https://api.github.com/repos/klmitch/turnstile/branches{/branch}","tags_url":"https://api.github.com/repos/klmitch/turnstile/tags","blobs_url":"https://api.github.com/repos/klmitch/turnstile/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/klmitch/turnstile/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/klmitch/turnstile/git/refs{/sha}","trees_url":"https://api.github.com/repos/klmitch/turnstile/git/trees{/sha}","statuses_url":"https://api.github.com/repos/klmitch/turnstile/statuses/{sha}","languages_url":"https://api.github.com/repos/klmitch/turnstile/languages","stargazers_url":"https://api.github.com/repos/klmitch/turnstile/stargazers","contributors_url":"https://api.github.com/repos/klmitch/turnstile/contributors","subscribers_url":"https://api.github.com/repos/klmitch/turnstile/subscribers","subscription_url":"https://api.github.com/repos/klmitch/turnstile/subscription","commits_url":"https://api.github.com/repos/klmitch/turnstile/commits{/sha}","git_commits_url":"https://api.github.com/repos/klmitch/turnstile/git/commits{/sha}","comments_url":"https://api.github.com/repos/klmitch/turnstile/comments{/number}","issue_comment_url":"https://api.github.com/repos/klmitch/turnstile/issues/comments/{number}","contents_url":"https://api.github.com/repos/klmitch/turnstile/contents/{+path}","compare_url":"https://api.github.com/repos/klmitch/turnstile/compare/{base}...{head}","merges_url":"https://api.github.com/repos/klmitch/turnstile/merges","archive_url":"https://api.github.com/repos/klmitch/turnstile/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/klmitch/turnstile/downloads","issues_url":"https://api.github.com/repos/klmitch/turnstile/issues{/number}","pulls_url":"https://api.github.com/repos/klmitch/turnstile/pulls{/number}","milestones_url":"https://api.github.com/repos/klmitch/turnstile/milestones{/number}","notifications_url":"https://api.github.com/repos/klmitch/turnstile/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/klmitch/turnstile/labels{/name}","created_at":"2012-02-10T05:16:36Z","updated_at":"2013-08-21T16:04:54Z","pushed_at":"2013-05-01T22:22:20Z","git_url":"git://github.com/klmitch/turnstile.git","ssh_url":"git@github.com:klmitch/turnstile.git","clone_url":"https://github.com/klmitch/turnstile.git","svn_url":"https://github.com/klmitch/turnstile","homepage":"","size":260,"watchers_count":15,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"forks_count":6,"mirror_url":null,"open_issues_count":1,"forks":6,"open_issues":1,"watchers":15,"master_branch":"master","default_branch":"master","permissions":{"admin":false,"push":false,"pull":true},"network_count":6} + diff --git a/github/tests/ReplayData/BadAttributes.testBadAttributeTransformation.txt b/github/tests/ReplayData/BadAttributes.testBadAttributeTransformation.txt new file mode 100755 index 00000000..4dda347f --- /dev/null +++ b/github/tests/ReplayData/BadAttributes.testBadAttributeTransformation.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/users/klmitch +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4966'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('x-github-request-id', 'b66ca3c7-84f9-455a-9db8-3df385fc7b32'), ('access-control-allow-credentials', 'true'), ('vary', 'Accept, Authorization, Cookie, Accept-Encoding'), ('content-length', '1254'), ('server', 'GitHub.com'), ('last-modified', 'Wed, 11 Sep 2013 19:26:25 GMT'), ('x-ratelimit-limit', '5000'), ('etag', '"6c1c41cdc34b6a47b3ee2a765cc51310"'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('date', 'Thu, 12 Sep 2013 08:45:34 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1378976739')] +{"login":"klmitch","id":686398,"avatar_url":"https://1.gravatar.com/avatar/3c505225c6f28a7702b318a991141495?d=https%3A%2F%2Fidenticons.github.com%2Ffffa0f2e30bad5753edbb60f250b7cbe.png","gravatar_id":"3c505225c6f28a7702b318a991141495","url":"https://api.github.com/users/klmitch","html_url":"https://github.com/klmitch","followers_url":"https://api.github.com/users/klmitch/followers","following_url":"https://api.github.com/users/klmitch/following{/other_user}","gists_url":"https://api.github.com/users/klmitch/gists{/gist_id}","starred_url":"https://api.github.com/users/klmitch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/klmitch/subscriptions","organizations_url":"https://api.github.com/users/klmitch/orgs","repos_url":"https://api.github.com/users/klmitch/repos","events_url":"https://api.github.com/users/klmitch/events{/privacy}","received_events_url":"https://api.github.com/users/klmitch/received_events","type":"User","name":"Kevin L. Mitchell","company":"Rackspace","blog":null,"location":"San Antonio, TX","email":"kevin.mitchell@rackspace.com","hireable":false,"bio":null,"public_repos":29,"followers":15,"following":18,"created_at":"foobar","updated_at":42,"public_gists":0} + diff --git a/github/tests/ReplayData/BadAttributes.testBadSimpleAttribute.txt b/github/tests/ReplayData/BadAttributes.testBadSimpleAttribute.txt new file mode 100644 index 00000000..c04566d1 --- /dev/null +++ b/github/tests/ReplayData/BadAttributes.testBadSimpleAttribute.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/users/klmitch +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4970'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('x-github-request-id', '678fcfc5-140a-4d38-be2f-09ebbd8bb58d'), ('access-control-allow-credentials', 'true'), ('vary', 'Accept, Authorization, Cookie, Accept-Encoding'), ('content-length', '1254'), ('server', 'GitHub.com'), ('last-modified', 'Wed, 11 Sep 2013 19:26:25 GMT'), ('x-ratelimit-limit', '5000'), ('etag', '"6c1c41cdc34b6a47b3ee2a765cc51310"'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('date', 'Thu, 12 Sep 2013 08:21:32 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1378976739')] +{"login":"klmitch","id":686398,"avatar_url":"https://2.gravatar.com/avatar/3c505225c6f28a7702b318a991141495?d=https%3A%2F%2Fidenticons.github.com%2Ffffa0f2e30bad5753edbb60f250b7cbe.png","gravatar_id":"3c505225c6f28a7702b318a991141495","url":"https://api.github.com/users/klmitch","html_url":"https://github.com/klmitch","followers_url":"https://api.github.com/users/klmitch/followers","following_url":"https://api.github.com/users/klmitch/following{/other_user}","gists_url":"https://api.github.com/users/klmitch/gists{/gist_id}","starred_url":"https://api.github.com/users/klmitch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/klmitch/subscriptions","organizations_url":"https://api.github.com/users/klmitch/orgs","repos_url":"https://api.github.com/users/klmitch/repos","events_url":"https://api.github.com/users/klmitch/events{/privacy}","received_events_url":"https://api.github.com/users/klmitch/received_events","type":"User","name":42,"company":"Rackspace","blog":null,"location":"San Antonio, TX","email":"kevin.mitchell@rackspace.com","hireable":false,"bio":null,"public_repos":29,"followers":15,"following":18,"created_at":"2011-03-23T15:42:09Z","updated_at":"2013-09-11T19:26:25Z","public_gists":0} + diff --git a/github/tests/ReplayData/BadAttributes.testBadSimpleAttributeInList.txt b/github/tests/ReplayData/BadAttributes.testBadSimpleAttributeInList.txt new file mode 100644 index 00000000..8c8603d0 --- /dev/null +++ b/github/tests/ReplayData/BadAttributes.testBadSimpleAttributeInList.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/hooks/activecollab +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4969'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('x-github-request-id', 'fd44f8b6-d47d-44c5-a365-cd7bf9569c88'), ('access-control-allow-credentials', 'true'), ('vary', 'Accept, Authorization, Cookie, Accept-Encoding'), ('content-length', '191'), ('server', 'GitHub.com'), ('last-modified', 'Wed, 04 Sep 2013 18:03:57 GMT'), ('x-ratelimit-limit', '5000'), ('etag', '"678dd8e392d70d3a284c3d47221ec6f0"'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('date', 'Thu, 12 Sep 2013 08:31:46 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1378976739')] +{"name":"activecollab","events":["push", 42],"supported_events":["push"],"schema":[["string","url"],["string","token"],["string","project_id"],["string","milestone_id"],["string","category_id"]]} + diff --git a/github/tests/ReplayData/BadAttributes.testBadTransformedAttribute.txt b/github/tests/ReplayData/BadAttributes.testBadTransformedAttribute.txt new file mode 100644 index 00000000..4dda347f --- /dev/null +++ b/github/tests/ReplayData/BadAttributes.testBadTransformedAttribute.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/users/klmitch +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4966'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('x-github-request-id', 'b66ca3c7-84f9-455a-9db8-3df385fc7b32'), ('access-control-allow-credentials', 'true'), ('vary', 'Accept, Authorization, Cookie, Accept-Encoding'), ('content-length', '1254'), ('server', 'GitHub.com'), ('last-modified', 'Wed, 11 Sep 2013 19:26:25 GMT'), ('x-ratelimit-limit', '5000'), ('etag', '"6c1c41cdc34b6a47b3ee2a765cc51310"'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('date', 'Thu, 12 Sep 2013 08:45:34 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1378976739')] +{"login":"klmitch","id":686398,"avatar_url":"https://1.gravatar.com/avatar/3c505225c6f28a7702b318a991141495?d=https%3A%2F%2Fidenticons.github.com%2Ffffa0f2e30bad5753edbb60f250b7cbe.png","gravatar_id":"3c505225c6f28a7702b318a991141495","url":"https://api.github.com/users/klmitch","html_url":"https://github.com/klmitch","followers_url":"https://api.github.com/users/klmitch/followers","following_url":"https://api.github.com/users/klmitch/following{/other_user}","gists_url":"https://api.github.com/users/klmitch/gists{/gist_id}","starred_url":"https://api.github.com/users/klmitch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/klmitch/subscriptions","organizations_url":"https://api.github.com/users/klmitch/orgs","repos_url":"https://api.github.com/users/klmitch/repos","events_url":"https://api.github.com/users/klmitch/events{/privacy}","received_events_url":"https://api.github.com/users/klmitch/received_events","type":"User","name":"Kevin L. Mitchell","company":"Rackspace","blog":null,"location":"San Antonio, TX","email":"kevin.mitchell@rackspace.com","hireable":false,"bio":null,"public_repos":29,"followers":15,"following":18,"created_at":"foobar","updated_at":42,"public_gists":0} + diff --git a/github/tests/ReplayData/BadAttributes.testBadTransformedAttributeInDict.txt b/github/tests/ReplayData/BadAttributes.testBadTransformedAttributeInDict.txt new file mode 100644 index 00000000..461bfb0a --- /dev/null +++ b/github/tests/ReplayData/BadAttributes.testBadTransformedAttributeInDict.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/gists/6437766 +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4996'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('x-github-request-id', '8131a430-28c1-45bb-a5b7-09fcdabc5dc7'), ('access-control-allow-credentials', 'true'), ('vary', 'Accept, Authorization, Cookie, Accept-Encoding'), ('content-length', '2933'), ('server', 'GitHub.com'), ('last-modified', 'Thu, 12 Sep 2013 00:23:35 GMT'), ('x-ratelimit-limit', '5000'), ('etag', '"b3954ac942969f1e10c24ec5b5ec04d3"'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('date', 'Thu, 12 Sep 2013 09:25:36 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1378980564')] +{"url":"https://api.github.com/gists/6437766","forks_url":"https://api.github.com/gists/6437766/forks","commits_url":"https://api.github.com/gists/6437766/commits","id":"6437766","git_pull_url":"https://gist.github.com/6437766.git","git_push_url":"https://gist.github.com/6437766.git","html_url":"https://gist.github.com/6437766","files":{"test.py":42},"public":true,"created_at":"2013-09-04T14:30:47Z","updated_at":"2013-09-04T14:30:48Z","description":"Test script for https://github.com/jacquev6/PyGithub/issues/194","comments":0,"user":{"login":"jacquev6","id":327146,"avatar_url":"https://1.gravatar.com/avatar/b68de5ae38616c296fa345d2b9df2225?d=https%3A%2F%2Fidenticons.github.com%2Ffadfb5f7088ef66579d198a3c9a4935e.png","gravatar_id":"b68de5ae38616c296fa345d2b9df2225","url":"https://api.github.com/users/jacquev6","html_url":"https://github.com/jacquev6","followers_url":"https://api.github.com/users/jacquev6/followers","following_url":"https://api.github.com/users/jacquev6/following{/other_user}","gists_url":"https://api.github.com/users/jacquev6/gists{/gist_id}","starred_url":"https://api.github.com/users/jacquev6/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jacquev6/subscriptions","organizations_url":"https://api.github.com/users/jacquev6/orgs","repos_url":"https://api.github.com/users/jacquev6/repos","events_url":"https://api.github.com/users/jacquev6/events{/privacy}","received_events_url":"https://api.github.com/users/jacquev6/received_events","type":"User"},"comments_url":"https://api.github.com/gists/6437766/comments","forks":[],"history":[{"user":null,"version":"5aa7a28e0a1dc6acf5a70de66e189f73f01735f4","committed_at":"2013-09-04T14:30:47Z","change_status":{"total":24,"additions":24,"deletions":0},"url":"https://api.github.com/gists/6437766/5aa7a28e0a1dc6acf5a70de66e189f73f01735f4"}]} + diff --git a/github/tests/ReplayData/BadAttributes.testBadTransformedAttributeInList.txt b/github/tests/ReplayData/BadAttributes.testBadTransformedAttributeInList.txt new file mode 100644 index 00000000..33678ebc --- /dev/null +++ b/github/tests/ReplayData/BadAttributes.testBadTransformedAttributeInList.txt @@ -0,0 +1,22 @@ +https +GET +api.github.com +None +/repos/klmitch/turnstile +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4999'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('x-github-request-id', 'b9d67757-009d-4a30-9854-f41e04681849'), ('access-control-allow-credentials', 'true'), ('vary', 'Accept, Authorization, Cookie, Accept-Encoding'), ('content-length', '4587'), ('server', 'GitHub.com'), ('last-modified', 'Wed, 21 Aug 2013 16:04:54 GMT'), ('x-ratelimit-limit', '5000'), ('etag', '"aab62d006633c3842d38e20dc732a2c9"'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('date', 'Thu, 12 Sep 2013 09:09:24 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1378980564')] +{"id":3404510,"name":"turnstile","full_name":"klmitch/turnstile","owner":{"login":"klmitch","id":686398,"avatar_url":"https://1.gravatar.com/avatar/3c505225c6f28a7702b318a991141495?d=https%3A%2F%2Fidenticons.github.com%2Ffffa0f2e30bad5753edbb60f250b7cbe.png","gravatar_id":"3c505225c6f28a7702b318a991141495","url":"https://api.github.com/users/klmitch","html_url":"https://github.com/klmitch","followers_url":"https://api.github.com/users/klmitch/followers","following_url":"https://api.github.com/users/klmitch/following{/other_user}","gists_url":"https://api.github.com/users/klmitch/gists{/gist_id}","starred_url":"https://api.github.com/users/klmitch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/klmitch/subscriptions","organizations_url":"https://api.github.com/users/klmitch/orgs","repos_url":"https://api.github.com/users/klmitch/repos","events_url":"https://api.github.com/users/klmitch/events{/privacy}","received_events_url":"https://api.github.com/users/klmitch/received_events","type":"User"},"private":false,"html_url":"https://github.com/klmitch/turnstile","description":"A distributed rate limiting WSGI middleware.","fork":false,"url":"https://api.github.com/repos/klmitch/turnstile","forks_url":"https://api.github.com/repos/klmitch/turnstile/forks","keys_url":"https://api.github.com/repos/klmitch/turnstile/keys{/key_id}","collaborators_url":"https://api.github.com/repos/klmitch/turnstile/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/klmitch/turnstile/teams","hooks_url":"https://api.github.com/repos/klmitch/turnstile/hooks","issue_events_url":"https://api.github.com/repos/klmitch/turnstile/issues/events{/number}","events_url":"https://api.github.com/repos/klmitch/turnstile/events","assignees_url":"https://api.github.com/repos/klmitch/turnstile/assignees{/user}","branches_url":"https://api.github.com/repos/klmitch/turnstile/branches{/branch}","tags_url":"https://api.github.com/repos/klmitch/turnstile/tags","blobs_url":"https://api.github.com/repos/klmitch/turnstile/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/klmitch/turnstile/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/klmitch/turnstile/git/refs{/sha}","trees_url":"https://api.github.com/repos/klmitch/turnstile/git/trees{/sha}","statuses_url":"https://api.github.com/repos/klmitch/turnstile/statuses/{sha}","languages_url":"https://api.github.com/repos/klmitch/turnstile/languages","stargazers_url":"https://api.github.com/repos/klmitch/turnstile/stargazers","contributors_url":"https://api.github.com/repos/klmitch/turnstile/contributors","subscribers_url":"https://api.github.com/repos/klmitch/turnstile/subscribers","subscription_url":"https://api.github.com/repos/klmitch/turnstile/subscription","commits_url":"https://api.github.com/repos/klmitch/turnstile/commits{/sha}","git_commits_url":"https://api.github.com/repos/klmitch/turnstile/git/commits{/sha}","comments_url":"https://api.github.com/repos/klmitch/turnstile/comments{/number}","issue_comment_url":"https://api.github.com/repos/klmitch/turnstile/issues/comments/{number}","contents_url":"https://api.github.com/repos/klmitch/turnstile/contents/{+path}","compare_url":"https://api.github.com/repos/klmitch/turnstile/compare/{base}...{head}","merges_url":"https://api.github.com/repos/klmitch/turnstile/merges","archive_url":"https://api.github.com/repos/klmitch/turnstile/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/klmitch/turnstile/downloads","issues_url":"https://api.github.com/repos/klmitch/turnstile/issues{/number}","pulls_url":"https://api.github.com/repos/klmitch/turnstile/pulls{/number}","milestones_url":"https://api.github.com/repos/klmitch/turnstile/milestones{/number}","notifications_url":"https://api.github.com/repos/klmitch/turnstile/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/klmitch/turnstile/labels{/name}","created_at":"2012-02-10T05:16:36Z","updated_at":"2013-08-21T16:04:54Z","pushed_at":"2013-05-01T22:22:20Z","git_url":"git://github.com/klmitch/turnstile.git","ssh_url":"git@github.com:klmitch/turnstile.git","clone_url":"https://github.com/klmitch/turnstile.git","svn_url":"https://github.com/klmitch/turnstile","homepage":"","size":260,"watchers_count":15,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"forks_count":6,"mirror_url":null,"open_issues_count":1,"forks":6,"open_issues":1,"watchers":15,"master_branch":"master","default_branch":"master","permissions":{"admin":false,"push":false,"pull":true},"network_count":6} + +https +GET +api.github.com +None +/repos/klmitch/turnstile/commits/38d9082a898d0822b5ccdfd78f3a536e2efa6c26 +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4998'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('x-github-request-id', '205eb9ed-a173-47a2-b670-16ec266adef5'), ('access-control-allow-credentials', 'true'), ('vary', 'Accept, Authorization, Cookie, Accept-Encoding'), ('content-length', '6111'), ('server', 'GitHub.com'), ('last-modified', 'Wed, 01 May 2013 19:03:50 GMT'), ('x-ratelimit-limit', '5000'), ('etag', '"50a14a79f7095a8d4fed16d05a4b1412"'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('date', 'Thu, 12 Sep 2013 09:09:25 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1378980564')] +{"sha":"38d9082a898d0822b5ccdfd78f3a536e2efa6c26","commit":{"author":{"name":"Kevin L. Mitchell","email":"kevin.mitchell@rackspace.com","date":"2013-05-01T19:03:50Z"},"committer":{"name":"Kevin L. Mitchell","email":"kevin.mitchell@rackspace.com","date":"2013-05-01T19:03:50Z"},"message":"Ignore empty configuration values for extra database arguments\n\nTurnstile's functionality to allow the control daemon and the\ncompactor daemon to use different Redis configuration provides\none problem: values that are set in the \"[redis]\" section are\ninherited by all sections, even when that is not desired. To\ncombat this, we now allow an empty value to completely delete\nthe key from the redis configuration in Config.get_database().","tree":{"sha":"83b8ab73bedb67846b47533d1bac7767ac325dc8","url":"https://api.github.com/repos/klmitch/turnstile/git/trees/83b8ab73bedb67846b47533d1bac7767ac325dc8"},"url":"https://api.github.com/repos/klmitch/turnstile/git/commits/38d9082a898d0822b5ccdfd78f3a536e2efa6c26","comment_count":0},"url":"https://api.github.com/repos/klmitch/turnstile/commits/38d9082a898d0822b5ccdfd78f3a536e2efa6c26","html_url":"https://github.com/klmitch/turnstile/commit/38d9082a898d0822b5ccdfd78f3a536e2efa6c26","comments_url":"https://api.github.com/repos/klmitch/turnstile/commits/38d9082a898d0822b5ccdfd78f3a536e2efa6c26/comments","author":{"login":"klmitch","id":686398,"avatar_url":"https://1.gravatar.com/avatar/3c505225c6f28a7702b318a991141495?d=https%3A%2F%2Fidenticons.github.com%2Ffffa0f2e30bad5753edbb60f250b7cbe.png","gravatar_id":"3c505225c6f28a7702b318a991141495","url":"https://api.github.com/users/klmitch","html_url":"https://github.com/klmitch","followers_url":"https://api.github.com/users/klmitch/followers","following_url":"https://api.github.com/users/klmitch/following{/other_user}","gists_url":"https://api.github.com/users/klmitch/gists{/gist_id}","starred_url":"https://api.github.com/users/klmitch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/klmitch/subscriptions","organizations_url":"https://api.github.com/users/klmitch/orgs","repos_url":"https://api.github.com/users/klmitch/repos","events_url":"https://api.github.com/users/klmitch/events{/privacy}","received_events_url":"https://api.github.com/users/klmitch/received_events","type":"User"},"committer":{"login":"klmitch","id":686398,"avatar_url":"https://1.gravatar.com/avatar/3c505225c6f28a7702b318a991141495?d=https%3A%2F%2Fidenticons.github.com%2Ffffa0f2e30bad5753edbb60f250b7cbe.png","gravatar_id":"3c505225c6f28a7702b318a991141495","url":"https://api.github.com/users/klmitch","html_url":"https://github.com/klmitch","followers_url":"https://api.github.com/users/klmitch/followers","following_url":"https://api.github.com/users/klmitch/following{/other_user}","gists_url":"https://api.github.com/users/klmitch/gists{/gist_id}","starred_url":"https://api.github.com/users/klmitch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/klmitch/subscriptions","organizations_url":"https://api.github.com/users/klmitch/orgs","repos_url":"https://api.github.com/users/klmitch/repos","events_url":"https://api.github.com/users/klmitch/events{/privacy}","received_events_url":"https://api.github.com/users/klmitch/received_events","type":"User"},"parents":[{"sha":"e649bcaa580248de40ef6c126fe446a3da514312","url":"https://api.github.com/repos/klmitch/turnstile/commits/e649bcaa580248de40ef6c126fe446a3da514312","html_url":"https://github.com/klmitch/turnstile/commit/e649bcaa580248de40ef6c126fe446a3da514312"}],"stats":{"total":9,"additions":7,"deletions":2},"files":[42]} + diff --git a/github/tests/ReplayData/BadAttributes.testIssue195.txt b/github/tests/ReplayData/BadAttributes.testIssue195.txt new file mode 100644 index 00000000..6d558a0d --- /dev/null +++ b/github/tests/ReplayData/BadAttributes.testIssue195.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/hooks +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4994'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('access-control-expose-headers', 'ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes'), ('x-github-request-id', 'beb27389-3e55-40c9-b2e7-718b4f647721'), ('access-control-allow-credentials', 'true'), ('vary', 'Accept, Authorization, Cookie, Accept-Encoding'), ('content-length', '28297'), ('server', 'GitHub.com'), ('last-modified', 'Wed, 04 Sep 2013 18:03:57 GMT'), ('x-ratelimit-limit', '5000'), ('etag', '"678dd8e392d70d3a284c3d47221ec6f0"'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('date', 'Thu, 12 Sep 2013 09:34:49 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1378980564')] +[{"name":"activecollab","events":["push"],"supported_events":["push"],"schema":[["string","url"],["string","token"],["string","project_id"],["string","milestone_id"],["string","category_id"]]},{"name":"acunote","events":["push"],"supported_events":["push"],"schema":[["string","token"]]},{"name":"agilebench","events":["push"],"supported_events":["push"],"schema":[["string","token"],["string","project_id"]]},{"name":"agilezen","events":["push"],"supported_events":["push"],"schema":[["string","api_key"],["string","project_id"],["string","branches"]]},{"name":"amazonsns","events":["push"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","aws_key"],["string","aws_secret"],["string","sns_topic"],["string","sqs_queue"],["password","aws_secret"]]},{"name":"apiary","events":["push"],"supported_events":["push"],"schema":[["string","branch"],["string","domain"]]},{"name":"apoio","events":["issues"],"supported_events":["issues"],"schema":[["string","subdomain"],["string","token"]]},{"name":"appharbor","events":["push"],"supported_events":["push"],"schema":[["string","application_slug"],["string","token"]]},{"name":"apropos","events":["commit_comment","issues","issue_comment","pull_request","push"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","project_id"]]},{"name":"asana","events":["push"],"supported_events":["push"],"schema":[["string","auth_token"],["string","restrict_to_branch"],["boolean","restrict_to_last_commit"]]},{"name":"backlog","events":["push"],"supported_events":["push"],"schema":[["string","api_url"],["string","user_id"],["password","password"]]},{"name":"bamboo","events":["push"],"supported_events":["push"],"schema":[["string","base_url"],["string","build_key"],["string","username"],["password","password"]]},{"name":"basecamp","events":["push"],"supported_events":["push"],"schema":[["string","url"],["string","project"],["string","category"],["string","username"],["password","password"],["boolean","ssl"]]},{"name":"bcx","events":["push","pull_request","issues"],"supported_events":["issues","pull_request","push"],"schema":[["string","project_url"],["string","email_address"],["password","password"]]},{"name":"blimp","events":["issues","issue_comment"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","project_url"],["string","username"],["string","goal_title"],["password","api_key"]]},{"name":"boxcar","events":["push"],"supported_events":["push"],"schema":[["string","subscribers"]]},{"name":"buddycloud","events":["push"],"supported_events":["push"],"schema":[["string","buddycloud_base_api"],["string","username"],["string","password"],["string","channel"],["password","password"],["boolean","show_commit_summary"],["boolean","show_commit_detail"]]},{"name":"bugherd","events":["issues","issue_comment","push"],"supported_events":["issue_comment","issues","push"],"schema":[["string","project_key"]]},{"name":"bugly","events":["push"],"supported_events":["push"],"schema":[["string","project_id"],["string","account_name"],["string","token"]]},{"name":"bugzilla","events":["push"],"supported_events":["push"],"schema":[["string","server_url"],["string","username"],["string","integration_branch"],["password","password"],["boolean","central_repository"]]},{"name":"campfire","events":["push","pull_request","issues"],"supported_events":["gollum","issues","public","pull_request","push"],"schema":[["string","subdomain"],["string","room"],["string","token"],["string","sound"],["boolean","master_only"],["boolean","play_sound"],["boolean","long_url"]]},{"name":"cia","events":["push"],"supported_events":["push"],"schema":[["string","address"],["string","project"],["string","branch"],["string","module"],["boolean","long_url"],["boolean","full_commits"]]},{"name":"circleci","events":[["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"]],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[]},{"name":"codeclimate","events":["push"],"supported_events":["push"],"schema":[["string","token"]]},{"name":"codeportingcsharp2java","events":["push"],"supported_events":["push"],"schema":[["string","project_name"],["string","repo_key"],["string","target_repo_key"],["string","codeporting_username"],["password","codeporting_password"],["string","github_access_token"]]},{"name":"codeship","events":["push"],"supported_events":["push"],"schema":[["string","project_uuid"]]},{"name":"coffeedocinfo","events":["push"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[]},{"name":"conductor","events":["push"],"supported_events":["push"],"schema":[["string","api_key"]]},{"name":"coop","events":["push"],"supported_events":["push"],"schema":[["string","group_id"],["string","token"]]},{"name":"copperegg","events":["push"],"supported_events":["push"],"schema":[["string","url"],["string","tag"],["boolean","master_only"],["string","api_key"]]},{"name":"cube","events":["push"],"supported_events":["push"],"schema":[["string","domain"],["string","project"],["string","token"]]},{"name":"depending","events":["push"],"supported_events":["push"],"schema":[["string","token"]]},{"name":"deployhq","events":["push"],"supported_events":["push"],"schema":[["string","deploy_hook_url"],["boolean","email_pusher"]]},{"name":"devaria","events":["push","member","public","issues","gollum"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","project_name"],["string","username"],["string","user_class_id"]]},{"name":"docker","events":["push"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[]},{"name":"ducksboard","events":["push","issues","fork","watch"],"supported_events":["fork","issues","push","watch"],"schema":[["string","webhook_key"]]},{"name":"email","events":["push"],"supported_events":["public","push"],"schema":[["string","address"],["password","secret"],["boolean","send_from_author"]]},{"name":"firebase","events":["push"],"supported_events":["push"],"schema":[["string","firebase"],["string","secret"]]},{"name":"fisheye","events":["push"],"supported_events":["push"],"schema":[["string","url_base"],["string","token"],["string","repository_name"]]},{"name":"flowdock","events":["commit_comment","gollum","issues","issue_comment","pull_request","push"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","token"]]},{"name":"fogbugz","events":["push"],"supported_events":["push"],"schema":[["string","cvssubmit_url"],["string","fb_repoid"],["string","fb_version"]]},{"name":"freckle","events":["push"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","subdomain"],["string","project"],["string","token"]]},{"name":"friendfeed","events":["push"],"supported_events":["push"],"schema":[["string","nickname"],["string","remotekey"]]},{"name":"gemini","events":["push"],"supported_events":["push"],"schema":[["string","server_url"],["string","api_key"]]},{"name":"gemnasium","events":["push"],"supported_events":["push"],"schema":[["string","user"],["string","token"]]},{"name":"geocommit","events":["push"],"supported_events":["push"],"schema":[]},{"name":"getlocalization","events":["push"],"supported_events":["push"],"schema":[["string","project_name"],["string","project_token"]]},{"name":"gitlive","events":["push"],"supported_events":["push"],"schema":[]},{"name":"grmble","events":["push"],"supported_events":["push"],"schema":[["string","room_api_url"],["string","token"]]},{"name":"grouptalent","events":["push"],"supported_events":["push"],"schema":[["string","token"]]},{"name":"grove","events":["commit_comment","gollum","issues","issue_comment","pull_request","push"],"supported_events":["push"],"schema":[["string","channel_token"]]},{"name":"habitualist","events":["push"],"supported_events":["push"],"schema":[]},{"name":"hakiri","events":["push"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","token"],["string","project_id"]]},{"name":"hall","events":["commit_comment","gollum","issues","issue_comment","pull_request","push"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","room_token"]]},{"name":"harvest","events":["push"],"supported_events":["push"],"schema":[["string","subdomain"],["string","username"],["password","password"],["boolean","ssl"]]},{"name":"hipchat","events":["commit_comment","download","fork","fork_apply","gollum","issues","issue_comment","member","public","pull_request","push","watch"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","auth_token"],["string","room"],["string","restrict_to_branch"],["boolean","notify"],["boolean","quiet_fork"],["boolean","quiet_watch"],["boolean","quiet_comments"]]},{"name":"hostedgraphite","events":["push"],"supported_events":["push"],"schema":[["string","api_key"]]},{"name":"hubcap","events":["push"],"supported_events":["push"],"schema":[]},{"name":"hubci","events":["push"],"supported_events":["push"],"schema":[["string","token"]]},{"name":"humbug","events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","push","team_add","watch","pull_request_review_comment","status"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","email"],["string","api_key"],["string","stream"],["string","branches"]]},{"name":"icescrum","events":["push"],"supported_events":["push"],"schema":[["string","base_url"],["string","project_key"],["string","username"],["password","password"]]},{"name":"irc","events":["push","pull_request"],"supported_events":["commit_comment","issue_comment","issues","pull_request","pull_request_review_comment","push"],"schema":[["string","server"],["string","port"],["string","room"],["string","nick"],["string","branch_regexes"],["string","nickserv_password"],["password","password"],["boolean","ssl"],["boolean","message_without_join"],["boolean","no_colors"],["boolean","long_url"],["boolean","notice"]]},{"name":"irker","events":["push"],"supported_events":["push"],"schema":[["string","address"],["string","project"],["string","branch"],["string","module"],["string","channels"],["boolean","long_url"],["boolean","color"],["boolean","full_commits"]]},{"name":"ironmq","events":["commit_comment","download","fork","fork_apply","gollum","issues","issue_comment","member","public","pull_request","push","watch"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","token"],["string","project_id"],["string","queue_name"]]},{"name":"ironworker","events":["commit_comment","download","fork","fork_apply","gollum","issues","issue_comment","member","public","pull_request","push","watch"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","token"],["string","project_id"],["string","queue_name"]]},{"name":"jabber","events":["push"],"supported_events":["push"],"schema":[["string","user"]]},{"name":"jaconda","events":["commit_comment","download","fork","fork_apply","gollum","issues","issue_comment","member","public","pull_request","push","watch"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","subdomain"],["string","room_id"],["string","room_token"],["boolean","digest"]]},{"name":"jeapie","events":["push","pull_request","commit_comment"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","token"]]},{"name":"jenkins","events":["push"],"supported_events":["push"],"schema":[["string","jenkins_hook_url"]]},{"name":"jenkinsgit","events":["push"],"supported_events":["push"],"schema":[["string","jenkins_url"]]},{"name":"jira","events":["push"],"supported_events":["push"],"schema":[["string","server_url"],["string","api_version"],["string","username"],["password","password"]]},{"name":"jqueryplugins","events":["push"],"supported_events":["push"],"schema":[]},{"name":"kanbanery","events":["push"],"supported_events":["push"],"schema":[["string","project_id"],["string","project_token"]]},{"name":"kickoff","events":["push"],"supported_events":["push"],"schema":[["string","project_id"],["string","project_token"]]},{"name":"leanto","events":["push"],"supported_events":["push"],"schema":[["string","token"]]},{"name":"lechat","events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","webhook_url"]]},{"name":"lighthouse","events":["push"],"supported_events":["push"],"schema":[["string","subdomain"],["string","project_id"],["string","token"],["boolean","private"],["boolean","send_only_ticket_commits"]]},{"name":"lingohub","events":["push"],"supported_events":["push"],"schema":[["string","project_token"]]},{"name":"loggly","events":["push"],"supported_events":["push"],"schema":[["string","input_token"]]},{"name":"mantisbt","events":["push"],"supported_events":["push"],"schema":[["string","url"],["string","api_key"]]},{"name":"masterbranch","events":["push"],"supported_events":["push"],"schema":[]},{"name":"mqttpub","events":["push"],"supported_events":["push"],"schema":[["string","broker"],["string","port"],["string","topic"],["string","clientid"],["string","user"],["password","pass"],["boolean","retain"]]},{"name":"nma","events":["push"],"supported_events":["push"],"schema":[["string","apikey"]]},{"name":"nodejitsu","events":["push"],"supported_events":["push"],"schema":[["string","username"],["password","password"],["string","branch"],["string","endpoint"],["boolean","email_success_deploys"],["boolean","email_errors"]]},{"name":"notifo","events":["push"],"supported_events":["push"],"schema":[["string","subscribers"]]},{"name":"ontime","events":["push"],"supported_events":["push"],"schema":[["string","ontime_url"],["string","api_key"]]},{"name":"pachube","events":["push"],"supported_events":["push"],"schema":[["string","api_key"],["string","feed_id"],["string","track_branch"]]},{"name":"packagist","events":["push"],"supported_events":["push"],"schema":[["string","user"],["string","token"],["string","domain"]]},{"name":"phraseapp","events":["push"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","auth_token"]]},{"name":"pivotaltracker","events":["push"],"supported_events":["push"],"schema":[["string","token"],["string","branch"],["string","endpoint"]]},{"name":"planbox","events":["push"],"supported_events":["push"],"schema":[["string","token"]]},{"name":"planio","events":["push"],"supported_events":["push"],"schema":[["string","address"],["string","project"],["string","api_key"]]},{"name":"prowl","events":["push"],"supported_events":["push"],"schema":[["string","apikey"]]},{"name":"puppetlinter","events":["push"],"supported_events":["push"],"schema":[]},{"name":"pushalot","events":["push"],"supported_events":["push"],"schema":[["string","authorization_token"]]},{"name":"pushover","events":["push"],"supported_events":["push"],"schema":[["string","user_key"],["string","device_name"]]},{"name":"pythonpackages","events":["push"],"supported_events":["push"],"schema":[]},{"name":"railsbp","events":["push"],"supported_events":["push"],"schema":[["string","railsbp_url"],["string","token"]]},{"name":"railsbrakeman","events":["push"],"supported_events":["push"],"schema":[["string","rails_brakeman_url"],["string","token"]]},{"name":"rally","events":["push"],"supported_events":["push"],"schema":[["string","server"],["string","username"],["string","workspace"],["string","repository"],["password","password"]]},{"name":"rapidpush","events":["push"],"supported_events":["push"],"schema":[["string","apikey"]]},{"name":"rationaljazzhub","events":["push"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","username"],["password","password"],["string","override_server_url"]]},{"name":"rationalteamconcert","events":["push"],"supported_events":["push"],"schema":[["string","server_url"],["string","username"],["string","project_area_uuid"],["password","password"],["boolean","basic_authentication"],["boolean","no_verify_ssl"]]},{"name":"rdocinfo","events":["push"],"supported_events":["push"],"schema":[]},{"name":"readthedocs","events":["push"],"supported_events":["push"],"schema":[]},{"name":"redmine","events":["push"],"supported_events":["push"],"schema":[["string","address"],["string","project"],["string","api_key"],["boolean","fetch_commits"],["boolean","update_redmine_issues_about_commits"]]},{"name":"rubyforge","events":["push"],"supported_events":["push"],"schema":[["string","groupid"],["string","username"],["password","password"]]},{"name":"scrumdo","events":["push"],"supported_events":["push"],"schema":[["string","username"],["string","project_slug"],["password","password"]]},{"name":"shiningpanda","events":["push"],"supported_events":["push"],"schema":[["string","workspace"],["string","job"],["string","token"],["string","branches"],["string","parameters"]]},{"name":"sifter","events":["push"],"supported_events":["push"],"schema":[["string","subdomain"],["string","token"]]},{"name":"simperium","events":["push","issues","issue_comment","commit_comment","pull_request","pull_request_review_comment","watch","fork","fork_apply","member","public","team_add","status"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","app_id"],["string","token"],["string","bucket"]]},{"name":"slatebox","events":["push"],"supported_events":["push"],"schema":[["string","app_id"],["string","token"]]},{"name":"snowyevening","events":["push"],"supported_events":["push"],"schema":[["string","project"],["string","api_key"]]},{"name":"socialcast","events":["push"],"supported_events":["push"],"schema":[["string","api_domain"],["string","group_id"],["string","username"],["password","password"]]},{"name":"softlayermessaging","events":["push"],"supported_events":["push"],"schema":[["string","account"],["string","user"],["string","name"],["password","key"],["boolean","topic"]]},{"name":"sourcemint","events":["push"],"supported_events":["push"],"schema":[]},{"name":"splendidbacon","events":["push"],"supported_events":["push"],"schema":[["string","project_id"],["string","token"]]},{"name":"sprintly","events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","push","team_add","watch","pull_request_review_comment","status"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","email"],["string","api_key"],["string","product_id"]]},{"name":"sqsqueue","events":["push"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","aws_access_key"],["string","sqs_queue_name"],["password","aws_secret_key"]]},{"name":"stackmob","events":["push"],"supported_events":["push"],"schema":[["string","token"]]},{"name":"statusnet","events":["push"],"supported_events":["push"],"schema":[["string","server"],["string","username"],["password","password"],["boolean","digest"]]},{"name":"talker","events":["push"],"supported_events":["issues","pull_request","push"],"schema":[["string","url"],["string","token"],["boolean","digest"]]},{"name":"targetprocess","events":["push"],"supported_events":["push"],"schema":[["string","base_url"],["string","username"],["password","password"]]},{"name":"tddium","events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","token"],["string","override_url"]]},{"name":"teamcity","events":["push"],"supported_events":["push"],"schema":[["string","base_url"],["string","build_type_id"],["string","username"],["string","branches"],["password","password"]]},{"name":"tender","events":["issues"],"supported_events":["issues","pull_request"],"schema":[["string","domain"],["string","token"]]},{"name":"tenxer","events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[]},{"name":"testpilot","events":["push"],"supported_events":["push"],"schema":[["string","token"]]},{"name":"toggl","events":["push"],"supported_events":["push"],"schema":[["string","project"],["string","api_token"]]},{"name":"trac","events":["push"],"supported_events":["push"],"schema":[["string","url"],["string","token"]]},{"name":"trajectory","events":["push"],"supported_events":["pull_request","push"],"schema":[["string","api_key"]]},{"name":"travis","events":["push","pull_request","issue_comment","public","member"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","user"],["password","token"],["string","domain"]]},{"name":"trello","events":["push","pull_request"],"supported_events":["pull_request","push"],"schema":[["string","push_list_id"],["string","pull_request_list_id"],["string","ignore_regex"],["boolean","master_only"],["password","consumer_token"]]},{"name":"twilio","events":["push"],"supported_events":["push"],"schema":[["string","account_sid"],["string","from_phone"],["string","to_phone"],["boolean","master_only"],["password","auth_token"]]},{"name":"twitter","events":["push"],"supported_events":["push"],"schema":[["string","token"],["string","secret"],["boolean","digest"],["boolean","short_format"]]},{"name":"unfuddle","events":["push"],"supported_events":["push"],"schema":[["string","subdomain"],["string","repo_id"],["string","username"],["password","password"],["boolean","httponly"]]},{"name":"web","events":["push"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","url"],["string","secret"],["string","content_type"],["string","ssl_version"],["boolean","insecure_ssl"]]},{"name":"weblate","events":["push"],"supported_events":["push"],"schema":[["string","url"]]},{"name":"webtranslateit","events":["push"],"supported_events":["push"],"schema":[["string","api_key"]]},{"name":"yammer","events":["push","commit_comment","pull_request","pull_request_review_comment","public"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","token"]]},{"name":"youtrack","events":["push"],"supported_events":["push"],"schema":[["string","base_url"],["string","committers"],["string","username"],["string","branch"],["password","password"]]},{"name":"zendesk","events":["commit_comment","issues","issue_comment","pull_request","push"],"supported_events":["commit_comment","create","delete","download","follow","fork","fork_apply","gist","gollum","issue_comment","issues","member","public","pull_request","pull_request_review_comment","push","status","team_add","watch"],"schema":[["string","subdomain"],["string","username"],["password","password"]]},{"name":"zohoprojects","events":["push"],"supported_events":["push"],"schema":[["string","project_id"],["string","token"]]}] +