web-dev-qa-db-fra.com

Comment cloner tous les projets d'un groupe à la fois dans GitLab?

Dans mon référentiel GitLab, j'ai un groupe de 20 projets. Je veux cloner tous les projets à la fois. Est-ce possible?

42
Doon

Pas vraiment, à moins que:

  • vous avez un 21ème projet qui référence les 20 autres sous la forme submodules .
    (auquel cas un clone suivi d'un git submodule update --init suffirait pour cloner et extraire les 20 projets)

  • ou vous listez d'une manière ou d'une autre les projets auxquels vous avez accès ( API de GitLab pour les projets ), et effectuez une boucle sur ce résultat pour les cloner (ce qui signifie qu'ils peuvent être scriptés, puis exécutés en tant que commande "one")


Depuis 2015, Jay Gabez mentionne dans les commentaires (août 2019) l'outil gabrie30/ghorg

ghorg vous permet de cloner rapidement toutes les organisations ou les utilisateurs dans un répertoire unique.

Usage:

$ ghorg clone someorg
$ ghorg clone someuser --clone-type=user --protocol=ssh --branch=develop
$ ghorg clone gitlab-org --scm=gitlab --namespace=gitlab-org/security-products
$ ghorg clone --help
18
VonC

Voici un exemple dans Python 3:

from urllib.request import urlopen
import json
import subprocess, shlex

allProjects     = urlopen("http://[yourServer:port]/api/v4/projects?private_token=[yourPrivateTokenFromUserProfile]&per_page=100000")
allProjectsDict = json.loads(allProjects.read().decode())
for thisProject in allProjectsDict: 
    try:
        thisProjectURL  = thisProject['ssh_url_to_repo']
        command     = shlex.split('git clone %s' % thisProjectURL)
        resultCode  = subprocess.Popen(command)

    except Exception as e:
        print("Error on %s: %s" % (thisProjectURL, e.strerror))
22
Hot Diggity

Il existe un outil appelé myrepos , qui gère plusieurs référentiels de contrôles de version. La mise à jour de tous les référentiels nécessite simplement une commande:

mr update

Pour enregistrer tous les projets gitlab sur mr, voici un petit script python. Il nécessite le package python-gitlab installé:

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"])
7
Benedikt

J'ai construit un script (curl, git, jq requis) juste pour ça. Nous l'utilisons et cela fonctionne très bien: https://Gist.github.com/JonasGroeger/1b5155e461036b557d0fb4b3307e1e75

Pour connaître votre espace de noms, il est préférable de vérifier l'API rapidement:

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

Là, utilisez "namespace.name" comme NAMESPACE pour votre groupe.

Le script fait essentiellement:

  1. Obtenez tous les projets qui correspondent à votre PROJECT_SEARCH_PARAM
  2. Obtenez leurs path et ssh_url_to_repo

    2.1. Si le répertoire path existe, insérez-le et appelez git pull

    2.2. Si le répertoire path n’existe pas, appelez git clone

7
Jonas Gröger

Voici un autre exemple de script bash permettant de cloner toutes les mises en pension d'un groupe. La seule dépendance à installer est jq ( https://stedolan.github.io/jq/ ). Placez simplement le script dans le répertoire dans lequel vous souhaitez cloner vos projets. Puis lancez-le comme suit:

./myscript <group name> <private token> <gitlab url>

c'est à dire.

./myscript group1 abc123tyn234 http://yourserver.git.com

Scénario:

#!/bin/bash
if command -v jq >/dev/null 2>&1; then
  echo "jq parser found";
else
  echo "this script requires the 'jq' json parser (https://stedolan.github.io/jq/).";
  exit 1;
fi

if [ -z "$1" ]
  then
    echo "a group name arg is required"
    exit 1;
fi

if [ -z "$2" ]
  then
    echo "an auth token arg is required. See $3/profile/account"
    exit 1;
fi

if [ -z "$3" ]
  then
    echo "a gitlab URL is required."
    exit 1;
fi

TOKEN="$2";
URL="$3/api/v3"
PREFIX="ssh_url_to_repo";

echo "Cloning all git projects in group $1";

GROUP_ID=$(curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups?search=$1 | jq '.[].id')
echo "group id was $GROUP_ID";
curl --header "PRIVATE-TOKEN: $TOKEN" $URL/groups/$GROUP_ID/projects?per_page=100 | jq --arg p "$PREFIX" '.[] | .[$p]' | xargs -L1 git clone
5
pbuchheit

Si vous êtes d'accord avec certains Sorecery Shell, cela va cloner toutes les pensions groupées par leur identifiant de groupe (vous avez besoin de jq et de parallèle)

seq 3                                                                           \
| parallel curl -s "'https://[gitlabUrl]/api/v4/projects?page={}&per_page=100&private_token=[privateToken]'
                     | jq '.[] | .ssh_url_to_repo, .name, .namespace.path'" \
| tr -d '"'                                                                 \
| awk '{ printf "%s ", $0; if (NR % 3 == 0) print " " }'                    \
| parallel --colsep ' ' 'mkdir -p {2} && git clone {1} {3}/{2}'
4
Moshohayeb

Un script mis à jour Python 3) accomplit cette tâche de manière vraiment efficace en utilisant la dernière API et la pagination appropriée de Gitlab:

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')

Nécessite la bibliothèque request (pour naviguer vers les liens de page).

4
forresthopkinsa

Une doublure avec boucle, jq, tr

for repo in $(curl "https://<your-Host>/api/v4/groups/<group_id>?private_token=<your_private_token>" | jq .projects[].ssh_url_to_repo | tr -d '"'); do git clone $repo; done;```
3

Vous pouvez vous référer à ce Ruby ici: https://Gist.github.com/thegauraw/da2a3429f19f603cf1c9b3b09553728b)

Mais vous devez vous assurer que vous avez le lien vers l'URL de l'organisation gitlab (qui ressemble à: https://gitlab.example.com/api/v3/ par exemple organisation) et le jeton privé ( qui ressemble à: QALWKQFAGZDWQYDGHADS et vous pouvez entrer dans: https://gitlab.example.com/profile/account une fois que vous êtes connecté). Assurez-vous également que vous avez installé httparty gem ou gem install httparty

2
thegauraw

Oui c'est possible, voici le code.

conditions préalables:

pip installer 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()

Exemple:

  • créer un fichier .py (ex. gitlab-downloader.py)
  • copier-coller du code ci-dessus
  • sous Linux OS (ou OSX), chmod + x dans le fichier de script (ex. chmod + x gitlab-downloader.py)
  • exécutez-le avec 3 paramètres: nom d'hôte Gitlab, nom de groupe, votre jeton d'accès personnel (voir https://gitlab.exmaple.com/profile/personal_access_tokens )
1

Une autre façon de le faire avec Windows "Git Bash" qui a des paquets limités installés:

#!/bin/bash
curl -o projects.json https://<GitLabUrl>/api/v4/projects?private_token=<YourToken>
i=0
while : ; do
    echo "/$i/namespace/full_path" > jsonpointer
    path=$(jsonpointer -f jsonpointer projects.json 2>/dev/null | tr -d '"')
    [ -z "$path" ] && break
    echo $path
    if [ "${path%%/*}" == "<YourProject>" ]; then
        [ ! -d "${path#*/}" ] && mkdir -p "${path#*/}"
        echo "/$i/ssh_url_to_repo" > jsonpointer
        url=$(jsonpointer -f jsonpointer projects.json 2>/dev/null | tr -d '"')
        ( cd "${path#*/}" ; git clone --mirror "$url" )
    fi
    let i+=1
done 
rm -f projects.json jsonpointer
1
olivm

Une alternative basée sur la réponse de Dmitriy - dans le cas où vous deviez cloner des référentiels dans une arborescence de groupe entier de manière récursive.

#!/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
Ilya Rodionov