获取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

相关推荐
极小狐2 天前
GitLab 18.2 发布几十项与 DevSecOps 有关的功能,可升级体验【二】
ci/cd·gitlab·devsecops·devops·极狐gitlab
不念霉运4 天前
2025 Gitee vs. GitLab:全面对比与选择指南
gitee·gitlab
水瓶_bxt4 天前
创建 GitLab Runner 使用CICD自动化部署容器
eureka·自动化·gitlab
黑心的奥利奥6 天前
Docker配置Gitlab-runner实现自动化容器化部署前端项目
docker·自动化·gitlab
wuzuyu3656 天前
在腾讯云上安装gitlab
云计算·gitlab·腾讯云
xiaodaiwang6 天前
OpenEuler 22.03 系统上安装配置gitlab runner
gitlab
TimberWill7 天前
gitlab私服搭建
gitlab
中东大鹅7 天前
访问 gitlab 跳转 0.0.0.0
gitlab
guygg887 天前
配置本地git到gitlab并推送
git·gitlab
大A崛起8 天前
Gitlab-CI实现组件自动推送
ci/cd·gitlab·github