Skip to content
This repository has been archived by the owner on May 27, 2021. It is now read-only.

Commit

Permalink
Handle crossdomain request
Browse files Browse the repository at this point in the history
  • Loading branch information
drewrygh committed Jan 3, 2015
1 parent ac3ace5 commit 4db2ce5
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 54 deletions.
53 changes: 53 additions & 0 deletions cron/issue.py
@@ -1,5 +1,7 @@
import datetime
import re
import github3
import requests
from config import CONFIG_VARS as cvar


Expand Down Expand Up @@ -168,3 +170,54 @@ def needs_reply(self):
return not any([c for c in comments if c.created_at.replace(tzinfo=None) > label_time and c.user.login != e.actor.login])

return False


def close_old_issues():

gh = github3.login(cvar['GITHUB_USERNAME'], cvar['GITHUB_PASSWORD'])
repo = gh.repository(cvar['REPO_USERNAME'], cvar['REPO_ID'])
issues = repo.iter_issues()

try: # Read message templates from remote URL
msg = requests.get(cvar['CLOSING_TEMPLATE']).text
except: # Read from local file
msg = open(cvar['CLOSING_TEMPLATE']).read()

closed = [Issue(i).close(msg=msg, reason='old') for i in issues]

print 'Old Issues Closed: '
print filter(lambda x: x is not None, closed)


def close_noreply_issues():

gh = github3.login(cvar['GITHUB_USERNAME'], cvar['GITHUB_PASSWORD'])
repo = gh.repository(cvar['REPO_USERNAME'], cvar['REPO_ID'])
issues = repo.iter_issues()

try: # Read message templates from remote URL
msg = requests.get(cvar['CLOSING_NOREPLY_TEMPLATE']).text
except: # Read from local file
msg = open(cvar['CLOSING_NOREPLY_TEMPLATE']).read()

closed = [Issue(i).close(msg=msg, reason='noreply') for i in issues]

print "No-Reply Issues Closed: "
print filter(lambda x: x is not None, closed)


def warn_old_issues():

gh = github3.login(cvar['GITHUB_USERNAME'], cvar['GITHUB_PASSWORD'])
repo = gh.repository(cvar['REPO_USERNAME'], cvar['REPO_ID'])
issues = repo.iter_issues()

try: # Read from remote URL
warning_msg = requests.get(cvar['WARNING_TEMPLATE']).text
except: # Read from local file
warning_msg = open(cvar['WARNING_TEMPLATE']).read()

warned = [Issue(i).warn(msg=warning_msg) for i in issues]

print "Old Issues Warned: "
print filter(lambda x: x is not None, warned)
43 changes: 43 additions & 0 deletions decorators.py
@@ -0,0 +1,43 @@
from datetime import timedelta
from flask import make_response, request, current_app
from functools import update_wrapper


def crossdomain(origin=None, methods=None, headers=None, max_age=21600, attach_to_all=True, automatic_options=True):
if methods is not None:
methods = ', '.join(sorted(x.upper() for x in methods))
if headers is not None and not isinstance(headers, basestring):
headers = ', '.join(x.upper() for x in headers)
if not isinstance(origin, basestring):
origin = ', '.join(origin)
if isinstance(max_age, timedelta):
max_age = max_age.total_seconds()

def get_methods():
if methods is not None:
return methods

options_resp = current_app.make_default_options_response()
return options_resp.headers['allow']

def decorator(f):
def wrapped_function(*args, **kwargs):
if automatic_options and request.method == 'OPTIONS':
resp = current_app.make_default_options_response()
else:
resp = make_response(f(*args, **kwargs))
if not attach_to_all and request.method != 'OPTIONS':
return resp

h = resp.headers

h['Access-Control-Allow-Origin'] = origin
h['Access-Control-Allow-Methods'] = get_methods()
h['Access-Control-Max-Age'] = str(max_age)
if headers is not None:
h['Access-Control-Allow-Headers'] = headers
return resp

f.provide_automatic_options = False
return update_wrapper(wrapped_function, f)
return decorator
77 changes: 27 additions & 50 deletions main.py
@@ -1,13 +1,14 @@
import json
import os
import requests
import github3
import threading
from flask import Response, request, Flask, render_template
from config import CONFIG_VARS as cvar
from cron.issue import Issue
from decorators import crossdomain
from cron.issue import close_old_issues, warn_old_issues
from cron.issue import close_noreply_issues
from webhooks.pull_request import validate_commit_messages
from webhooks.issue import flag_if_submitted_through_github
from webhooks.issue_comment import remove_flag_if_valid
from webhooks.issue_updated import remove_notice_if_valid


app = Flask(__name__)

Expand All @@ -25,84 +26,60 @@ def cron_close_old_issues():
"""
An endpoint for a cronjob to call.
Closes issues older than REMOVAL_DAYS.
@return: a JSON array containing the ids of closed issues
"""

gh = github3.login(cvar['GITHUB_USERNAME'], cvar['GITHUB_PASSWORD'])
repo = gh.repository(cvar['REPO_USERNAME'], cvar['REPO_ID'])
issues = repo.iter_issues()

try: # Read message templates from remote URL
msg = requests.get(cvar['CLOSING_TEMPLATE']).text
except: # Read from local file
msg = open(cvar['CLOSING_TEMPLATE']).read()
t = threading.Thread(target=close_old_issues)
t.start()
msg = 'close_old_issues task forked to background'

closed = [Issue(i).close(msg=msg, reason='old') for i in issues]
closed = filter(lambda x: x is not None, closed)

return Response(json.dumps({'closed': closed}), mimetype='application/json')
return Response(json.dumps({'message': msg}), mimetype='application/json')


@app.route("/api/close-noreply-issues", methods=['GET', 'POST'])
def cron_noreply_issues():
def cron_close_noreply_issues():
"""
An endpoint for a cronjob to call.
Closes issues that never received a requested reply.
@return: a JSON array containing the ids of closed issues
"""

gh = github3.login(cvar['GITHUB_USERNAME'], cvar['GITHUB_PASSWORD'])
repo = gh.repository(cvar['REPO_USERNAME'], cvar['REPO_ID'])
issues = repo.iter_issues()

try: # Read message templates from remote URL
msg = requests.get(cvar['CLOSING_NOREPLY_TEMPLATE']).text
except: # Read from local file
msg = open(cvar['CLOSING_NOREPLY_TEMPLATE']).read()
t = threading.Thread(target=close_noreply_issues)
t.start()
msg = 'close_noreply_issues task forked to background'

closed = [Issue(i).close(msg=msg, reason='noreply') for i in issues]
closed = filter(lambda x: x is not None, closed)

return Response(json.dumps({'closed': closed}), mimetype='application/json')
return Response(json.dumps({'message': msg}), mimetype='application/json')


@app.route("/api/warn-old-issues", methods=['GET', 'POST'])
def cron_warn_old_issues():
"""
An endpoint for a cronjob to call.
Adds a warning message to issues older than REMOVAL_WARNING_DAYS..
@return: a JSON array containing the ids of warned issues
Adds a warning message to issues older than REMOVAL_WARNING_DAYS.
"""
gh = github3.login(cvar['GITHUB_USERNAME'], cvar['GITHUB_PASSWORD'])
repo = gh.repository(cvar['REPO_USERNAME'], cvar['REPO_ID'])
issues = repo.iter_issues()

try: # Read from remote URL
warning_msg = requests.get(cvar['WARNING_TEMPLATE']).text
except: # Read from local file
warning_msg = open(cvar['WARNING_TEMPLATE']).read()

warned = [Issue(i).warn(msg=warning_msg) for i in issues]
warned = filter(lambda x: x is not None, warned)
t = threading.Thread(target=warn_old_issues)
t.start()
msg = 'warn_old_issues task forked to background'

return Response(json.dumps({'warned': warned}), mimetype='application/json')
return Response(json.dumps({'message': msg}), mimetype='application/json')


@app.route("/api/webhook", methods=['GET', 'POST'])
@app.route("/api/webhook", methods=['GET', 'POST', 'OPTIONS'])
@crossdomain(origin='*', headers=['Content-Type', 'X-Github-Event'])
def webhook_router():

event_type = request.headers['X-Github-Event']
payload = json.loads(request.data)
response = []
event_type = request.headers['X-Github-Event']
if request.data:
payload = json.loads(request.data)

if event_type == 'pull_request':
response.append(validate_commit_messages(payload))

if event_type == 'issues':
response.append(flag_if_submitted_through_github(payload))

if event_type == 'issue_comment':
response.append(remove_flag_if_valid(payload))
if event_type == 'issue_updated':
response.append(remove_notice_if_valid(request.args['issueNum']))

return Response(json.dumps(response), mimetype='application/json')

Expand Down
10 changes: 6 additions & 4 deletions webhooks/issue_comment.py → webhooks/issue_updated.py
Expand Up @@ -2,15 +2,17 @@
from config import CONFIG_VARS as cvar


def remove_flag_if_valid(payload):
def notice_flag_if_valid(issueNum):
"""
Removes the flag (automated comments and label) if the issue has been resubmitted
through the custom form on the Ionic site.
Removes the notice flag (automated comments and label) if the issue has been
resubmitted through the custom form on the Ionic site.
@param issueNum: the issue number that should be refreshed (string)
@return: whether or not the flag was removed (bool)
"""

print issueNum
gh = github3.login(cvar['GITHUB_USERNAME'], cvar['GITHUB_PASSWORD'])
i = gh.issue(cvar['REPO_USERNAME'], cvar['REPO_ID'], payload['issue']['number'])
i = gh.issue(cvar['REPO_USERNAME'], cvar['REPO_ID'], str(issueNum))

if i.labels:
labels = [l.name for l in i.labels]
Expand Down

0 comments on commit 4db2ce5

Please sign in to comment.