Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Github integration - issue/project card creation #481

Merged
merged 8 commits into from
Apr 1, 2020
18 changes: 17 additions & 1 deletion server/src/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from services.requestDetailService import RequestDetailService
from services.ingress_service import ingress_service
from services.sqlIngest import DataHandler
from services.feedbackService import FeedbackService

app = Sanic(__name__)
CORS(app)
Expand All @@ -31,7 +32,9 @@ def environment_overrides():
if os.environ.get('TOKEN', None):
app.config['Settings']['Socrata']['TOKEN'] =\
os.environ.get('TOKEN')

if os.environ.get('GITHUB_TOKEN', None):
app.config['Settings']['Github']['GITHUB_TOKEN'] =\
os.environ.get('GITHUB_TOKEN')

def configure_app():
# Settings initialization
Expand Down Expand Up @@ -211,6 +214,19 @@ async def requestDetails(request, srnumber):
return json(return_data)


@app.route('/feedback', methods=["POST"])
@compress.compress()
async def handle_feedback(request):
github_worker = FeedbackService(app.config['Settings'])
postArgs = request.json
title = postArgs.get('title', None)
body = postArgs.get('body', None)

issue_id = await github_worker.create_issue(title, body)
response = await github_worker.add_issue_to_project(issue_id)
return json(response)


@app.route('/test_multiple_workers')
@compress.compress()
async def test_multiple_workers(request):
Expand Down
82 changes: 82 additions & 0 deletions server/src/services/feedbackService.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from json import dumps, loads
import requests_async as requests


class FeedbackService(object):
def __init__(self, config=None):
self.config = config
self.token = None if not self.config \
else self.config['Github']['GITHUB_TOKEN']
self.issues_url = None if not self.config \
else self.config['Github']['ISSUES_URL']
self.project_url = None if not self.config \
else self.config['Github']['PROJECT_URL']

async def create_issue(self, title, body, labels=['feedback'], milestone=None, assignees=[]):
"""
Creates a Github issue via Github API v3 and returns the new issue id.

Note: Per Github, the API (and required 'Accept' headers) may change without notice.
See https://developer.github.com/v3/issues/
"""
headers = {
"Authorization": "token {}".format(self.token),
"Accept": "application/vnd.github.v3+json"
}
data = {
'title': title,
'body': body,
'labels': labels,
'milestone': milestone,
'assigness': assignees
}
payload = dumps(data)

async with requests.Session() as session:
try:
response = await session.post(self.issues_url, data=payload, headers=headers)
response_content = loads(response.content)
issue_id = response_content['id']
response.raise_for_status()
return issue_id
except requests.exceptions.HTTPError as errh:
return "An Http Error occurred:" + repr(errh)
except requests.exceptions.ConnectionError as errc:
return "An Error Connecting to the API occurred:" + repr(errc)
except requests.exceptions.Timeout as errt:
return "A Timeout Error occurred:" + repr(errt)
except requests.exceptions.RequestException as err:
return "An Unknown Error occurred" + repr(err)


async def add_issue_to_project(self, issue_id, content_type='Issue'):
"""
Takes a Github issue id and adds the issue to a project board card.
Returns the response from Github API.

Note: Per Github, the API (and required 'Accept' headers) may change without notice.
See https://developer.github.com/v3/projects/cards/
"""
headers = {
"Authorization": "token {}".format(self.token),
"Accept": "application/vnd.github.inertia-preview+json"
}
data = {
'content_id': issue_id,
'content_type': content_type
}
payload = dumps(data)

async with requests.Session() as session:
try:
response = await session.post(self.project_url, data=payload, headers=headers)
response.raise_for_status()
return response.status_code
except requests.exceptions.HTTPError as errh:
return "An Http Error occurred:" + repr(errh)
except requests.exceptions.ConnectionError as errc:
return "An Error Connecting to the API occurred:" + repr(errc)
except requests.exceptions.Timeout as errt:
return "A Timeout Error occurred:" + repr(errt)
except requests.exceptions.RequestException as err:
return "An Unknown Error occurred" + repr(err)
6 changes: 6 additions & 0 deletions server/src/settings.example.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@ AP2015 = ms7h-a45h
YEARS=2015,2016,2017,2018,2019,2020
LIMIT=2000000
QUERY_SIZE=50000

[Github]
GITHUB_TOKEN = REDACTED
ISSUES_URL = https://api.github.com/repos/hackforla/311-data/issues
PROJECT_URL = REDACTED