async def needs_rebase_hook(request): payload = await request.read() # Verify the payload against the signature if (request.headers.get("X-Hub-Signature") and request.app.get("github_payload_key")): try: verify_signature( request.app["github_payload_key"], request.headers["X-Hub-Signature"], payload, ) except InvalidSignature: return web.json_response( {"message": "Invalid signature"}, status=400, ) data = json.loads(payload.decode(request.charset or "utf8")) # We only care about a few different kinds of actions, the rest of them # are not useful to us, so we'll no-op out quickly if it is one of them. if (data.get("action") not in {"opened", "reopened", "synchronize"}): return web.json_response({"message": "Skipped due to action"}) # Check our PR async with aiohttp.ClientSession() as session: gh = gidgethub.aiohttp.GitHubAPI( session, "BrownTruck", oauth_token=request.app["github_token"], ) await _check_pr(gh, data["pull_request"]["url"]) return web.Response(status=204)
async def news_hook(request): payload = await request.read() # Verify the payload against the signature if (request.headers.get("X-Hub-Signature") and request.app.get("github_payload_key")): try: verify_signature( request.app["github_payload_key"], request.headers["X-Hub-Signature"], payload, ) except InvalidSignature: return web.json_response( {"message": "Invalid signature"}, status=400, ) data = json.loads(payload.decode(request.charset or "utf8")) # We only care about a few different kinds of actions, the rest of them # are not useful to us, so we'll no-op out quickly if it is one of them. if (data.get("action") not in { "labeled", "unlabeled", "opened", "reopened", "synchronize" }): return web.json_response({"message": "Skipped due to action"}) async with aiohttp.ClientSession() as session: gh = gidgethub.aiohttp.GitHubAPI( session, "BrownTruck", oauth_token=request.app["github_token"], ) # Grab our labels out of GitHub's API tries = 5 while True: try: issue_data = await gh.getitem(data["pull_request"]["issue_url"] ) label_data = await gh.getitem(issue_data["labels_url"]) except gidgethub.BadRequest as exc: if (isinstance(exc.status_code, http.HTTPStatus.NOT_FOUND) and tries > 0): tries -= 1 await asyncio.sleep(1) raise else: break labels = {l["name"] for l in label_data} # Grab the diff from GitHub and parse it into a diff object. diff_url = data["pull_request"]["diff_url"] async with session.get(diff_url) as resp: diff = unidiff.PatchSet(io.StringIO(await resp.text())) # Determine if the status check for this PR is passing or not and # update the status check to account for that. if ("trivial" in labels or any(not f.is_removed_file for f in diff if _news_fragment_re.search(f.path))): await gh.post( data["pull_request"]["statuses_url"], data={ "context": NEWS_FILE_CONTEXT, "target_url": HELP_URL, "state": "success", "description": "News files updated and/or change is trivial.", }, ) return web.json_response({ "message": "news file updated and/or ignored", }) else: await gh.post( data["pull_request"]["statuses_url"], data={ "context": NEWS_FILE_CONTEXT, "target_url": HELP_URL, "state": "failure", "description": "Missing either a news entry or a trivial file/label.", }, ) return web.json_response({ "message": "news file was not updated", "labels": list(labels), "files": [{ "path": f.path, "is_added_file": f.is_added_file } for f in diff], })