获取gitlab上项目分支版本(二)

获取gitlab上项目分支版本_gitlab代码分支版本在哪-CSDN博客

原先写过一版,但是这次想更新一下项目的分支信息时,提示我

git服务器上的Python版本是2.7.3,这个错误表明当前Python环境中没有安装requests库,服务器也没有连接外网,所以排除了上面的方法。换了一种方式是获取列表后 测试发现是输出到屏幕,想直接生成一个表格,这样便于后面分析。计划是使用xlwt库来创建Excel文件的,但是机器里也没有安装xlwt,所以采用CSV代替Excel, Python内置的csv模块,无需额外安装,输出为CSV格式,可直接用Excel打开。

  1. 文件管理

    • 自动创建输出目录GitLab_Branch_Reports

    • 文件名包含时间戳,便于区分不同时间的报告

  2. 输出格式优化

    • 表头:项目ID, 项目名称, 分支数量, 分支列表

    • 分支列表以逗号分隔,方便查看。

使用说明

  1. 将脚本保存为gitlab_branches_csv.py

  2. 在命令行中运行:python gitlab_branches_csv.py

  3. 脚本运行完成后,在GitLab_Branch_Reports目录下找到CSV文件

  4. 用Excel打开CSV文件查看结果

    python 复制代码
    # -*- coding: utf-8 -*-
    import urllib2
    import json
    import time
    import sys
    import socket
    import csv
    import os
    from datetime import datetime
    
    # 配置信息
    GITLAB_URL = 'http://172.16.67.163:8083'
    ACCESS_TOKEN = 'glpat-xcyhWihzE7Z3SxQVicuY'
    HEADERS = {'PRIVATE-TOKEN': ACCESS_TOKEN}
    TIMEOUT = 30  # 请求超时时间(秒)
    MAX_RETRIES = 3  # 最大重试次数
    DELAY_BETWEEN_REQUESTS = 0.5  # 请求间隔(秒)
    
    def test_connection():
        """测试网络连接并验证API访问权限"""
        print("测试连接至 GitLab 服务器...")
        try:
            # 测试网络连接
            host, port = '172.16.67.163', 8083
            sock = socket.create_connection((host, port), timeout=5)
            sock.close()
            print("网络连接成功!")
            
            # 测试API访问权限
            print("验证API访问权限...")
            test_url = GITLAB_URL + "/api/v4/projects?per_page=1"
            req = urllib2.Request(test_url)
            for key, value in HEADERS.items():
                req.add_header(key, value)
                
            response = urllib2.urlopen(req, timeout=TIMEOUT)
            if response.getcode() == 200:
                print("API访问验证成功!")
                return True
            else:
                print("API访问失败,状态码: %d" % response.getcode())
                return False
                
        except (socket.timeout, socket.error) as e:
            print("网络连接失败: %s" % str(e))
            print("请检查: ")
            print("1. 服务器 %s 是否在线" % host)
            print("2. 端口 %s 是否开放" % port)
            print("3. 本地防火墙设置")
        except urllib2.HTTPError as e:
            print("API访问错误: %d %s" % (e.code, e.reason))
            if e.code == 401:
                print("认证失败,请检查访问令牌是否有效")
            elif e.code == 403:
                print("权限不足,请检查令牌权限")
        except Exception as e:
            print("未知错误: %s" % str(e))
        return False
    
    def make_request(url, params=None):
        """发起带重试机制和分页处理的请求"""
        all_items = []
        page = 1
        retry_count = 0
        
        while True:
            try:
                # 构建请求参数
                params = params or {}
                params['page'] = page
                params['per_page'] = 100
                
                query = '&'.join(["%s=%s" % (k, v) for k, v in params.items()])
                full_url = "%s?%s" % (url, query)
                
                # 创建请求对象
                req = urllib2.Request(full_url)
                for key, value in HEADERS.items():
                    req.add_header(key, value)
                    
                # 发送请求(带超时设置)
                response = urllib2.urlopen(req, timeout=TIMEOUT)
                data = response.read()
                items = json.loads(data)
                
                if not items:
                    break
                    
                all_items.extend(items)
                
                # 检查是否有更多页面
                link_header = response.info().getheader('Link')
                if not link_header or 'rel="next"' not in link_header:
                    break
                    
                page += 1
                retry_count = 0  # 成功则重置重试计数
                
            except urllib2.URLError as e:
                if isinstance(e.reason, socket.timeout):
                    print("请求超时: %s" % full_url)
                else:
                    print("URL错误: %s" % str(e))
                    
                retry_count += 1
                if retry_count > MAX_RETRIES:
                    print("达到最大重试次数,放弃请求")
                    break
                    
                print("等待 %d 秒后重试..." % retry_count)
                time.sleep(retry_count * 2)  # 指数退避
                
            except Exception as e:
                print("请求出错: %s" % str(e))
                retry_count += 1
                if retry_count > MAX_RETRIES:
                    print("达到最大重试次数,放弃请求")
                    break
                time.sleep(retry_count * 2)
                
        return all_items
    
    # 创建输出目录
    OUTPUT_DIR = "GitLab_Branch_Reports"
    if not os.path.exists(OUTPUT_DIR):
        os.makedirs(OUTPUT_DIR)
    
    # 先测试网络连接
    if not test_connection():
        print("无法连接到 GitLab 服务器,请检查网络连接和API权限")
        sys.exit(1)
    
    # 创建CSV文件
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    csv_filename = os.path.join(OUTPUT_DIR, 'gitlab_branches_%s.csv' % timestamp)
    
    # 修复Unicode问题:使用UnicodeWriter类
    class UnicodeWriter:
        """
        CSV writer that supports Unicode in Python 2.7
        """
        def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
            self.queue = []
            self.writer = csv.writer(f, dialect=dialect, **kwds)
            self.encoding = encoding
            
        def writerow(self, row):
            # 确保所有元素都是Unicode
            unicode_row = []
            for item in row:
                if isinstance(item, (str, unicode)):
                    if not isinstance(item, unicode):
                        item = unicode(item, self.encoding)
                else:
                    item = unicode(item)
                unicode_row.append(item)
            self.queue.append(unicode_row)
            
        def writerows(self, rows):
            for row in rows:
                self.writerow(row)
                
        def write_to_file(self):
            # 写入BOM头,使Excel正确识别UTF-8编码
            self.writer.writerow([])  # 先写一个空行确保位置正确
            for row in self.queue:
                # 将Unicode编码为UTF-8字节串
                encoded_row = [col.encode(self.encoding) for col in row]
                self.writer.writerow(encoded_row)
    
    # 打开CSV文件准备写入
    with open(csv_filename, 'wb') as csvfile:
        # 创建UnicodeWriter实例
        writer = UnicodeWriter(csvfile)
        
        # 写入CSV表头(使用Unicode字符串)
        headers = [u'项目ID', u'项目名称', u'分支数量', u'分支列表']
        writer.writerow(headers)
        
        # 获取所有项目
        print("\n正在获取所有项目列表...")
        projects_url = GITLAB_URL + '/api/v4/projects'
        all_projects = make_request(projects_url, {'simple': True})
    
        if not all_projects:
            print("无法获取项目列表,请检查错误信息")
            sys.exit(1)
    
        print("\n共获取 %d 个项目\n%s" % (len(all_projects), '='*50))
    
        # 遍历所有项目获取分支
        for idx, project in enumerate(all_projects, 1):
            project_id = project['id']
            
            # 安全处理项目名称
            try:
                # 优先使用带命名空间的项目名
                project_name = project.get('name_with_namespace', project.get('name', u'未知项目'))
            except Exception as e:
                project_name = u"项目名获取失败: %s" % unicode(e)
            
            # 打印项目信息
            try:
                print("\n[%d/%d] 处理项目: %s" % (idx, len(all_projects), project_name.encode('utf-8')))
            except:
                print("\n[%d/%d] 处理项目: [Unicode项目名]" % (idx, len(all_projects)))
            
            # 获取项目所有分支
            branches_url = GITLAB_URL + '/api/v4/projects/%d/repository/branches' % project_id
            all_branches = make_request(branches_url)
            
            branch_count = len(all_branches) if all_branches else 0
            
            # 处理分支信息
            branch_names = []
            if all_branches:
                print("  找到 %d 个分支:" % branch_count)
                
                # 收集分支名称
                for branch in all_branches:
                    try:
                        branch_name = branch.get('name', u'未知分支')
                        branch_names.append(branch_name)
                        
                        # 只打印前5个分支
                        if len(branch_names) <= 5:
                            try:
                                print("    - %s" % branch_name.encode('utf-8'))
                            except:
                                print("    - [Unicode分支名]")
                    except Exception as e:
                        error_msg = u"分支名获取失败: %s" % unicode(e)
                        branch_names.append(error_msg)
                        print("    - [分支名错误]")
                
                if branch_count > 5:
                    print("    ...及其他 %d 个分支" % (branch_count-5))
            else:
                print("  该项目没有分支或获取失败")
            
            # 准备CSV行数据
            branch_list_str = u", ".join(branch_names)
            csv_row = [
                unicode(project_id),
                project_name,
                unicode(branch_count),
                branch_list_str
            ]
            writer.writerow(csv_row)
            
            # 避免请求过快
            time.sleep(DELAY_BETWEEN_REQUESTS)
        
        # 将所有数据写入文件
        writer.write_to_file()
    
    print("\n所有项目处理完成!结果已保存到: %s" % csv_filename)
    
    # 添加完成提示
    print("\n操作说明:")
    print("1. CSV文件路径: %s" % os.path.abspath(csv_filename))

然后再通过Excel的操作,获取到分支信息

需要注意的是:ACCESS_TOKEN = 'glpat-xcyhWihzE7Z3SxQVicuY'的有效期会变,需要重新去gitlab上生成。

Excel单元和合并,2列内容合并到一起,2列内容都保留
公式:=A2 & " " & B2

相关推荐
vpk1121 小时前
Docker Compose 部署 GitLab
docker·容器·gitlab
Irene199111 小时前
什么是 DevOps
gitlab·devops
蓝天星空1 天前
GitLab上传项目到新的分支
gitlab
1candobetter4 天前
GitLab 项目创建与分支管理全流程
gitlab
林鸿群5 天前
Ubuntu 26.04 本地安装 GitLab CE 完整教程(非 Docker 方式)
linux·ubuntu·gitlab·私有部署·代码托管·ubuntu 26.04·omnibus
ascarl20106 天前
IDEA 一直弹 GitLab 登录,VS Code 却能正常 `git push`?问题排查记录
git·gitlab·intellij-idea
企鹅郁金香8 天前
Gitlab和Confluence和Svn的备份
svn·gitlab·confluence·gitlab备份·svn备份·confluence备份
barbyQAQ8 天前
GitLab CI/CD 基本用法指南
java·ci/cd·gitlab
云中飞鸿9 天前
git、svn;TortoiseGit、TortoiseSVN;gitlab、github、bitbucket、bamboo有什么关系?
git·svn·gitlab
007张三丰11 天前
掌握核心!Git最常用的15个命令行:从入门到实战详解
git·gitlab·github·git命令行·常用命令行