diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1ee8c50 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +__pycache__ +.tox/* +*.pyc +.coverage* +!.coveragerc +*egg* diff --git a/github_webhook/webhook.py b/github_webhook/webhook.py index 85787d3..f4ca352 100644 --- a/github_webhook/webhook.py +++ b/github_webhook/webhook.py @@ -16,11 +16,25 @@ class Webhook(object): :param secret: Optional secret, used to authenticate the hook comes from Github """ - def __init__(self, app, endpoint="/postreceive", secret=None): - app.add_url_rule(rule=endpoint, endpoint=endpoint, view_func=self._postreceive, methods=["POST"]) + def __init__(self, app=None, endpoint="/postreceive", secret=None): + self.app = app + self.secret = secret + if app is not None: + self.init_app(app, endpoint, secret) + def init_app(self, app, endpoint="/postreceive", secret=None): self._hooks = collections.defaultdict(list) self._logger = logging.getLogger("webhook") + if secret is not None: + self.secret = secret + app.add_url_rule(rule=endpoint, endpoint=endpoint, view_func=self._postreceive, methods=["POST"]) + + @property + def secret(self): + return self._secret + + @secret.setter + def secret(self, secret): if secret is not None and not isinstance(secret, six.binary_type): secret = secret.encode("utf-8") self._secret = secret diff --git a/setup.py b/setup.py index ebd03dc..b1ebbae 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name="github-webhook", - version="1.0.3", + version="1.0.4", description="Very simple, but powerful, microframework for writing Github webhooks in Python", url="https://github.com/bloomberg/python-github-webhook", author="Alex Chamberlain, Fred Phillips, Daniel Kiss, Daniel Beer", diff --git a/tests/test_webhook.py b/tests/test_webhook.py index b6e64a2..29eba7d 100644 --- a/tests/test_webhook.py +++ b/tests/test_webhook.py @@ -65,6 +65,44 @@ def test_constructor(): ) +def test_init_app_flow(): + # GIVEN + app = mock.Mock() + + # WHEN + webhook = Webhook() + webhook.init_app(app) + + # THEN + app.add_url_rule.assert_called_once_with( + endpoint="/postreceive", rule="/postreceive", view_func=webhook._postreceive, methods=["POST"] + ) + + +def test_init_app_flow_should_not_accidentally_override_secrets(): + # GIVEN + app = mock.Mock() + + # WHEN + webhook = Webhook(secret="hello-world-of-secrecy") + webhook.init_app(app) + + # THEN + assert webhook.secret is not None + + +def test_init_app_flow_should_override_secrets(): + # GIVEN + app = mock.Mock() + + # WHEN + webhook = Webhook(secret="hello-world-of-secrecy") + webhook.init_app(app, secret="a-new-world-of-secrecy") + + # THEN + assert webhook.secret == "a-new-world-of-secrecy".encode("utf-8") + + def test_run_push_hook(webhook, handler, push_request): # WHEN webhook._postreceive()