Skip to content

Commit

Permalink
Easy CLA Checks Tab Provision (#598)
Browse files Browse the repository at this point in the history
- Created checks tab in case of check fails
- Handle invalid github ids

Resolves: #204

Signed-off-by: Harold <wanyaland@gmail.com>

Co-authored-by: David Deal <dealako@gmail.com>
  • Loading branch information
wanyaland and dealako authored Feb 24, 2020
1 parent 094f267 commit 282252e
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 6 deletions.
23 changes: 22 additions & 1 deletion cla-backend/cla/controllers/github_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

import os
import time
import requests
from requests.exceptions import RequestException

from github import BadCredentialsException, UnknownObjectException, GithubException, GithubIntegration, Github
from jose import jwt
Expand Down Expand Up @@ -53,6 +55,25 @@ def __init__(self, installation_id):
'{}, error: {}'.format(self.app_id, self.installation_id, e))
raise e

def create_check_run(self, repository_name, data):
"""
Function that creates a check run for unsigned users
"""
try:
url = 'https://api.github.com/repos/{}/check-runs'.format(repository_name)
requests.post(
url,
data=data,
headers={
'Content-Type': 'application/json',
'Authorization': 'token %s' % self.token,
'Accept': 'application/vnd.github.antiope-preview+json'
}
)

except RequestException as err:
cla.log.debug(err)


class GithubCLAIntegration(GithubIntegration):
"""
Expand All @@ -70,5 +91,5 @@ def create_jwt(self):
"iss": self.integration_id
}
gh_jwt = jwt.encode(payload, self.private_key, 'RS256')
# cla.log.debug('github jwt: {}'.format(gh_jwt))
#cla.log.debug('github jwt: {}'.format(gh_jwt))
return gh_jwt
65 changes: 60 additions & 5 deletions cla-backend/cla/models/github_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""
Holds the GitHub repository service.
"""

import json
import os
import uuid

Expand Down Expand Up @@ -340,7 +340,8 @@ def update_change_request(self, installation_id, github_repository_id, change_re
cla.log.debug('PR: {}, updating github pull request for repo: {}, '
'with signed authors: {} with missing authors: {}'.
format(pull_request.number, github_repository_id, signed, missing))
update_pull_request(installation_id, github_repository_id, pull_request,
repository_name = repository.get_repository_name()
update_pull_request(installation_id, github_repository_id, pull_request, repository_name,
signed=signed, missing=missing)

def get_pull_request(self, github_repository_id, pull_request_number, installation_id):
Expand Down Expand Up @@ -632,7 +633,23 @@ def handle_commit_from_user(project, commit_sha, author_info, signed, missing):
return

# Didn't find a signed signature for this project - add to our missing bucket list
missing.append((commit_sha, list(author_info)))
list_author_info = list(author_info)
signatures = cla.utils.get_signature_instance().get_signatures_by_project(project.get_project_id())
for signature in signatures:
if cla.utils.is_whitelisted(
signature,
email=author_email,
github_id=author_id,
github_username=author_username
):
# Append whitelisted flag to the author info list
cla.log.debug(
'Github user(id:{}, user: {}, email {}) is whitelisted but not affiliated'.
format(author_id, author_username, author_email)
)
list_author_info.append(True)
break
missing.append((commit_sha, list_author_info))


def get_pull_request_commit_authors(pull_request):
Expand Down Expand Up @@ -715,7 +732,7 @@ def has_check_previously_failed(pull_request: PullRequest) -> bool:
return False


def update_pull_request(installation_id, github_repository_id, pull_request, signed,
def update_pull_request(installation_id, github_repository_id, pull_request, repository_name, signed,
missing): # pylint: disable=too-many-locals
"""
Helper function to update a PR's comment/status based on the list of signers.
Expand All @@ -733,14 +750,51 @@ def update_pull_request(installation_id, github_repository_id, pull_request, sig
:type signed: [(string, string)]
:param missing: The list of (commit hash, author name) tuples that have not signed
an signature for this PR.
:type missing: [(string, string)]
:type missing: [(string, list)]
"""
notification = cla.conf['GITHUB_PR_NOTIFICATION']
both = notification == 'status+comment' or notification == 'comment+status'
last_commit = pull_request.get_commits().reversed[0]

# Here we update the PR status by adding/updating the PR body - this is the way the EasyCLA app
# knows if it is pass/fail.
#Create check run for users that havent yet signed and/or affiliated
if missing:
text = ""
for authors in missing:
#Check for valid github id
if authors[1][0] is None:
help_url = "https://help.github.com/en/github/committing-changes-to-your-project/why-are-my-commits-linked-to-the-wrong-user"
else:
help_url = cla.utils.get_full_sign_url('github', installation_id, github_repository_id, pull_request.number)
client = GitHubInstallation(installation_id)
#check if unsigned user is whitelisted
commit_sha = authors[0]
if commit_sha != last_commit.sha:
continue
author_email = authors[1][2]
author_id = authors[1][0]
if author_id:
if len(authors[1]) == 4:
text += f'{author_email} must confirm corporate affiliation.\n'
else:
text += f'{author_email} is not authorized under a signed CLA.\n'
else:
text += f'{author_email} is not linked to this commit. \n'

payload = {
"name": "CLA check",
"head_sha": last_commit.sha,
"status": "completed",
"conclusion": "action_required",
"details_url": help_url,
"output": {
"title": "EasyCLA: Signed CLA not found",
"summary": "One or more committers are authorized under a signed CLA.",
"text": text,
},
}
client.create_check_run(repository_name, json.dumps(payload))

if both or notification == 'comment':
body = cla.utils.assemble_cla_comment('github', installation_id, github_repository_id, pull_request.number,
Expand Down Expand Up @@ -783,6 +837,7 @@ def update_pull_request(installation_id, github_repository_id, pull_request, sig
create_commit_status(pull_request, last_commit.sha, state, sign_url, body, context)



def create_commit_status(pull_request, commit_hash, state, sign_url, body, context):
"""
Helper function to create a pull request commit status message given the PR and commit hash.
Expand Down

0 comments on commit 282252e

Please sign in to comment.