You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by GitBox <gi...@apache.org> on 2020/08/16 17:51:49 UTC

[GitHub] [incubator-mxnet-ci] ChaiBapchya commented on a change in pull request #27: Serverless based Lambda function for Labelling Successful PRs with pr-awaiting-review

ChaiBapchya commented on a change in pull request #27:
URL: https://github.com/apache/incubator-mxnet-ci/pull/27#discussion_r471139900



##########
File path: services/lambda-pr-status-labeler/PRStatusBot.py
##########
@@ -0,0 +1,298 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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 ast
+import json
+import hmac
+import hashlib
+import os
+import logging
+import re
+import secret_manager
+
+from github import Github
+
+
+class PRStatusBot:
+    def __init__(self,
+                 repo=os.environ.get("repo"),
+                 github_personal_access_token=None,
+                 apply_secret=True):
+        """
+        Initializes the PR Status Bot
+        :param repo: GitHub repository that is being referenced
+        :param github_personal_access_token: GitHub authentication token (Personal access token)
+        :param apply_secret: GitHub secret credential (Secret credential that is unique to a GitHub developer)
+        """
+        self.repo = repo
+        self.github_personal_access_token = github_personal_access_token
+        if apply_secret:
+            self._get_secret()
+
+    def _get_secret(self):
+        """
+        This method is to get secret value from Secrets Manager
+        """
+        secret = json.loads(secret_manager.get_secret())
+        self.github_personal_access_token = secret["github_personal_access_token"]
+        self.webhook_secret = secret["webhook_secret"]
+
+    def _secure_webhook(self, event):
+        """
+        This method will validate the security of the webhook, it confirms that the secret
+        of the webhook is matched and that each github event is signed appropriately
+        :param event: The github event we want to validate
+        :return Response denoting success or failure of security
+        """
+
+        # Validating github event is signed
+        try:
+            git_signed = ast.literal_eval(event["Records"][0]['body'])['headers']["X-Hub-Signature"]
+        except KeyError:
+            raise Exception("WebHook from GitHub is not signed")
+        git_signed = git_signed.replace('sha1=', '')
+
+        # Signing our event with the same secret as what we assigned to github event
+        secret = self.webhook_secret
+        body = ast.literal_eval(event["Records"][0]['body'])['body']
+        secret_sign = hmac.new(key=secret.encode('utf-8'), msg=body.encode('utf-8'), digestmod=hashlib.sha1).hexdigest()
+
+        # Validating signatures match
+        return hmac.compare_digest(git_signed, secret_sign)
+
+    def _get_github_object(self):
+        """
+        This method returns github object initialized with Github personal access token
+        """
+        github_obj = Github(self.github_personal_access_token)
+        return github_obj
+
+    def _get_pull_request_object(self, github_obj, pr_number):
+        """
+        This method returns a PullRequest object based on the PR number
+        :param github_obj
+        :param pr_number
+        """
+        repo = github_obj.get_repo(self.repo)
+        pr_obj = repo.get_pull(pr_number)
+        return pr_obj
+
+    def _get_commit_object(self, github_obj, commit_sha):
+        """
+        This method returns a Commit object based on the SHA of the commit
+        :param github_obj
+        :param commit_sha
+        """
+        repo = github_obj.get_repo(self.repo)
+        commit_obj = repo.get_commit(commit_sha)
+        return commit_obj
+
+    def _drop_other_pr_labels(self, pr, desired_label):
+        labels = pr.get_labels()
+
+        for label in labels:
+            logging.info(f'Label:{label}')
+            if label.name.startswith('pr-') and label.name != desired_label:
+                try:
+                    logging.info(f'Removing {label}')
+                    # pr.remove_from_labels(label)
+                except Exception:
+                    logging.error(f'Error while removing the label {label}')
+
+    def _add_label(self, pr, label):
+        # drop other PR labels
+        self._drop_other_pr_labels(pr, label)
+
+        # check if the PR already has the desired label
+        if(self._has_desired_label(pr, label)):
+            logging.info(f'PR {pr.number} already contains the label {label}')
+            return
+
+        # try:
+        #     pr.add_to_labels(label)
+        # except Exception:
+        #     logging.error(f'Unable to add label {label}')
+
+        # verify that label has been correctly added
+        if(self._has_desired_label(pr, label)):
+            logging.info(f'Successfully labeled {label} for PR-{pr.number}')
+        else:
+            logging.info(f'Not labeled {label}')
+        return
+
+    def _has_desired_label(self, pr, desired_label):
+        """
+        This method returns True if desired label found in PR labels
+        """
+        labels = pr.get_labels()
+        for label in labels:

Review comment:
       Labels is a PaginatedList of objects of type Label. Each object has an attribute `name`
   I guess Python doesn't allow to check if objects in a list contain an attribute value without iteration.
   I could use 
   ```
   any(label.name == desired_label for label in labels)
   ```
   But in general I'd have to iterate. Correct me if wrong.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org