From 517ad33654eb1f7d773645ccc45a1a117b7365eb Mon Sep 17 00:00:00 2001 From: Jonathan Greg <31892308+jmgreg31@users.noreply.github.com> Date: Tue, 20 Jun 2023 02:49:02 -0400 Subject: [PATCH] Add Webhook Deliveries (#2508) Co-authored-by: Enrico Minack --- github/GithubObject.py | 2 +- github/HookDelivery.py | 275 ++++++++++++++++++ github/MainClass.py | 36 +++ github/Organization.py | 34 +++ github/Organization.pyi | 2 +- github/Repository.py | 36 +++ tests/Github_.py | 45 +++ tests/Organization.py | 45 +++ .../Github.testGetHookDeliveries.txt | 10 + .../ReplayData/Github.testGetHookDelivery.txt | 10 + .../Organization.testGetHookDeliveries.txt | 10 + .../Organization.testGetHookDelivery.txt | 10 + .../Repository.testGetHookDeliveries.txt | 10 + .../Repository.testGetHookDelivery.txt | 10 + tests/Repository.py | 45 +++ 15 files changed, 578 insertions(+), 2 deletions(-) create mode 100644 github/HookDelivery.py create mode 100644 tests/ReplayData/Github.testGetHookDeliveries.txt create mode 100644 tests/ReplayData/Github.testGetHookDelivery.txt create mode 100644 tests/ReplayData/Organization.testGetHookDeliveries.txt create mode 100644 tests/ReplayData/Organization.testGetHookDelivery.txt create mode 100644 tests/ReplayData/Repository.testGetHookDeliveries.txt create mode 100644 tests/ReplayData/Repository.testGetHookDelivery.txt diff --git a/github/GithubObject.py b/github/GithubObject.py index 6cea1cc0..21fa736a 100644 --- a/github/GithubObject.py +++ b/github/GithubObject.py @@ -211,7 +211,7 @@ class GithubObject: return GithubObject.__makeSimpleAttribute(value, int) @staticmethod - def _makeFloatAttribute(value): + def _makeFloatAttribute(value: Optional[float]) -> Attribute[float]: return GithubObject.__makeSimpleAttribute(value, float) @staticmethod diff --git a/github/HookDelivery.py b/github/HookDelivery.py new file mode 100644 index 00000000..da1d028b --- /dev/null +++ b/github/HookDelivery.py @@ -0,0 +1,275 @@ +############################ Copyrights and license ############################ +# # +# Copyright 2012 Vincent Jacques # +# Copyright 2012 Zearin # +# Copyright 2013 AKFish # +# Copyright 2013 Vincent Jacques # +# Copyright 2014 Vincent Jacques # +# Copyright 2016 Jannis Gebauer # +# Copyright 2016 Peter Buckley # +# Copyright 2018 Wan Liuyang # +# Copyright 2018 sfdye # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# 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 . # +# # +################################################################################ +from datetime import datetime +from typing import Any, Dict, Optional + +import github.GithubObject +from github.GithubObject import Attribute, NotSet + + +class HookDeliverySummary(github.GithubObject.NonCompletableGithubObject): + """ + This class represents a Summary of HookDeliveries + """ + + def __repr__(self) -> str: + return self.get__repr__({"id": self._id.value}) + + @property + def id(self) -> Optional[int]: + """ + :type: integer + """ + return self._id.value + + @property + def guid(self) -> Optional[str]: + """ + :type: string + """ + return self._guid.value + + @property + def delivered_at(self) -> Optional[datetime]: + """ + :type: datetime + """ + return self._delivered_at.value + + @property + def redelivery(self) -> Optional[bool]: + """ + :type: boolean + """ + return self._redelivery.value + + @property + def duration(self) -> Optional[float]: + """ + :type: float + """ + return self._duration.value + + @property + def status(self) -> Optional[str]: + """ + :type: string + """ + return self._status.value + + @property + def status_code(self) -> Optional[int]: + """ + :type: integer + """ + return self._status_code.value + + @property + def event(self) -> Optional[str]: + """ + :type: string + """ + return self._event.value + + @property + def action(self) -> Optional[str]: + """ + :type: string + """ + return self._action.value + + @property + def installation_id(self) -> Optional[int]: + """ + :type: integer + """ + return self._installation_id.value + + @property + def repository_id(self) -> Optional[int]: + """ + :type: integer + """ + return self._repository_id.value + + @property + def url(self) -> Optional[str]: + """ + :type: string + """ + return self._url.value + + def _initAttributes(self) -> None: + self._id: Attribute[int] = NotSet + self._guid: Attribute[str] = NotSet + self._delivered_at: Attribute[datetime] = NotSet + self._redelivery: Attribute[bool] = NotSet + self._duration: Attribute[float] = NotSet + self._status: Attribute[str] = NotSet + self._status_code: Attribute[int] = NotSet + self._event: Attribute[str] = NotSet + self._action: Attribute[str] = NotSet + self._installation_id: Attribute[int] = NotSet + self._repository_id: Attribute[int] = NotSet + self._url: Attribute[str] = NotSet + + def _useAttributes(self, attributes: Dict[str, Any]): + if "id" in attributes: # pragma no branch + self._id = self._makeIntAttribute(attributes["id"]) + if "guid" in attributes: # pragma no branch + self._guid = self._makeStringAttribute(attributes["guid"]) + if "delivered_at" in attributes: # pragma no branch + self._delivered_at = self._makeDatetimeAttribute(attributes["delivered_at"]) + if "redelivery" in attributes: # pragma no branch + self._redelivery = self._makeBoolAttribute(attributes["redelivery"]) + if "duration" in attributes: # pragma no branch + self._duration = self._makeFloatAttribute(attributes["duration"]) + if "status" in attributes: # pragma no branch + self._status = self._makeStringAttribute(attributes["status"]) + if "status_code" in attributes: # pragma no branch + self._status_code = self._makeIntAttribute(attributes["status_code"]) + if "event" in attributes: # pragma no branch + self._event = self._makeStringAttribute(attributes["event"]) + if "action" in attributes: # pragma no branch + self._action = self._makeStringAttribute(attributes["action"]) + if "installation_id" in attributes: # pragma no branch + self._installation_id = self._makeIntAttribute( + attributes["installation_id"] + ) + if "repository_id" in attributes: # pragma no branch + self._repository_id = self._makeIntAttribute(attributes["repository_id"]) + if "url" in attributes: # pragma no branch + self._url = self._makeStringAttribute(attributes["url"]) + + +class HookDeliveryRequest(github.GithubObject.NonCompletableGithubObject): + """ + This class represents a HookDeliveryRequest + """ + + def __repr__(self) -> str: + return self.get__repr__({"payload": self._payload.value}) + + @property + def headers(self) -> Optional[dict]: + """ + :type: dict + """ + return self._request_headers.value + + @property + def payload(self) -> Optional[dict]: + """ + :type: dict + """ + return self._payload.value + + def _initAttributes(self) -> None: + self._request_headers: Attribute[Dict] = NotSet + self._payload: Attribute[Dict] = NotSet + + def _useAttributes(self, attributes: Dict[str, Any]) -> None: + if "headers" in attributes: # pragma no branch + self._request_headers = self._makeDictAttribute(attributes["headers"]) + if "payload" in attributes: # pragma no branch + self._payload = self._makeDictAttribute(attributes["payload"]) + + +class HookDeliveryResponse(github.GithubObject.NonCompletableGithubObject): + """ + This class represents a HookDeliveryResponse + """ + + def __repr__(self) -> str: + return self.get__repr__({"payload": self._payload.value}) + + @property + def headers(self) -> Optional[dict]: + """ + :type: dict + """ + return self._response_headers.value + + @property + def payload(self) -> Optional[str]: + """ + :type: str + """ + return self._payload.value + + def _initAttributes(self) -> None: + self._response_headers: Attribute[Dict] = NotSet + self._payload: Attribute[str] = NotSet + + def _useAttributes(self, attributes: Dict[str, Any]) -> None: + if "headers" in attributes: # pragma no branch + self._response_headers = self._makeDictAttribute(attributes["headers"]) + if "payload" in attributes: # pragma no branch + self._payload = self._makeStringAttribute(attributes["payload"]) + + +class HookDelivery(HookDeliverySummary): + """ + This class represents a HookDelivery + """ + + def __repr__(self) -> str: + return self.get__repr__({"id": self._id.value}) + + @property + def request(self) -> Optional[HookDeliveryRequest]: + """ + :type: :class:`HookDeliveryRequest` + """ + return self._request.value + + @property + def response(self) -> Optional[HookDeliveryResponse]: + """ + :type: :class:`HookDeliveryResponse` + """ + return self._response.value + + def _initAttributes(self) -> None: + super()._initAttributes() + self._request: Attribute[HookDeliveryRequest] = NotSet + self._response: Attribute[HookDeliveryResponse] = NotSet + + def _useAttributes(self, attributes: Dict[str, Any]) -> None: + super()._useAttributes(attributes) + if "request" in attributes: # pragma no branch + self._request = self._makeClassAttribute( + HookDeliveryRequest, attributes["request"] + ) + if "response" in attributes: # pragma no branch + self._response = self._makeClassAttribute( + HookDeliveryResponse, attributes["response"] + ) + # self._response = self._makeDictAttribute(attributes["response"]) diff --git a/github/MainClass.py b/github/MainClass.py index a5887153..cbec4248 100644 --- a/github/MainClass.py +++ b/github/MainClass.py @@ -50,6 +50,7 @@ import datetime import pickle import warnings +from typing import List import urllib3 @@ -68,10 +69,12 @@ from . import ( Consts, GithubApp, GitignoreTemplate, + HookDelivery, HookDescription, RateLimit, Repository, ) +from .HookDelivery import HookDeliverySummary from .Requester import Requester @@ -725,6 +728,39 @@ class Github: for attributes in data ] + def get_hook_delivery(self, hook_id: int, delivery_id: int) -> HookDelivery: + """ + :calls: `GET /hooks/{hook_id}/deliveries/{delivery_id} `_ + :param hook_id: integer + :param delivery_id: integer + :rtype: :class:`github.HookDelivery.HookDelivery` + """ + assert isinstance(hook_id, int), hook_id + assert isinstance(delivery_id, int), delivery_id + headers, attributes = self.__requester.requestJsonAndCheck( + "GET", f"/hooks/{hook_id}/deliveries/{delivery_id}" + ) + return HookDelivery.HookDelivery( + self.__requester, headers, attributes, completed=True + ) + + def get_hook_deliveries(self, hook_id: int) -> List[HookDeliverySummary]: + """ + :calls: `GET /hooks/{hook_id}/deliveries `_ + :param hook_id: integer + :rtype: list of :class:`github.HookDelivery.HookDeliverySummary` + """ + assert isinstance(hook_id, int), hook_id + headers, data = self.__requester.requestJsonAndCheck( + "GET", f"/hooks/{hook_id}/deliveries" + ) + return [ + HookDelivery.HookDeliverySummary( + self.__requester, headers, attributes, completed=True + ) + for attributes in data + ] + def get_gitignore_templates(self): """ :calls: `GET /gitignore/templates `_ diff --git a/github/Organization.py b/github/Organization.py index f1f64ea3..2d843386 100644 --- a/github/Organization.py +++ b/github/Organization.py @@ -877,6 +877,40 @@ class Organization(github.GithubObject.CompletableGithubObject): github.Hook.Hook, self._requester, f"{self.url}/hooks", None ) + def get_hook_delivery( + self, hook_id: int, delivery_id: int + ) -> github.HookDelivery.HookDelivery: + """ + :calls: `GET /orgs/{owner}/hooks/{hook_id}/deliveries/{delivery_id} `_ + :param hook_id: integer + :param delivery_id: integer + :rtype: :class:`github.HookDelivery.HookDelivery` + """ + assert isinstance(hook_id, int), hook_id + assert isinstance(delivery_id, int), delivery_id + headers, data = self._requester.requestJsonAndCheck( + "GET", f"{self.url}/hooks/{hook_id}/deliveries/{delivery_id}" + ) + return github.HookDelivery.HookDelivery( + self._requester, headers, data, completed=True + ) + + def get_hook_deliveries( + self, hook_id: int + ) -> github.PaginatedList.PaginatedList[github.HookDelivery.HookDeliverySummary]: + """ + :calls: `GET /orgs/{owner}/hooks/{hook_id}/deliveries `_ + :param hook_id: integer + :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.HookDelivery.HookDeliverySummary` + """ + assert isinstance(hook_id, int), hook_id + return github.PaginatedList.PaginatedList( + github.HookDelivery.HookDeliverySummary, + self._requester, + f"{self.url}/hooks/{hook_id}/deliveries", + None, + ) + def get_issues( self, filter=github.GithubObject.NotSet, diff --git a/github/Organization.pyi b/github/Organization.pyi index 396da5b3..ad443bdc 100644 --- a/github/Organization.pyi +++ b/github/Organization.pyi @@ -4,10 +4,10 @@ from typing import Any, Dict, List, Optional, Union from github.Event import Event from github.GithubObject import CompletableGithubObject, _NotSetType from github.Hook import Hook +from github.Installation import Installation from github.Issue import Issue from github.Label import Label from github.Migration import Migration -from github.Installation import Installation from github.NamedUser import NamedUser from github.PaginatedList import PaginatedList from github.Plan import Plan diff --git a/github/Repository.py b/github/Repository.py index bd381b68..5bf14d10 100644 --- a/github/Repository.py +++ b/github/Repository.py @@ -158,6 +158,7 @@ import github.GitReleaseAsset import github.GitTag import github.GitTree import github.Hook +import github.HookDelivery import github.Invitation import github.Issue import github.IssueEvent @@ -2799,6 +2800,41 @@ class Repository(github.GithubObject.CompletableGithubObject): github.Hook.Hook, self._requester, f"{self.url}/hooks", None ) + def get_hook_delivery( + self, hook_id: int, delivery_id: int + ) -> github.HookDelivery.HookDelivery: + """ + :calls: `GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id} `_ + :param hook_id: integer + :param delivery_id: integer + :rtype: :class:`github.HookDelivery.HookDelivery` + """ + assert isinstance(hook_id, int), hook_id + assert isinstance(delivery_id, int), delivery_id + headers, data = self._requester.requestJsonAndCheck( + "GET", f"{self.url}/hooks/{hook_id}/deliveries/{delivery_id}" + ) + return github.HookDelivery.HookDelivery( + self._requester, headers, data, completed=True + ) + + def get_hook_deliveries( + self, hook_id: int + ) -> github.PaginatedList.PaginatedList[github.HookDelivery.HookDeliverySummary]: + """ + :calls: `GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries `_ + :param hook_id: integer + :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.HookDelivery.HookDeliverySummary` + """ + assert isinstance(hook_id, int), hook_id + + return github.PaginatedList.PaginatedList( + github.HookDelivery.HookDeliverySummary, + self._requester, + f"{self.url}/hooks/{hook_id}/deliveries", + None, + ) + def get_issue(self, number): """ :calls: `GET /repos/{owner}/{repo}/issues/{number} `_ diff --git a/tests/Github_.py b/tests/Github_.py index 3e702751..a87f4355 100644 --- a/tests/Github_.py +++ b/tests/Github_.py @@ -204,6 +204,51 @@ class Github(Framework.TestCase): ) self.assertEqual(repr(hook), 'HookDescription(name="activecollab")') + def testGetHookDelivery(self): + delivery = self.g.get_hook_delivery(257993, 12345) + self.assertEqual(delivery.id, 12345) + self.assertEqual(delivery.guid, "abcde-12345") + self.assertEqual( + delivery.delivered_at, datetime.datetime(2012, 5, 27, 6, 0, 32) + ) + self.assertEqual(delivery.redelivery, False) + self.assertEqual(delivery.duration, 0.27) + self.assertEqual(delivery.status, "OK") + self.assertEqual(delivery.status_code, 200) + self.assertEqual(delivery.event, "issues") + self.assertEqual(delivery.action, "opened") + self.assertEqual(delivery.installation_id, 123) + self.assertEqual(delivery.repository_id, 456) + self.assertEqual(delivery.url, "https://www.example-webhook.com") + self.assertIsInstance(delivery.request, github.HookDelivery.HookDeliveryRequest) + self.assertEqual(delivery.request.headers, {"content-type": "application/json"}) + self.assertEqual(delivery.request.payload, {"action": "opened"}) + self.assertIsInstance( + delivery.response, github.HookDelivery.HookDeliveryResponse + ) + self.assertEqual( + delivery.response.headers, {"content-type": "text/html;charset=utf-8"} + ) + self.assertEqual(delivery.response.payload, "ok") + + def testGetHookDeliveries(self): + deliveries = list(self.g.get_hook_deliveries(257993)) + self.assertEqual(len(deliveries), 1) + self.assertEqual(deliveries[0].id, 12345) + self.assertEqual(deliveries[0].guid, "abcde-12345") + self.assertEqual( + deliveries[0].delivered_at, datetime.datetime(2012, 5, 27, 6, 0, 32) + ) + self.assertEqual(deliveries[0].redelivery, False) + self.assertEqual(deliveries[0].duration, 0.27) + self.assertEqual(deliveries[0].status, "OK") + self.assertEqual(deliveries[0].status_code, 200) + self.assertEqual(deliveries[0].event, "issues") + self.assertEqual(deliveries[0].action, "opened") + self.assertEqual(deliveries[0].installation_id, 123) + self.assertEqual(deliveries[0].repository_id, 456) + self.assertEqual(deliveries[0].url, "https://www.example-webhook.com") + def testGetRepoFromFullName(self): self.assertEqual( self.g.get_repo("jacquev6/PyGithub").description, diff --git a/tests/Organization.py b/tests/Organization.py index 25b5336d..9e77ac65 100644 --- a/tests/Organization.py +++ b/tests/Organization.py @@ -185,6 +185,51 @@ class Organization(Framework.TestCase): def testGetHooks(self): self.assertListKeyEqual(self.org.get_hooks(), lambda h: h.id, [257993]) + def testGetHookDelivery(self): + delivery = self.org.get_hook_delivery(257993, 12345) + self.assertEqual(delivery.id, 12345) + self.assertEqual(delivery.guid, "abcde-12345") + self.assertEqual( + delivery.delivered_at, datetime.datetime(2012, 5, 27, 6, 0, 32) + ) + self.assertEqual(delivery.redelivery, False) + self.assertEqual(delivery.duration, 0.27) + self.assertEqual(delivery.status, "OK") + self.assertEqual(delivery.status_code, 200) + self.assertEqual(delivery.event, "issues") + self.assertEqual(delivery.action, "opened") + self.assertEqual(delivery.installation_id, 123) + self.assertEqual(delivery.repository_id, 456) + self.assertEqual(delivery.url, "https://www.example-webhook.com") + self.assertIsInstance(delivery.request, github.HookDelivery.HookDeliveryRequest) + self.assertEqual(delivery.request.headers, {"content-type": "application/json"}) + self.assertEqual(delivery.request.payload, {"action": "opened"}) + self.assertIsInstance( + delivery.response, github.HookDelivery.HookDeliveryResponse + ) + self.assertEqual( + delivery.response.headers, {"content-type": "text/html;charset=utf-8"} + ) + self.assertEqual(delivery.response.payload, "ok") + + def testGetHookDeliveries(self): + deliveries = list(self.org.get_hook_deliveries(257993)) + self.assertEqual(len(deliveries), 1) + self.assertEqual(deliveries[0].id, 12345) + self.assertEqual(deliveries[0].guid, "abcde-12345") + self.assertEqual( + deliveries[0].delivered_at, datetime.datetime(2012, 5, 27, 6, 0, 32) + ) + self.assertEqual(deliveries[0].redelivery, False) + self.assertEqual(deliveries[0].duration, 0.27) + self.assertEqual(deliveries[0].status, "OK") + self.assertEqual(deliveries[0].status_code, 200) + self.assertEqual(deliveries[0].event, "issues") + self.assertEqual(deliveries[0].action, "opened") + self.assertEqual(deliveries[0].installation_id, 123) + self.assertEqual(deliveries[0].repository_id, 456) + self.assertEqual(deliveries[0].url, "https://www.example-webhook.com") + def testGetIssues(self): self.assertListKeyEqual(self.org.get_issues(), lambda i: i.id, []) diff --git a/tests/ReplayData/Github.testGetHookDeliveries.txt b/tests/ReplayData/Github.testGetHookDeliveries.txt new file mode 100644 index 00000000..40566ab6 --- /dev/null +++ b/tests/ReplayData/Github.testGetHookDeliveries.txt @@ -0,0 +1,10 @@ +https +GET +api.github.com +None +/hooks/257993/deliveries +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +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', 'b3cd8329-7f33-4611-84d1-4e2ecfd91812'), ('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', 'Wed, 11 Sep 2013 21:10:37 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1378937437')] +[{"id":12345,"guid":"abcde-12345","delivered_at":"2012-05-27T06:00:32Z","redelivery":false,"duration":0.27,"status":"OK","status_code":200,"event":"issues","action":"opened","installation_id":123,"repository_id":456,"url":"https://www.example-webhook.com"}] diff --git a/tests/ReplayData/Github.testGetHookDelivery.txt b/tests/ReplayData/Github.testGetHookDelivery.txt new file mode 100644 index 00000000..44ccfcb6 --- /dev/null +++ b/tests/ReplayData/Github.testGetHookDelivery.txt @@ -0,0 +1,10 @@ +https +GET +api.github.com +None +/hooks/257993/deliveries/12345 +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +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', 'b3cd8329-7f33-4611-84d1-4e2ecfd91812'), ('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', 'Wed, 11 Sep 2013 21:10:37 GMT'), ('access-control-allow-origin', '*'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1378937437')] +{"id":12345,"guid":"abcde-12345","delivered_at":"2012-05-27T06:00:32Z","redelivery":false,"duration":0.27,"status":"OK","status_code":200,"event":"issues","action":"opened","installation_id":123,"repository_id":456,"url":"https://www.example-webhook.com","request":{"headers":{"content-type": "application/json"},"payload":{"action": "opened"}},"response":{"headers":{"content-type": "text/html;charset=utf-8"},"payload":"ok"}} diff --git a/tests/ReplayData/Organization.testGetHookDeliveries.txt b/tests/ReplayData/Organization.testGetHookDeliveries.txt new file mode 100644 index 00000000..bdc53e63 --- /dev/null +++ b/tests/ReplayData/Organization.testGetHookDeliveries.txt @@ -0,0 +1,10 @@ +https +GET +api.github.com +None +/orgs/BeaverSoftware/hooks/257993/deliveries +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4953'), ('content-length', '295'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"07e5e1a2fafd1a5e2de62eb3afd007d5"'), ('date', 'Sun, 27 May 2012 07:02:25 GMT'), ('content-type', 'application/json; charset=utf-8')] +[{"id":12345,"guid":"abcde-12345","delivered_at":"2012-05-27T06:00:32Z","redelivery":false,"duration":0.27,"status":"OK","status_code":200,"event":"issues","action":"opened","installation_id":123,"repository_id":456,"url":"https://www.example-webhook.com"}] diff --git a/tests/ReplayData/Organization.testGetHookDelivery.txt b/tests/ReplayData/Organization.testGetHookDelivery.txt new file mode 100644 index 00000000..53fb26d9 --- /dev/null +++ b/tests/ReplayData/Organization.testGetHookDelivery.txt @@ -0,0 +1,10 @@ +https +GET +api.github.com +None +/orgs/BeaverSoftware/hooks/257993/deliveries/12345 +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4953'), ('content-length', '295'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"07e5e1a2fafd1a5e2de62eb3afd007d5"'), ('date', 'Sun, 27 May 2012 07:02:25 GMT'), ('content-type', 'application/json; charset=utf-8')] +{"id":12345,"guid":"abcde-12345","delivered_at":"2012-05-27T06:00:32Z","redelivery":false,"duration":0.27,"status":"OK","status_code":200,"event":"issues","action":"opened","installation_id":123,"repository_id":456,"url":"https://www.example-webhook.com","request":{"headers":{"content-type": "application/json"},"payload":{"action": "opened"}},"response":{"headers":{"content-type": "text/html;charset=utf-8"},"payload":"ok"}} diff --git a/tests/ReplayData/Repository.testGetHookDeliveries.txt b/tests/ReplayData/Repository.testGetHookDeliveries.txt new file mode 100644 index 00000000..b5403983 --- /dev/null +++ b/tests/ReplayData/Repository.testGetHookDeliveries.txt @@ -0,0 +1,10 @@ +https +GET +api.github.com +None +/repos/jacquev6/PyGithub/hooks/257993/deliveries +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4953'), ('content-length', '295'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"07e5e1a2fafd1a5e2de62eb3afd007d5"'), ('date', 'Sun, 27 May 2012 07:02:25 GMT'), ('content-type', 'application/json; charset=utf-8')] +[{"id":12345,"guid":"abcde-12345","delivered_at":"2012-05-27T06:00:32Z","redelivery":false,"duration":0.27,"status":"OK","status_code":200,"event":"issues","action":"opened","installation_id":123,"repository_id":456,"url":"https://www.example-webhook.com"}] diff --git a/tests/ReplayData/Repository.testGetHookDelivery.txt b/tests/ReplayData/Repository.testGetHookDelivery.txt new file mode 100644 index 00000000..67029a72 --- /dev/null +++ b/tests/ReplayData/Repository.testGetHookDelivery.txt @@ -0,0 +1,10 @@ +https +GET +api.github.com +None +/repos/jacquev6/PyGithub/hooks/257993/deliveries/12345 +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4953'), ('content-length', '295'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"07e5e1a2fafd1a5e2de62eb3afd007d5"'), ('date', 'Sun, 27 May 2012 07:02:25 GMT'), ('content-type', 'application/json; charset=utf-8')] +{"id":12345,"guid":"abcde-12345","delivered_at":"2012-05-27T06:00:32Z","redelivery":false,"duration":0.27,"status":"OK","status_code":200,"event":"issues","action":"opened","installation_id":123,"repository_id":456,"url":"https://www.example-webhook.com","request":{"headers":{"content-type": "application/json"},"payload":{"action": "opened"}},"response":{"headers":{"content-type": "text/html;charset=utf-8"},"payload":"ok"}} diff --git a/tests/Repository.py b/tests/Repository.py index fa4e91c9..e7a2226f 100644 --- a/tests/Repository.py +++ b/tests/Repository.py @@ -935,6 +935,51 @@ class Repository(Framework.TestCase): def testGetHooks(self): self.assertListKeyEqual(self.repo.get_hooks(), lambda h: h.id, [257993]) + def testGetHookDelivery(self): + delivery = self.repo.get_hook_delivery(257993, 12345) + self.assertEqual(delivery.id, 12345) + self.assertEqual(delivery.guid, "abcde-12345") + self.assertEqual( + delivery.delivered_at, datetime.datetime(2012, 5, 27, 6, 0, 32) + ) + self.assertEqual(delivery.redelivery, False) + self.assertEqual(delivery.duration, 0.27) + self.assertEqual(delivery.status, "OK") + self.assertEqual(delivery.status_code, 200) + self.assertEqual(delivery.event, "issues") + self.assertEqual(delivery.action, "opened") + self.assertEqual(delivery.installation_id, 123) + self.assertEqual(delivery.repository_id, 456) + self.assertEqual(delivery.url, "https://www.example-webhook.com") + self.assertIsInstance(delivery.request, github.HookDelivery.HookDeliveryRequest) + self.assertEqual(delivery.request.headers, {"content-type": "application/json"}) + self.assertEqual(delivery.request.payload, {"action": "opened"}) + self.assertIsInstance( + delivery.response, github.HookDelivery.HookDeliveryResponse + ) + self.assertEqual( + delivery.response.headers, {"content-type": "text/html;charset=utf-8"} + ) + self.assertEqual(delivery.response.payload, "ok") + + def testGetHookDeliveries(self): + deliveries = list(self.repo.get_hook_deliveries(257993)) + self.assertEqual(len(deliveries), 1) + self.assertEqual(deliveries[0].id, 12345) + self.assertEqual(deliveries[0].guid, "abcde-12345") + self.assertEqual( + deliveries[0].delivered_at, datetime.datetime(2012, 5, 27, 6, 0, 32) + ) + self.assertEqual(deliveries[0].redelivery, False) + self.assertEqual(deliveries[0].duration, 0.27) + self.assertEqual(deliveries[0].status, "OK") + self.assertEqual(deliveries[0].status_code, 200) + self.assertEqual(deliveries[0].event, "issues") + self.assertEqual(deliveries[0].action, "opened") + self.assertEqual(deliveries[0].installation_id, 123) + self.assertEqual(deliveries[0].repository_id, 456) + self.assertEqual(deliveries[0].url, "https://www.example-webhook.com") + def testGetIssues(self): self.assertListKeyEqual( self.repo.get_issues(),