Gerrit同步Gitlab

发布于 2023年12月15日

1.将Gerrit的项目名称导入到一个文件内,如下命令是将所有以Platform/AC8015开头的项目名称导入到gerrit_repo.xml文件中,使用这个命令必须将ssh-key公钥放置到appuser账户中。

ssh -p 29418 appuser@Gerrit地址 gerrit ls-projects | grep "Platform/AC8015" > gerrit_repo.xml

2.运行python脚本以gerrit_repo.xml生成replication.config配置文件,并且去除Gerrit仓库路径中的单个字符,生成gitlab_repo.xml文件。

Python文件内容:

# 打开 gerrit_repo.xml 文件
with open("C:/Desktop/脚本/gitlab_create_repos/gerrit_repo.xml", "r") as infile:
    # 读取每一行的内容
    lines = infile.readlines()

# 打开输出文件
with open("C:/Desktop/脚本/gitlab_create_repos/replication.config", "w") as outfile:
    # 打开 gitlab_repo.xml 文件
    with open("C:/Desktop/脚本/gitlab_create_repos/gitlab_repo.xml", "w") as xmlfile:
        # 遍历每一行
        for line in lines:
            # 去除行中的单个字符和多余的 /
            parts = [p.strip() for p in line.split('/')]
            new_parts = [p for p in parts if len(p) > 1]

            # 替换小数点为 -
            path1 = "/".join(new_parts).replace(".", "-")
            path2 = "/".join(new_parts)

            # 写入 replication.config 文件
            outfile.write("[remote \"" + line.strip() + "\"]\n")
            outfile.write("projects = " + line.strip() + "\n")
            outfile.write("url = ssh://git@10.30.4.54:2289/" + path1 + ".git\n")
            outfile.write("push = +refs/heads/*:refs/heads/*\n")
            outfile.write("push = +refs/tags/*:refs/tags/*\n")
            outfile.write("push = +refs/changes/*:refs/changes/*\n")
            outfile.write("threads = 3\n\n")

            # 写入 gitlab_repo.xml 文件
            xmlfile.write(path2 + "\n")

3.python脚本创建Gitlab仓库,如果创建不成功会将错误仓库路径写入error_Path.txt中。

如果有创建不成功的仓库,那需要用户手动操作。
创建仓库不成功错误目前只遇到一种,是仓库路径冲突。
例如:
AC8010/device/autochips/common
AC8010/device/autochips/common/carlink
创建这两个仓库,先创建common仓库,就不能创建carlink仓库,因为common是仓库不能作为群组来使用。如果先创建carlink仓库,那么就会显示common路径被占用。
就需要手动操作,将其更改路径,并且更改replication.config配置文件。
脚本内容:

import gitlab

# 使用GitLab API的类
class GitlabAPI:
    # 初始化函数,传入GitLab的URL和访问令牌
    def __init__(self, url, token):
        # 创建GitLab对象
        self.gl = gitlab.Gitlab(url, private_token=token)
    # 创建GitLab仓库的函数,传入仓库路径
    def create_project(self, repo_path):
        try:
            # 解析仓库路径,获取仓库名称和命名空间名称
            parts = repo_path.strip().split('/')
            project_name = parts[-1]
            namespace_parts = parts[:-1]
            namespace_id = None
            # 遍历命名空间路径,检查每个部分是否存在
            for part in namespace_parts:
                if not part:
                    continue
                if namespace_id is None:
                    try:
                        # 尝试获取该组
                        namespace = self.gl.groups.get(part, include_subgroups=True)
                        namespace_id = namespace.id
                    except gitlab.exceptions.GitlabGetError as e:
                        if e.response_code == 404:
                            # 组不存在,创建它
                            namespace = self.gl.groups.create({'name': part, 'path': part})
                            namespace_id = namespace.id
                else:
                    try:
                        # 尝试获取该子组
                        subgroup_path = "/".join(namespace_parts[:namespace_parts.index(part)+1])
                        subgroup = self.gl.groups.get(subgroup_path, include_subgroups=True)
                        namespace_id = subgroup.id
                    except gitlab.exceptions.GitlabGetError as e:
                        if e.response_code == 404:
                            # 子组不存在,创建它
                            parent_path = "/".join(namespace_parts[:namespace_parts.index(part)])
                            parent = self.gl.groups.get(parent_path, include_subgroups=True)
                            subgroup = self.gl.groups.create({'name': part, 'path': part, 'parent_id': parent.id})
                            namespace_id = subgroup.id
            # 创建仓库并输出成功信息
            project = self.gl.projects.create({'name': project_name, 'namespace_id': namespace_id})
            print(f"Project '{project_name}' created in namespace '{'/'.join(namespace_parts)}'")
        # 出错时,输出错误信息并将仓库路径写入错误文件
        except Exception as e:
            print(f'Error creating project in GitLab: {str(e)}')
            with open("C:/Desktop/脚本/gitlab_create_repos/error_Path.txt", "a") as error_file:
                error_file.write(f"{repo_path}\n")
# 在主函数中调用GitLab API,从文件中读取仓库路径并创建仓库
if __name__ == "__main__":
    # 创建GitLab API对象
    gl_api = GitlabAPI('http://gitlab地址', 'gitlab用户token')
    # 打开包含仓库路径的文件
    with open("C:/Desktop/脚本/gitlab_create_repos/gitlab_repo.xml", "r") as f:
        #去除每行开头和结尾的空格和换行符,并将剩余的内容作为参数传递给 create_project 
        for line in f:
            gl_api.create_project(line.strip())

更改gitlab地址与gitlab用户token,直接运行脚本即可,就会自动创建仓库。
还有地址如果没有也需要更改
C:/Desktop/脚本/gitlab_create_repos/gitlab_repo.xml
C:/Desktop/脚本/gitlab_create_repos/error_Path.txt

之后将replication.config文件写入到gerrit的replication.config文件内,然后重新加载replication插件,等待同步成功。