bradshjg / flask-githubapp

Flask extension for rapid Github app development in Python, in the spirit of probot (https://probot.github.io/)
MIT License
56 stars 14 forks source link

Errors running locally #14

Closed Napo2k closed 3 years ago

Napo2k commented 3 years ago

Hello!

I am trying to use this to - duh - set up a github app. I have gotten, I believe, all the details related to app id, signature, key, etc. I have a bunch of prepared payloads from git to test, and I have the app running as flask locally as per your README However when I send one of the requests:

STOLTM6653 ॐ  ~/Work/gitbot: git@master! [08:46:08] ± curl -H "X-GitHub-Event: push" -H "Content-Type: application/json" -X POST -d @./zzpayloads/master_push.json localhost:5000           ✹ ✭
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>

and the output from the flask server process is:

Traceback (most recent call last):
  File "/Users/nachofernandez/Work/gitbot/.env/lib/python3.9/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/nachofernandez/Work/gitbot/.env/lib/python3.9/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/nachofernandez/Work/gitbot/.env/lib/python3.9/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/nachofernandez/Work/gitbot/.env/lib/python3.9/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/Users/nachofernandez/Work/gitbot/.env/lib/python3.9/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/nachofernandez/Work/gitbot/.env/lib/python3.9/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/nachofernandez/Work/gitbot/.env/lib/python3.9/site-packages/flask_githubapp/core.py", line 172, in _flask_view_func
    self._verify_webhook()
  File "/Users/nachofernandez/Work/gitbot/.env/lib/python3.9/site-packages/flask_githubapp/core.py", line 192, in _verify_webhook
    signature = request.headers['X-Hub-Signature'].split('=')[1]
  File "/Users/nachofernandez/Work/gitbot/.env/lib/python3.9/site-packages/werkzeug/datastructures.py", line 1463, in __getitem__
    return _unicodify_header_value(self.environ["HTTP_" + key])
KeyError: 'HTTP_X_HUB_SIGNATURE'

I have checked the git payloads in the webhook I am trying to put this github app on, and I don't see any X-Hub-Signature headers. I see headers like:

Request URL: 
Request method: POST
content-type: application/json
Expect: 
User-Agent: GitHub-Hookshot/b56da86
X-GitHub-Delivery: <some-guid>
X-GitHub-Enterprise-Host: <host>
X-GitHub-Enterprise-Version: 2.22.5
X-GitHub-Event: pull_request

The payload itself is a full push payload - in any case my code doesn't do anything with it just yet. Is this a problem on my end, is it that I am using a wrong flask-githubapp version (I am on flask 1.1.2 and flask-githubapp 0.2.0)?

Napo2k commented 3 years ago

I was able to deploy in Kubernetes so I can test "in real life conditions" - however some local testing solution would be awesome, to be able to iterate quicker :)

Napo2k commented 3 years ago

I have made changes locally so if the app is running in DEBUG mode, the webhook verification doesn't happen, and a warning is displayed on boot.

bradshjg commented 3 years ago

Howdy, thanks so much for stopping by and sorry you're running into trouble. In order to develop GitHub Apps locally I use ngrok to create a tunnel that allows me to run the app locally and receive hooks payloads from GitHub, is that something you're interested in?

I'm also curious If it possible the X-Hub-Signature header is missing due to either the GitHub App configuration (on the GitHub side) or because the hook didn't originate from GitHub? I'm very interested in the local changes you were able to make to help make things work smoother for you. I'd love to be able to incorporate anything helpful 😄

Napo2k commented 3 years ago

Hello! Thanks for the answer

So, what I did was download a payload from Github - so I guess it's technically another way of testing the app without needing to set up the webhook to point to your development environment.

I guess these payloads are plain json so I have to construct the curl request like I explained, with custom headers, so I am fairly sure the problem is that the app is not receiving a proper Github payload (i.e., missing headers and as such no X-Hub-Signature). I think a DEBUG mode is a bit simpler, and requires less things to be installed :) but alas! I made it work so I can continue using this without a problem. This was the way I normally tested the app that I am refactoring, using this package. For clarity, my way of testing is running the flask app on my machine, and sending requests to localhost:5000.

I forked this repo into my company's github (is it's own instance, so it doesn't show in this github as forked), but I will gladly repeat the changes here and open a PR if you give me permissions :)

bradshjg commented 3 years ago

That makes sense, thanks for walking me through your process.

To support that behavior (it also simplified testing a bit 🙏 ), I've created a PR to change the behavior of the GITHUBAPP_SECRET config setting to allow providing False to disable verification with the idea that we can support the workflow you mention above.

I'm curious what sort of interface you decided on for supporting your workflow, and would be happy to use your design over the idea above if that's preferable to you.

Feel free to run git diff 236ba9e6331bdea01428a6c5cb3f1986d95f09ab > changes.patch (that's the commit that represents the head of the default branch right now) and copy the contents of that patch file here, I'm happy to dig through it myself and really appreciate your help.

I've also added you as a collaborator if it would be easier for you to create a branch and PR here. Thanks again.

Napo2k commented 3 years ago

I resorted to the FLASK_DEBUG config value. I think either way is explicit enough - i.e., I guess you won't do it by mistake. Perhaps your solution is a bit better since, if someone does indeed make a mistake (when has that ever happened), at least you won't be exposing the app to a potential code injection.

Napo2k commented 3 years ago

Oh, also, not related to any of this, but I didn't want to open an issue about that - I revamped the README in my fork so it is even clearer, how to use this module

For instance, explaining, in this function declaration

@github_app.on('issues.opened')
def cruel_closer():

when exactly does it get triggered, so as to make it super easy for people to map webhooks and their payloads, to functions. Plus the "local debug, payload only" workflows. I can send it over to you if you want!

bradshjg commented 3 years ago

That would be awesome, thanks so much. I'm not super happy with the README two years ago me wrote 😄

Napo2k commented 3 years ago

Alright! Will start working on this on a branch and open a PR. Part of these readme improvements are a more streamlined workflow to locally run the sample app :D

Napo2k commented 3 years ago

I think we can close this one, what do you say?

bradshjg commented 3 years ago

I agree, thanks for your help.