Exemplo n.º 1
0
def main():

    args = create_parser().parse_args()
    threads = int(args.threads)
    EXEC = threadly.Scheduler(threads)

    server_domain = args.server_url
    if args.server_url[:8] == "https://":
        server_domain = args.server_url[8:]
    elif args.server_url[:7] == "http://":
        server_domain = args.server_url[7:]

    if os.environ.get('BBMIGRATE_IN_DOCKER') == "true":
        open("{}/.gitconfig".format(str(Path.home())),
             "w").write("[credential]\n	helper = store\n")
        open("{}/.git-credentials".format(str(Path.home())),
             "w").write("https://{}:{}@{}\nhttps://{}:{}@{}\n".format(
                 args.server_user, urllib.parse.quote(args.server_pass),
                 server_domain, args.cloud_user,
                 urllib.parse.quote(args.cloud_pass), "bitbucket.org"))

    # setting up directory for repo clones
    dir_name = os.path.abspath(args.repo_path)
    clone_dir = dir_name
    try:
        if not os.path.isdir(clone_dir):
            os.mkdir(clone_dir)
    except OSError:
        logger.exception(f'Failed to create directory {clone_dir}')
        sys.exit(1)
    logger.info("Saving repos to path:{}".format(clone_dir))

    # initializing Bitbucket Server instance
    try:
        bitbucket_server = Bitbucket(url=args.server_url,
                                     username=args.server_user,
                                     password=args.server_pass)
    except Error:
        logger.exception(
            f'Unable to instantiate Bitbucker Server connection! One or more parameters may be missing or malformed.'
        )
        sys.exit(1)

    try:
        projects_gen = bitbucket_server.project_list()
    except Error:
        logger.exception(
            f'Failed to retrieve data from Bitbucket Server {args.server_url}')
        sys.exit(1)

    projects = []
    logger.info(
        f'Retrieving projects and repos from Bitbucket Server {args.server_url}'
    )
    for p in projects_gen:
        new_project_key = p['key'].replace("-", "")
        project_dir = os.path.join(clone_dir, new_project_key)
        p['project_dir'] = project_dir
        p['new_project_key'] = new_project_key
        projects.append(p)
        try:
            repos = bitbucket_server.repo_list(project_key=p['key'])
        except Error:
            logger.exception(
                "Failed to gather repository list from Bitbucket Server project {}"
                .format(p['name']))
            sys.exit(1)
        logger.info(
            "Retrieving repositories from Bitbucket Server project {}".format(
                p['name']))
        p['repos'] = []
        for r in repos:
            new_repo_name = new_project_key.lower() + "." + r['slug'].lower()
            repo_dir = os.path.join(project_dir, r['slug'])
            new_repo_git = "https://bitbucket.org/" + args.workspace + "/" + new_repo_name + ".git"
            old_repo_git = ""
            for href in r['links']['clone']:
                if href['href'][:8] == "https://":
                    old_repo_git = href['href']
                    break
            r['old_repo_git'] = old_repo_git
            r['new_repo_git'] = new_repo_git
            r['new_repo_name'] = new_repo_name
            r['repo_dir'] = repo_dir
            p['repos'].append(r)
        p['repos'] = sorted(p['repos'], key=lambda k: k['slug'])

    projects = sorted(projects, key=lambda k: k['key'])

    processing = []
    logger.info("Duplicating projects on BBCloud")
    for p in projects:
        proj = p
        f = EXEC.schedule_with_future(bbcloud.duplicate_project,
                                      args=(args.cloud_user, args.cloud_pass,
                                            args.workspace, proj))
        processing.append(f)

    for lf in processing:
        lf.get()

    processing = []
    logger.info("Duplicating repos and cloning them on BBCloud")
    for project in projects:
        project_name = project['name']
        project_dir = project['project_dir']
        try:
            os.mkdir(project_dir)
        except:
            pass
        for repo in project['repos']:
            p = project
            r = repo
            f = EXEC.schedule_with_future(
                git.backupRepo,
                args=(args.cloud_user, args.cloud_pass, args.workspace, p, r,
                      clone_dir, args.no_remove_repos))
            processing.append(f)
            if len(processing) > 10:
                for lf in processing:
                    lf.get()
                processing = []
    for lf in processing:
        lf.get()

    # When it's all over, remove the tmp dir to keep things tidy
    if not args.no_remove_repos:
        try:
            os_system_string = "rm -rf " + clone_dir
            os.system(os_system_string)
        except OSError:
            logger.exception(f'Failed to remove temp directory {clone_dir}')
            sys.exit(1)
Exemplo n.º 2
0
def main():
    parser = create_parser()
    parser_namespace = parser.parse_args(sys.argv[1:])
    bitbucket_url = parser_namespace.bitbucket
    bitbucket_user = parser_namespace.user
    bitbucket_pass = parser_namespace.passwd
    project_model_path = parser_namespace.file

    project_key = ntpath.basename(project_model_path).replace('_meta.yaml', '')

    project_map = yaml_read(project_model_path)

    if project_map['READY']:
        project_map = yaml_read(project_model_path)
        if project_map['RESOURCES'] and project_map['RESOURCES']['bitbucket']:

            project_model_bitbucket = project_map['RESOURCES']['bitbucket']
            project_name = project_model_bitbucket['name']
            project_description = project_model_bitbucket['description']

            bitbucket = Bitbucket(url=bitbucket_url,
                                  username=bitbucket_user,
                                  password=bitbucket_pass)

            bb_projects = bitbucket.project_list(limit=9999)

            if next(
                (i for i in bb_projects if i['key'] == project_key.upper()),
                    None):
                print(f'INFO: BitBucket project {project_key} already exists')
            else:
                bitbucket.create_project(project_key,
                                         project_name,
                                         description=project_description)
                print(f'INFO: BitBucket project {project_key} created')

            for group in project_model_bitbucket['privileges']:

                if 'delete' in project_model_bitbucket['privileges'][group]:
                    bitbucket.project_grant_group_permissions(
                        project_key, f'rb-{project_key}-{group}',
                        'PROJECT_ADMIN')
                    print(
                        f'INFO: rb-{project_key}-{group} PROJECT_ADMIN granted'
                    )

                elif 'write' in project_model_bitbucket['privileges'][group]:
                    bitbucket.project_grant_group_permissions(
                        project_key, f'rb-{project_key}-{group}',
                        'PROJECT_WRITE')
                    print(
                        f'INFO: rb-{project_key}-{group} PROJECT_WRITE granted'
                    )

                elif 'read' in project_model_bitbucket['privileges'][group]:
                    bitbucket.project_grant_group_permissions(
                        project_key, f'rb-{project_key}-{group}',
                        'PROJECT_READ')
                    print(
                        f'INFO: rb-{project_key}-{group} PROJECT_READ granted')

    else:
        print('MAP NOT READY')
# coding=utf-8
from atlassian import Bitbucket
from pprint import pprint

bitbucket = Bitbucket(url='http://localhost:7990',
                      username='******',
                      password='******')

pprint(bitbucket.project_list())
Exemplo n.º 4
0
class Server:
    """
    Class that represents the BitBucket server.

    Has methods to perform queries on the server.
    """
    def __init__(self, url: str, user: str, password: str):
        """
        C'tor of Server.

        :param str url: URL of the BitBucket server
        :param str user: Login username
        :param str password: Login password or token
        """
        self.server_url = url
        self.user = user
        self.password = password
        self.api = Bitbucket(self.server_url, self.user, self.password)

    def project_list(self) -> List[str]:
        """
        Get the list of projects from the server.

        :return: List of project names
        """
        query = self.api.project_list()
        return query

    def pr_approved(self, project: str, repo: str, pr: int) -> bool:
        """
        Return True if at least one reviewer approved the pull request, otherwise False.

        :param: project Project ID of the repository
        :param: repo Repository slug of the pull request
        :param: pr Pull request ID
        :returns: True if one reviewer approved the pull request, otherwise False
        """
        query = self.api.get_pull_request(project, repo, pr)
        for reviewer in query["reviewers"]:
            if reviewer["approved"]:
                return True
        return False

    def open_pr_in_repo(
        self,
        project: str,
        repo: str,
        src_branch: str,
        dst_branch: str,
        title: str,
        desc: str,
        reviewers: str = None,
    ):
        """
        Open a new pull request in a repository.

        :param project: Project name
        :param repo: Repository name
        :param src_branch: Source branch name
        :param dst_branch: Destination branch name
        :param title: Title of the pull request
        :param desc: Description text of the pull request
        :param reviewers: UUIDs of reviewers (default None)
        """
        self.open_pr(project, repo, src_branch, project, repo, dst_branch,
                     title, desc, reviewers)

    def open_pr(
        self,
        src_project: str,
        src_repo: str,
        src_branch: str,
        dst_project: str,
        dst_repo: str,
        dst_branch: str,
        title: str,
        desc: str,
        reviewers: str = None,
    ):
        """
        Open a new pull request.

        :param src_project: Source project name
        :param src_repo: Source repository name
        :param src_branch: Source branch name
        :param dst_project: Destination project name
        :param dst_repo: Destination repository name
        :param dst_branch: Destination branch name
        :param title: Title of the pull request
        :param desc: Description text of the pull request
        :param reviewers: UUIDs of reviewers (default None)
        """
        logging.info("Attempting to open a pull request:")
        logging.info(title)
        logging.info(desc)
        if self._confirm("Open pull request " + src_project + "/" + src_repo +
                         "/" + src_branch + "->" + dst_project + "/" +
                         dst_repo + "/" + dst_branch):
            self.api.open_pull_request(
                src_project,
                src_repo,
                dst_project,
                dst_repo,
                src_branch,
                dst_branch,
                title,
                desc,
                reviewers,
            )
            print("Success")
        else:
            print("Action aborted")

    @staticmethod
    def _confirm(question: str) -> bool:
        """Ask for user decision on question."""
        reply = str(input(question + " (y/n): ")).lower().strip()
        return reply[0] == "y"