webhooks-with-cloud-run/MicroServices/GitHub/github.py (64 lines of code) (raw):

# Copyright 2019 Google, LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import base64 import hmac import json import os import sys import time import urllib from flask import Flask, request from google.cloud import secretmanager_v1beta1 from hashlib import sha1 app = Flask(__name__) @app.route("/", methods=["POST"]) def index(): # Subscribes to Pub/Sub Topic # and sends a message to Slack Channel envelope = request.get_json() # Check if valid JSON if not envelope: raise Exception("Expecting JSON payload") # Check if valid pub/sub message if "message" not in envelope: raise Exception("Not a valid Pub/Sub Message") msg = envelope["message"] data = json.loads(base64.b64decode(msg["data"]).decode("utf-8").strip()) if data["action"] == "opened": # Post response to Github create_issue_comment(data["issue"]["url"]) sys.stdout.flush() return ("", 204) def create_issue_comment(api_url): # Posts an auto response to Github Issue # Get tokens pem = get_secret(os.environ.get("PROJECT_NAME"), os.environ.get("PEM"), "1") app_token = get_jwt(pem) installation_token = get_installation_token(app_token) # Create Github issue comment via HTTP POST try: msg = { "body": "Thank you for filing an issue. \ Someone will respond within 24 hours." } req = urllib.request.Request( api_url + "/comments", data=json.dumps(msg).encode("utf8") ) req.add_header("Authorization", f"Bearer {installation_token}") response = urllib.request.urlopen(req) except Exception as e: print(e) def get_jwt(pem): # Encodes and returns JWT from jwt import JWT, jwk_from_pem payload = { "iat": int(time.time()), "exp": int(time.time()) + (10 * 60), "iss": os.environ.get("APP_ID"), } jwt = JWT() return jwt.encode(payload, jwk_from_pem(pem), "RS256") def get_installation_token(jwt): # Get App installation token to use Github API req = urllib.request.Request(os.environ.get("INSTALLATION"), method="POST") req.add_header("Authorization", f"Bearer {jwt}") req.add_header("Accept", "application/vnd.github.machine-man-preview+json") response = urllib.request.urlopen(req) token_json = json.loads(response.read()) return token_json["token"] def get_secret(project_name, secret_name, version_num): # Returns secret payload from Cloud Secret Manager client = secretmanager_v1beta1.SecretManagerServiceClient() name = client.secret_version_path(project_name, secret_name, version_num) secret = client.access_secret_version(name) return secret.payload.data if __name__ == "__main__": PORT = int(os.getenv("PORT")) if os.getenv("PORT") else 8080 # This is used when running locally. Gunicorn is used to run the # application on Cloud Run. See entrypoint in Dockerfile. app.run(host="127.0.0.1", port=PORT, debug=True)