#!/usr/bin/python3 from flask import Flask, request, abort import json import requests app = Flask(__name__) API_TOKEN = "" def warning(msg): print(msg) def api_get(url): headers = {"accept": "application/json"} url = "%s?token=%s&access_token=%s" % (url, API_TOKEN, API_TOKEN) response = requests.get(url, headers=headers) return response.json() def api_put(url, data): headers = {"accept": "application/json", "Content-Type": "application/json"} url = "%s?token=%s&access_token=%s" % (url, API_TOKEN, API_TOKEN) response = requests.put(url, data=json.dumps(data), headers=headers) return response.json() def get_repo_labels(issue_url): repo_url = "/".join(issue_url.split("/")[:-2]) return api_get(repo_url + "/labels") def get_status_label(action, issue_state, issue_labels): closed_states = {"status/Archived", "status/Resolved"} if action == "closed": for label in issue_labels: if label['name'] in closed_states: return label["name"] return "status/Resolved" elif action == "reopened": for label in issue_labels: if label["name"].startswith("status/") and label['name'] not in closed_states: return label['name'] return "status/Confirmed" elif issue_state == "closed": for label in issue_labels: if label['name'] in closed_states: return label['name'] return "status/Archived" else: for label in issue_labels: if label["name"].startswith("status/") and label['name'] not in closed_states: return label['name'] return "status/Needs Triage" def issue_validate_labels(data): # Set status/Resolved label on automaticall closed issue. # TODO: distinguish from manually closed? action = data.get("action", "") issue = data["issue"] issue_url = issue["url"] issue_state = issue["state"] issue_labels = issue["labels"] repo_labels = get_repo_labels(issue_url) new_status = get_status_label(action, issue_state, issue_labels) for label in repo_labels: if label["name"] == new_status: new_status_id = label["id"] print(new_status_id) new_labels = [new_status_id] old_labels = [] for label in issue_labels: print(label["id"], label["name"]) old_labels.append(label["id"]) if not label["name"].startswith("status/"): new_labels.append(label["id"]) print(sorted(new_labels), sorted(old_labels)) if sorted(new_labels) != sorted(old_labels): api_put(issue_url + "/labels", {"labels": new_labels}) def handle_request(event, data): print(event) print(data) if event == "issues": issue_validate_labels(data) @app.route("/webhook", methods=["POST"]) def root(): # Get event and data event = request.headers.get("X-GitHub-Event", "") try: data = request.get_json() except Exception: warning("Failed to parse json from request") abort(400) # Handle try: handle_request(event, data) except Exception as err: warning("Failed to handle request: " + str(err)) abort(400) return "OK" if __name__ == "__main__": app.run(debug=True)