How to clone all projects of a group at once in GitLab?

后端 未结 15 1429
[愿得一人]
[愿得一人] 2020-12-23 02:02

In my GitLab repository, I have a group with 20 projects. I want to clone all projects at once. Is that possible?

相关标签:
15条回答
  • 2020-12-23 02:49

    An updated Python 3 script that accomplishes this really effectively using Gitlab's latest api and proper pagination:

    import requests
    import subprocess, shlex
    import os
    
    print('Starting getrepos process..')
    
    key = '12345678901234567890' # your gitlab key
    base_url = 'https://your.gitlab.url/api/v4/projects?simple=true&per_page=10&private_token='
    url = base_url + key
    
    base_dir = os.getcwd()
    
    while True:
        print('\n\nRetrieving from ' + url)
        response = requests.get(url, verify = False)
        projects = response.json()
    
        for project in projects:
            project_name = project['name']
            project_path = project['namespace']['full_path']
            project_url = project['ssh_url_to_repo']
    
            os.chdir(base_dir)
            print('\nProcessing %s...' % project_name)
    
            try:
                print('Moving into directory: %s' % project_path)
                os.makedirs(project_path, exist_ok = True)
                os.chdir(project_path)
                cmd = shlex.split('git clone --mirror %s' % project_url)
                subprocess.run(cmd)
            except Exception as e:
                print('Error: ' + e.strerror)
    
        if 'next' not in response.links:
            break
    
        url = response.links['next']['url'].replace('127.0.0.1:9999', 'your.gitlab.url')
    
    
    print('\nDone')
    

    Requires the requests library (for navigating to the page links).

    0 讨论(0)
  • 2020-12-23 02:50

    An alternative based on Dmitriy's answer -- in the case you were to clone repositories in a whole group tree recursively.

    #!/usr/bin/python3
    import os
    import sys
    import gitlab
    import subprocess
    
    glab = gitlab.Gitlab(f'https://{sys.argv[1]}', f'{sys.argv[3]}')
    groups = glab.groups.list()
    root = sys.argv[2]
    
    def visit(group):
        name = group.name
        real_group = glab.groups.get(group.id)
    
        os.mkdir(name)
        os.chdir(name) 
    
        clone(real_group.projects.list(all=True))
    
        for child in real_group.subgroups.list():
            visit(child)
    
        os.chdir("../")
    
    def clone(projects):
        for repo in projects:
            command = f'git clone {repo.ssh_url_to_repo}'
            process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
            output, _ = process.communicate()
            process.wait()
    
    glab = gitlab.Gitlab(f'https://{sys.argv[1]}', f'{sys.argv[3]}')
    groups = glab.groups.list()
    root = sys.argv[2]
    
    for group in groups:
        if group.name == root:
            visit(group)
    
    0 讨论(0)
  • 2020-12-23 02:51

    You can refer to this ruby script here: https://gist.github.com/thegauraw/da2a3429f19f603cf1c9b3b09553728b

    But you need to make sure that you have the link to the organization gitlab url (which looks like: https://gitlab.example.com/api/v3/ for example organization) and private token (which looks like: QALWKQFAGZDWQYDGHADS and you can get in: https://gitlab.example.com/profile/account once you are logged in). Also do make sure that you have httparty gem installed or gem install httparty

    0 讨论(0)
  • 2020-12-23 02:52

    I built a script (curl, git, jq required) just for that. We use it and it works just fine: https://gist.github.com/JonasGroeger/1b5155e461036b557d0fb4b3307e1e75

    To find out your namespace, its best to check the API quick:

    curl "https://domain.com/api/v3/projects?private_token=$GITLAB_PRIVATE_TOKEN"
    

    There, use "namespace.name" as NAMESPACE for your group.

    The script essentially does:

    1. Get all Projects that match your PROJECT_SEARCH_PARAM
    2. Get their path and ssh_url_to_repo

      2.1. If the directory path exists, cd into it and call git pull

      2.2. If the directory path does not exist, call git clone

    0 讨论(0)
  • 2020-12-23 02:53

    Yep it's possible, here is the code.

    prerequisites:

    pip install python-gitlab

    #!/usr/bin/python3
    import os
    import sys
    import gitlab
    import subprocess
    
    glab = gitlab.Gitlab(f'https://{sys.argv[1]}', f'{sys.argv[3]}')
    groups = glab.groups.list()
    groupname = sys.argv[2]
    for group in groups:
        if group.name == groupname:
            projects = group.projects.list(all=True)
    
    for repo in projects:
        command = f'git clone {repo.ssh_url_to_repo}'
        process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
        output, _ = process.communicate()
        process.wait()
    

    Example:

    • create .py file (ex. gitlab-downloader.py)
    • copy-paste code from above
    • on Linux OS (or OSX) do chmod +x on the script file (ex. chmod +x gitlab-downloader.py)
    • run it with 3 params: Gitlab hostname, groupname, your Personal Access Token(see https://gitlab.exmaple.com/profile/personal_access_tokens)
    0 讨论(0)
  • 2020-12-23 02:56

    There is a tool called myrepos, which manages multiple version controls repositories. Updating all repositories simply requires one command:

    mr update
    

    In order to register all gitlab projects to mr, here is a small python script. It requires the package python-gitlab installed:

    import os
    from subprocess import call
    from gitlab import Gitlab
    
    # Register a connection to a gitlab instance, using its URL and a user private token
    gl = Gitlab('http://192.168.123.107', 'JVNSESs8EwWRx5yDxM5q')
    groupsToSkip = ['aGroupYouDontWantToBeAdded']
    
    gl.auth() # Connect to get the current user
    
    gitBasePathRelative = "git/"
    gitBasePathRelativeAbsolut = os.path.expanduser("~/" + gitBasePathRelative)
    os.makedirs(gitBasePathRelativeAbsolut,exist_ok=True)
    
    for p in gl.Project():
        if not any(p.namespace.path in s for s in groupsToSkip):
            pathToFolder = gitBasePathRelative + p.namespace.name + "/" + p.name
            commandArray = ["mr", "config", pathToFolder, "checkout=git clone '" + p.ssh_url_to_repo + "' '" + p.name + "'"]
            call(commandArray)
    
    os.chdir(gitBasePathRelativeAbsolut)
    
    call(["mr", "update"])
    
    0 讨论(0)
提交回复
热议问题