Example #1
0
def handle_issue_comment(data):
    """ Handle a issue_comment event.

        This event is triggered any time a pull request or issue is commented
        on.
    """

    # We're only interested in pull request comments for now
    if "pull_request" not in data["issue"]:
        return

    # TODO: Might need to do something different for different "action" values
    # if different action values are ever implemented

    # TODO message-id

    # Figure out what email this will be a reply to
    pull_request = get_github(data["issue"]["pull_request"]["url"]).json()
    cover_msg_id = pull_request_msg_id(pull_request)

    subject = "Re: " + pull_request_subject(pull_request)
    from_addr = "%s <%s>" % (data["comment"]["user"]["login"], os.environ["GHEH_EMAIL_FROM"])
    body = data["comment"]["body"] + email_footer(data["issue"]["html_url"])

    msg = MIMEText(body)
    msg['From'] = from_addr
    msg['Subject'] = subject
    msg['In-Reply-To'] = cover_msg_id
    msg['Date'] = json_to_email_date(data["issue"]["updated_at"])
    send_email(msg)
Example #2
0
def handle_pull_request_review_comment(data):
    """ Handle a pull request review comment.

        This event is triggered by comments left on the unified diff (both
        split and unified views) for a pull request, via the "Files changed"
        tab.
    """

    # TODO: same as issue comments, might need to do something with "action" if
    # action ever gets used

    # TODO Message-Id

    cover_msg_id = pull_request_msg_id(data["pull_request"])
    
    subject = "Re: " + pull_request_subject(data["pull_request"])
    from_addr = "%s <%s>" % (data["comment"]["user"]["login"], os.environ["GHEH_EMAIL_FROM"])

    # Start with the diff being commented on as a quote
    body = '\n'.join('> ' + line for line in data["comment"]["diff_hunk"].split('\n'))
    body += '\n\n' + data["comment"]["body"]
    body += '\n' + email_footer(data["comment"]["html_url"])

    msg = MIMEText(body)
    msg['From'] = from_addr
    msg['Subject'] = subject
    msg['In-Reply-To'] = cover_msg_id
    msg['Date'] = json_to_email_date(data["comment"]["updated_at"])
    send_email(msg)
Example #3
0
def handle_pull_request(data):
    """ Handle a pull_request event.

        This event is triggered when a pull request is assigned, unassigned,
        labeled, unlabeled, opened, closed, reopened, or synchronized.

        https://developer.github.com/v3/activity/events/types/#pullrequestevent
    """

    # Pull requests form the base of the email threads used in this webook.
    # Any time a request is opened or synchronized (push --force on the branch
    # to be pulled), start a new email thread using the pull request body as
    # the cover letter, and reply to it with each of the patches.

    pull_request = data["pull_request"]

    # Construct the message ID for the cover letter that we will either be
    # sending or replying to
    cover_msg_id = pull_request_msg_id(data["pull_request"])

    subject_base = pull_request_subject(pull_request)

    if data["action"] in ("opened", "synchronize"):
        if data["action"] == "opened":
            subject = "New: "
        else:
            subject = "Updated: "

        subject += subject_base

        from_addr = "%s <%s>" % (data["sender"]["login"], os.environ["GHEH_EMAIL_FROM"])

        body = pull_request["body"] + email_footer(pull_request["html_url"])

        cover_letter = MIMEText(body)
        cover_letter['From'] = from_addr
        cover_letter['Subject'] = subject
        cover_letter['Message-Id'] = cover_msg_id
        cover_letter['Date'] = json_to_email_date(pull_request['updated_at'])
        send_email(cover_letter)

        # Get a list of commits in this pull request
        commit_list = get_github(pull_request["url"] + "/commits").json()
        patch_num = 1
        tot_num = len(commit_list)

        # Start with the PR date for the patches and add one second to each
        # as we go so that the patches appear in the right order.
        # This is the same thing that git-send-email does, both in terms of
        # throwing away the commit Date and using incrementing seconds to
        # order the patch emails.
        patch_date_ts = iso8601.parse_date(pull_request['updated_at']).timestamp()

        for commit in commit_list:
            # Start with the .patch file provided by github since it's
            # formatted all nice and email-like
            msg = read_message(commit['html_url'] + '.patch')

            # Set the message as a reply to the cover letter
            msg['In-Reply-To'] = cover_msg_id

            msg['Message-Id'] = patch_msg_id(pull_request, commit["sha"])

            del msg['Date']
            msg['Date'] = email.utils.formatdate(timeval=patch_date_ts)

            # Prepend a From: to the body of the message so git-am works right.
            # Add the footer.
            msg.set_payload('From: %s\n\n%s\n%s' % \
                    (msg['From'], msg.get_payload(),
                        email_footer(commit['html_url'], msg_type='commit')))

            # Replace the From header with ourselves
            del msg['From']
            msg['From'] = from_addr

            # Reset the Content-Transfer-Encoding so that non-ascii characters
            # get encoded right. This will encode the payload as base64.
            del msg['Content-Transfer-Encoding']
            msg.set_charset('utf-8')

            # Monkey with the subject to get the patch numbers and branch name in there
            subject = msg['Subject'].replace('[PATCH]',
                    '[%s %d/%d]' % (pull_request["base"]["ref"], patch_num, tot_num), 1)
            del msg['Subject']
            msg['Subject'] = subject
            send_email(msg)

            patch_date_ts += 1
            patch_num += 1

        # Create (or update) a database record with the pull request and
        # the list of commits
        client = pymongo.MongoClient(os.environ[os.environ["GHEH_DB_ENVVAR"]])
        db = client[os.environ['GHEH_DB_NAME']]
        pull_request_coll = db[PULL_REQUEST_COLLECTION]

        record = pull_request_coll.find_one({'pull_request.id': pull_request['id']})
        if record:
            record['pull_request'] = pull_request
            record['commit_list'] = commit_list
            pull_request_coll.save(record)
        else:
            pull_request_coll.insert({'pull_request': pull_request, 'commit_list': commit_list})

    elif data["action"] in ("closed", "reopened", "assigned", "unassigned", "labeled", "unlabeled"):
        subject = "Re: %s" % subject_base

        # If the action was assigned, say whom it was assigned to in the body
        if data["action"] == "assigned":
            body = "Assigned to %s" % data["assignee"]["login"]
        # For labels, put the label in the body
        elif data["action"] == "labeled":
            body = "Added label: %s." % data["label"]["name"]
        elif data["action"] == "unlabeled":
            body = "Removed label: %s." % data["label"]["name"]
        # For everything else just say what happened
        # uppercase the first letter
        else:
            body = "%s." % data["action"].title()

        from_addr = "%s <%s>" % (data["sender"]["login"], os.environ["GHEH_EMAIL_FROM"])

        msg = MIMEText(body + email_footer(pull_request["html_url"]))
        msg["From"] = from_addr
        msg["Subject"] = subject
        msg["In-Reply-To"] = cover_msg_id
        msg["Date"] = json_to_email_date(pull_request["updated_at"])
        send_email(msg)