Beispiel #1
0
def watch_orgs():
    try:
        gh.update_org_membership()
    except Exception:
        logger.exception('Failed to update org membership.')

    return gevent.spawn_later(app.config['WATCHED_ORGS_RELOAD_INTERVAL'],
                              watch_orgs)
Beispiel #2
0
def update_org_membership():
    logger.info('Refreshing watched organization membership.')
    ghc = get_github_client()
    for org_name in app.config['WATCHED_ORGS']:
        org = ghc.get_organization(org_name)
        try:
            ORG_MEMBERS[org_name] = [m.login for m in org.get_members()]
        except Exception:
            logger.exception(
                'Failed to get org membership for {}'.format(org_name))
Beispiel #3
0
def handle_webhook(message):
    data = json.loads(message['Body'])
    if data['action'] not in gh.HANDLED_PR_ACTIONS:
        logger.debug('Skipping unhandled action {}'.format(data['action']))
        return
    if data['action'] == 'closed':
        logger.debug('Skipping closed action')
        return
    try:
        gh.update_pr_status(data['full_repo_name'], data['pr_number'])
    except Exception:
        logger.exception('Failed to update status for {}#{}'.format(
            data['full_repo_name'], data['pr_number']))
Beispiel #4
0
def update_prs_for_username(username):
    logger.debug('Updating PRs for {}'.format(username))
    for pr in PullRequest.scan(username__eq=username):
        full_repo_name, pr_number = pr.pr.split(':')
        logger.debug('Adding an SQS message for {}, {}'.format(
            full_repo_name, pr_number))
        try:
            # Fake a synchronize repo action, to enqueue a PR check
            _queue_repo_action('synchronize', full_repo_name, int(pr_number))
        except Exception:
            logger.exception('Failed to queue SQS message for {}/{}'.format(
                full_repo_name, pr_number))
        try:
            # We know this user signed, so we can get rid of this PR in dynamo.
            pr.delete()
        except Exception:
            logger.exception('Failed to delete PR {}/{}'.format(
                full_repo_name, pr_number))
Beispiel #5
0
 def save(self, *args, **kwargs):
     # First, actually save the signature in dynamo
     super(Signature, self).save(*args, **kwargs)
     # Next, enqueue a message for async actions based on this signature
     try:
         sqs_client = osscla.services.sqs.get_client()
         q_url = osscla.services.sqs.get_queue_url()
         sqs_client.send_message(QueueUrl=q_url,
                                 MessageBody=json.dumps(
                                     {'username': self.username}),
                                 MessageAttributes={
                                     'type': {
                                         'DataType': 'String',
                                         'StringValue': 'signature'
                                     }
                                 })
     except Exception:
         logger.exception('Failed to queue signature message for {}'.format(
             self.username))
Beispiel #6
0
def handle_message(client, queue_url):
    try:
        response = client.receive_message(
            QueueUrl=queue_url,
            AttributeNames=['SentTimestamp'],
            MaxNumberOfMessages=1,
            MessageAttributeNames=['All'],
            VisibilityTimeout=60,
            WaitTimeSeconds=10
        )
        if 'Messages' in response:
            messages = response['Messages']
            message = messages[0]
            if 'type' not in message['MessageAttributes']:
                logger.error('SQS message does not have a type attribute.')
                return
            m_type = message['MessageAttributes']['type']['StringValue']
            logger.debug('Received SQS message of type {}'.format(m_type))
            if m_type == 'github_webhook':
                try:
                    handle_webhook(message)
                except Exception:
                    logger.exception(
                        'Failed to handle webhook SQS message'
                    )
                    return
            elif m_type == 'signature':
                try:
                    handle_signature(message)
                except Exception:
                    logger.exception(
                        'Failed to handle signature SQS message'
                    )
                    return
            else:
                logger.error(
                    '{} is an unsupported message type.'.format(m_type)
                )
            client.delete_message(
                QueueUrl=queue_url,
                ReceiptHandle=message['ReceiptHandle']
            )
        else:
            logger.debug('No messages, continuing')
            return
    except Exception:
        logger.exception('General error')
Beispiel #7
0
def update_pr_status(full_repo_name, pr_number):
    # We care about the author of all commits in the PR, so we'll find the
    # author of every commit, and ensure they have signatures.
    logger.debug('Updating PR status for PR {}/{}'.format(
        full_repo_name, pr_number))
    ghc = get_github_client()
    repo = ghc.get_repo(full_repo_name)
    pr = repo.get_pull(pr_number)
    commits = pr.get_commits()
    authors = []
    author_without_login = False
    for commit in commits:
        last_commit = commit
        try:
            authors.append(commit.author.login)
        except Exception:
            logger.exception('Failed to access the login name for a commit')
            author_without_login = True
    if author_without_login:
        last_commit.create_status(
            'failure',
            description=(
                'An author in one of the commits has no associated github name'
            ),
            target_url=app.config['SITE_URL'],
            context=app.config['GITHUB_STATUS_CONTEXT'])
        return
    else:
        last_commit.create_status('pending',
                                  context=app.config['GITHUB_STATUS_CONTEXT'])
    authors = list(set(authors))
    missing_authors = []
    # Check to see if the authors have signed the CLA
    for author in authors:
        if check_org_membership(author):
            # User is in a github org we have an org CLA with
            logger.debug('User {} has an org CLA'.format(author))
            continue
        try:
            Signature.get(author)
        except Signature.DoesNotExist:
            missing_authors.append(author)
    if missing_authors:
        for missing_author in missing_authors:
            # Save the PR info, so we can re-check the PR when signatures
            # occur.
            try:
                _pr = PullRequest(username=missing_author,
                                  pr='{0}:{1}'.format(repo.full_name,
                                                      pr_number))
                _pr.save(pr__null=True)
                logger.debug(
                    'Saved PR for missing author {}'.format(missing_author))
            except PutError:
                logger.debug('Skipping creation of existing PR in dynamo.')
        msg = ('The following authors related to commits in this PR have'
               ' not signed the CLA: {0}')
        msg = msg.format(', '.join(missing_authors))
        last_commit.create_status('failure',
                                  description=msg,
                                  target_url=app.config['SITE_URL'],
                                  context=app.config['GITHUB_STATUS_CONTEXT'])
        logger.debug('Submitted status for missing authors {0}.'.format(
            ','.join(missing_authors)))
    else:
        last_commit.create_status(
            'success',
            description='All authors have signed the CLA.',
            target_url=app.config['SITE_URL'],
            context=app.config['GITHUB_STATUS_CONTEXT'])