Commit 951f2590 authored by Didier WECKMANN's avatar Didier WECKMANN
Browse files

feat(core): initial commit

parent 8ceb6106
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import os
import time
import gitlab
def main():
"""
Main function
"""
# Get application arguments
parsed_arguments = parse_arguments()
# Initialize gitlab API
gitlab_instance = initialize_gitlab(parsed_arguments)
duplicate_group(parsed_arguments, gitlab_instance, parsed_arguments.from_group, parsed_arguments.to_group)
def parse_arguments(arguments=None):
"""
Parse command line arguments
Args:
arguments: optional argument list, to allow unit testing
Returns:
ArgumentParser object
"""
# Arguments parsing
parser = argparse.ArgumentParser(
description='Perform various git or conan task on Sight GitLab repositories.'
)
parser.add_argument(
'--gitlab_config',
type=str,
help='GitLab Python API configuration path. Default to ~/.python-gitlab.cfg'
)
parser.add_argument(
'--gitlab_config_section',
type=str,
default='ircad.fr',
help='GitLab Python API configuration section in configuration file.'
)
parser.add_argument(
'--gitlab_url',
type=str,
help='GitLab URL. Default to https://git.ircad.fr'
)
parser.add_argument(
'--gitlab_token',
type=str,
help='GitLab private access token.'
)
parser.add_argument(
'--dry',
action='store_true',
default=False,
help='do nothing but print things.'
)
parser.add_argument(
'--force',
action='store_true',
default=False,
help='be careless and overwrite things like existing merge request.'
)
parser.add_argument(
'--verbose',
action='store_true',
default=False,
help='prints some stuff.'
)
parser.add_argument(
'--from_group',
type=str,
help='Group source.'
)
parser.add_argument(
'--to_group',
type=str,
help='Group destination.'
)
# arguments is not None if coming from tests
if arguments is None:
parsed_arguments = parser.parse_args()
else:
parsed_arguments = parser.parse_args(arguments)
return parsed_arguments
def initialize_gitlab(parsed_arguments):
"""
Return an initialized gitlab object
Args:
parsed_arguments: parsed arguments from command line
Returns:
GitLab instance object
"""
gitlab_config = parsed_arguments.gitlab_config
gitlab_url = parsed_arguments.gitlab_url
gitlab_token = parsed_arguments.gitlab_token
# Use default value for configuration if not given as argument
if not gitlab_config or not os.path.exists(gitlab_config):
gitlab_config = os.path.join(os.path.expanduser('~'), '.python-gitlab.cfg')
# Use default value for url if the url is not given as argument
if not gitlab_url:
gitlab_url = 'https://git.ircad.fr'
# Use default value for token if not given as argument
if not gitlab_token:
gitlab_token = os.getenv('GITLAB_TOKEN')
# If an url or a token has been specified or the config cannot be opened
if parsed_arguments.gitlab_url or parsed_arguments.gitlab_token or not os.path.exists(gitlab_config):
return gitlab.Gitlab(gitlab_url, private_token=gitlab_token, ssl_verify=False, api_version='4')
else:
return gitlab.Gitlab.from_config(parsed_arguments.gitlab_config_section, gitlab_config)
def duplicate_group(parsed_arguments, gitlab_instance, from_group, to_group):
"""
Duplicate a group and all its projects.
Args:
parsed_arguments: parsed arguments from command line
gitlab_instance: the gitlab instance
from_group: the origin group
to_group: the target group
"""
# Get the conan group
from_gitlab_group = gitlab_instance.groups.get(from_group, lazy=True)
# Get or create the target group
try:
to_gitlab_group = gitlab_instance.groups.get(to_group)
except Exception:
to_gitlab_group = None
pass
if to_gitlab_group:
if parsed_arguments.dry or parsed_arguments.verbose:
print("delete existing target group {0}".format(to_group))
if not parsed_arguments.dry:
to_gitlab_group.delete()
time.sleep(10)
# Wait a bit
try:
while gitlab_instance.groups.get(to_group):
time.sleep(10)
except:
pass
if parsed_arguments.dry or parsed_arguments.verbose:
print("create group {0}".format(to_group))
# Create the new group
if not parsed_arguments.dry:
retry = 0
while retry < 10:
try:
to_gitlab_group = gitlab_instance.groups.create({'name': to_group, 'path': to_group})
retry = 99
except Exception as e:
if parsed_arguments.verbose:
print("\nWAITING for 'gitlab_instance.groups.create()' ({0})... {1}".format(retry, e))
retry = retry + 1
time.sleep(10)
pass
if retry != 99:
raise ValueError("Cannot create group {0}. Aborting...".format(to_group))
# For each project
from_group_projects = from_gitlab_group.projects.list(as_list=False, lazy=True)
projects_count = len(from_group_projects)
for group_project in from_group_projects:
# Get the project instance
project = gitlab_instance.projects.get(group_project.id, lazy=True)
if parsed_arguments.dry or parsed_arguments.verbose:
print("fork project {0}".format(group_project.path_with_namespace))
if not parsed_arguments.dry:
fork = project.forks.create({'namespace': to_group})
time.sleep(1)
# Delete fork relation
forked_project = gitlab_instance.projects.get(fork.id, lazy=True)
forked_project.delete_fork_relation()
time.sleep(1)
# This should not exist, but unfortunately, the group duplication is not instantaneous
# and we got http error 500, time to time.
retry = 0
while retry < 50:
try:
group = gitlab_instance.groups.get(parsed_arguments.to_group)
group_projects = group.projects.list(as_list=False, lazy=True)
if projects_count != len(group_projects):
raise LookupError(
"Not the same number of project in group {0} ({1}) and in group {2} ({3})...".format(
from_group,
projects_count,
to_group,
len(group_projects)
)
)
for group_project in group_projects:
if parsed_arguments.verbose:
print("\nProject {0} forked !".format(group_project.name))
project = gitlab_instance.projects.get(group_project.id)
project_branches = project.branches.list()
for project_branch in project_branches:
if parsed_arguments.verbose:
print("\t...with branch {0}".format(project_branch.name))
retry = 99
except Exception as e:
if not parsed_arguments.dry:
retry = retry + 1
if parsed_arguments.verbose:
print("\nWAITING for 'gitlab_instance.projects.get()' ({0})... {1}".format(retry, e))
time.sleep(60)
pass
else:
exit(0)
if retry != 99:
raise LookupError("Cannot lookup all projects and branches on group {0}...".format(to_group))
if __name__ == "__main__":
main()
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment