Beispiel #1
0
def update_repository(repository_id, # pylint: disable=too-many-arguments
                      repository_project_id=None,
                      repository_type=None,
                      repository_name=None,
                      repository_url=None,
                      repository_external_id=None):
    """
    Updates a repository and returns the newly updated repository in dict format.
    Values of None means the field will not be updated.

    :param repository_id: ID of the repository to update.
    :type repository_id: ID
    :param repository_project_id: ID of the repository project.
    :type repository_project_id: string
    :param repository_name: New name for the repository.
    :type repository_name: string | None
    :param repository_type: New type for repository ('github', 'gerrit', etc).
    :type repository_type: string | None
    :param repository_url: New URL for the repository.
    :type repository_url: string | None
    :param repository_external_id: ID of the repository from the service provider.
    :type repository_external_id: string
    :return: dict representation of the repository object.
    :rtype: dict
    """
    repository = Repository()
    try:
        repository.load(str(repository_id))
    except DoesNotExist as err:
        return {'errors': {'repository_id': str(err)}}
    # TODO: Ensure project_id exists.
    if repository_project_id is not None:
        repository.set_repository_project_id(str(repository_project_id))
    if repository_type is not None:
        supported_repo_types = get_supported_repository_providers().keys()
        if repository_type in supported_repo_types:
            repository.set_repository_type(repository_type)
        else:
            return {'errors': {'repository_type':
                               'Invalid value passed. The accepted values are: (%s)' \
                               %'|'.join(supported_repo_types)}}
    if repository_external_id is not None:
        # Find a repository is already linked with this external_id
        linked_repository = Repository().get_repository_by_external_id(repository_external_id, repository.get_repository_type())
        # If found return an error
        if linked_repository is not None:
            return {'errors': {'repository_external_id': 'This repository is alredy configured for a contract group.'}}

        repository.set_repository_external_id(repository_external_id)
    if repository_name is not None:
        repository.set_repository_name(repository_name)
    if repository_url is not None:
        try:
            val = cla.hug_types.url(repository_url)
            repository.set_repository_url(val)
        except ValueError as err:
            return {'errors': {'repository_url': 'Invalid URL specified'}}
    repository.save()
    return repository.to_dict()
Beispiel #2
0
def handle_installation_repositories_added_event(action: str, body: dict):
    func_name = 'github.activity.handle_installation_repositories_added_event'
    # Who triggered the event
    user_login = body['sender']['login']
    cla.log.debug(f'{func_name} - processing github [installation_repositories] '
                  f'activity {action} callback created by GitHub user {user_login}.')
    # Grab the list of repositories added from the event model
    repository_added = body.get('repositories_added', [])
    # Create a unique list of repositories for the email that we need to send out
    repository_list = set([repo.get('full_name', None) for repo in repository_added])
    # All the repos in the message should be under the same GitHub Organization
    organization_name = ''
    for repo in repository_added:
        # Grab the information
        repository_external_id = repo['id']  # example: 271841254
        repository_name = repo['name']  # example: PyImath
        repository_full_name = repo['full_name']  # example: AcademySoftwareFoundation/PyImath
        organization_name = repository_full_name.split('/')[0]  # example: AcademySoftwareFoundation
        # repository_private = repo['private']      # example: False

        # Lookup the GitHub Organization in our table - should be there already
        cla.log.debug(f'{func_name} - Locating organization using name: {organization_name}')
        org_model = get_organization_model(organization_name)

        if org_model is None:
            # Should we create since it's missing?
            cla.log.warning(f'Unable to locate GitHub Organization {organization_name} in our database')
            continue

        # Should we update to ensure the installation_id is set?
        if org_model.get_organization_installation_id() is None:
            # Update the installation ID
            org_model.set_organization_installation_id(body.get('installation', {}).get('id', None))
            org_model.save()

        # Check to see if the auto enabled flag is set
        if org_model.get_auto_enabled():
            # We need to check that we only have 1 CLA Group - auto-enable only works when the entire
            # Organization falls under a single CLA Group - otherwise, how would we know which CLA Group
            # to add them to? First we query all the existing repositories associated with this Github Org -
            # they should all point the the single CLA Group - let's verify this...
            existing_github_repositories = Repository().get_repositories_by_organization(organization_name)
            cla_group_ids = set(())  # hoping for only 1 unique value - set collection discards duplicates
            cla_group_repo_sfids = set(())  # keep track of the existing SFDC IDs from existing repos
            for existing_repo in existing_github_repositories:
                cla_group_ids.add(existing_repo.get_repository_project_id())
                cla_group_repo_sfids.add(existing_repo.get_repository_sfdc_id())

            # We should only have one...
            if len(cla_group_ids) != 1 or len(cla_group_repo_sfids) != 1:
                cla.log.warning(f'{func_name} - Auto Enabled set for Organization {organization_name}, '
                                f'but we found repositories or SFIDs that belong to multiple CLA Groups. '
                                'Auto Enable only works when all repositories under a given '
                                'GitHub Organization are associated with a single CLA Group. This '
                                f'organization is associated with {len(cla_group_ids)} CLA Groups and '
                                f'{len(cla_group_repo_sfids)} SFIDs.')
                return

            cla_group_id = cla_group_ids.pop()

            project_model = get_project_instance()
            try:
                project_model.load(project_id=cla_group_id)
            except DoesNotExist as err:
                cla.log.warning(f'{func_name} - unable to load project (cla_group) by '
                                f'project_id: {cla_group_id}, error: {err}')

            cla.log.debug(f'{func_name} - Organization {organization_name} has auto_enabled set - '
                          f'adding repository: {repository_name} to '
                          f'CLA Group: {project_model.get_project_name()}')
            try:
                # Create the new repository entry and associate it with the CLA Group
                new_repository = Repository(
                    repository_id=str(uuid.uuid4()),
                    repository_project_id=cla_group_id,
                    repository_name=repository_full_name,
                    repository_type='github',
                    repository_url='https://github.com/' + repository_full_name,
                    repository_organization_name=organization_name,
                    repository_external_id=repository_external_id,
                    repository_sfdc_id=cla_group_repo_sfids.pop(),
                )
                new_repository.set_enabled(True)
                new_repository.save()

                # Log the event
                msg = (f'Adding repository {repository_full_name} '
                       f'from GitHub organization : {organization_name} '
                       f'with URL: https://github.com/{repository_full_name} '
                       'to the CLA configuration. GitHub organization was set to auto-enable.')
                Event.create_event(
                    event_type=EventType.RepositoryAdded,
                    event_project_id=cla_group_id,
                    event_project_name=project_model.get_project_name(),
                    event_company_id=None,
                    event_data=msg,
                    event_summary=msg,
                    event_user_id=user_login,
                    contains_pii=False,
                )
            except Exception as err:
                cla.log.warning(f'{func_name} - Could not create GitHub repository: {err}')
                return

        else:
            cla.log.debug(f'{func_name} - Auto enabled NOT set for GitHub Organization {organization_name} - '
                          f'not auto-adding repository: {repository_full_name}')
            return

    # Notify the Project Managers
    notify_project_managers_auto_enabled(organization_name, repository_list)
Beispiel #3
0
def create_repository(auth_user: AuthUser, # pylint: disable=too-many-arguments
                      repository_project_id,
                      repository_name,
                      repository_organization_name, 
                      repository_type,
                      repository_url,
                      repository_external_id=None):
    """
    Creates a repository and returns the newly created repository in dict format.

    :param repository_project_id: The ID of the repository project.
    :type repository_project_id: string
    :param repository_name: The new repository name.
    :type repository_name: string
    :param repository_type: The new repository type ('github', 'gerrit', etc).
    :type repository_organization_name: string
    :param repository_organization_name: The repository organization name
    :type repository_type: string
    :param repository_url: The new repository URL.
    :type repository_url: string
    :param repository_external_id: The ID of the repository from the repository provider.
    :type repository_external_id: string
    :return: dict representation of the new repository object.
    :rtype: dict
    """

    # Check that organization exists 
    github_organization = GitHubOrg()
    try:
        github_organization.load(str(repository_organization_name))
    except DoesNotExist as err:
        return {'errors': {'organization_name': str(err)}}

    # Check that project is valid. 
    project = Project()
    try:
        project.load(str(repository_project_id))
    except DoesNotExist as err:
        return {'errors': {'repository_project_id': str(err)}}

    # Get SFDC project identifier
    sfdc_id = project.get_project_external_id()

    # Validate user is authorized for this project
    can_access = cla.controllers.project.check_user_authorization(auth_user, sfdc_id)
    if not can_access['valid']:
      return can_access['errors']

    # Validate if exist already repository linked to a contract group
    if repository_external_id is not None:
        # Seach for the repository
        linked_repository = Repository().get_repository_by_external_id(repository_external_id, repository_type)
        # If found return an error
        if linked_repository is not None:
            return {'errors': {'repository_external_id': 'This repository is alredy configured for a contract group.'}}

    repository = Repository()
    repository.set_repository_id(str(uuid.uuid4()))
    repository.set_repository_project_id(str(repository_project_id))
    repository.set_repository_sfdc_id(str(sfdc_id))
    repository.set_repository_name(repository_name)
    repository.set_repository_organization_name(repository_organization_name)
    repository.set_repository_type(repository_type)
    repository.set_repository_url(repository_url)
    if repository_external_id is not None:
        repository.set_repository_external_id(repository_external_id)
    repository.save()
    return repository.to_dict()