十四、Jenkins打包完成后,执行python脚本,将发行包打包压缩上传禅道提交版本

news2024/11/25 18:59:50

十四、Jenkins打包完成后,执行脚本,将版本发行包压缩上传禅道提交禅道版本

十三、禅道登录/提交版本/编辑版本接口 ,书接上回,在禅道中注册一个Jenkins账号,利用禅道的接口,提交到禅道中,具体代码如下

基本流程:
Jenkins打包完成==>执行python脚本==>包括打版本压缩包==>打源码压缩包==>新建或编辑版本==>上传发行包和源码包==>禅道版本新增完成

1. 代码上传Jenkins服务器 zentao_add_edit_version.py

# -*- coding: utf-8 -*-
"""
-------------------------------------------------------------------------------
File    : zentao_add_edit_version.py
Time    : 2023/4/11 12:05
author  : mojin
Email   : 397135766@qq.com
-------------------------------------------------------------------------------
"""


import requests
import datetime
import os

import sys
import time
import urllib.request
import shutil
import zipfile
import os,datetime
import logging
# 设置日志输出的格式
logging.basicConfig(format='%(asctime)s %(levelname)s-%(filename)s-[%(funcName)s] line %(lineno)d - %(message)s', level=logging.INFO)

class VersionManagement():
  '''
  打包完成后在禅道上传发行包,补充版本描述创建下个版本 用于fix bug

  '''
  def __init__(self):
    self.build_info=eval(sys.argv[1])

    # build_info = {
    #   'building_number': '%BUILD_NUMBER%',
    #   'execution': '105',
    #   'product': '35',
    #   'project_zt':'104',
    #   'build_name': '*v1.0.0.6.service.***',
    #   'build_name_keywords': '*,service',
    #   'scmPath': '%GIT_URL%',
    #   'filePath': '%GIT_URL%',
    #   'desc_doc': '%SCM_CHANGELOG%',
    #   'files_path': '%WORKSPACE%\\service-admin\\target\\service-admin.jar,%WORKSPACE%',
    #   'branch': 'dev',
    #   'project_name': '%PROJECT_NAME%',
    # }
    #
    build_info2 = {
      'building_number': '%BUILD_NUMBER%',#构建编号
      'execution': '105',#禅道迭代 id
      'product': '35',  #禅道产品id
      'project_zt': '104',  #产品 禅道项目id
      'build_name': '*v1.0.0.6.web.***',   #创建下个新版本的名称
      'build_name_keywords': '*,web',   #标识字符,用于找到在版本名称找到换个字符标书,编辑补充发行包和描述,下载地址等等信息
      'scmPath': '%GIT_URL%',  #代码地址
      'filePath': '%GIT_URL%',  #下载地址
      'desc_doc': '%SCM_CHANGELOG%',  # 版本描述
      'files_path': '%WORKSPACE%\\dist,%WORKSPACE%', #打包要删除的目录node_modules
      'branch': 'dev',  #分支
      'project_name': '%PROJECT_NAME%',  #项目名称
    }

    # self.build_info={
    #   'building_number':'265',
    #   'execution':'3',
    #   'product': '2',
    #   'build_name': '*v1.0.1.h5.***',
    #   'build_name_keywords': '*,h5',
    #   'scmPath': 'http://192.16***',
    #   'filePath': 'http://192***',
    #   'desc_doc': '*****变更记录************************************************************************************',
    #   'files_path': 'E:/java_xm/service-admin.jar,E:\\java_xm\\services',
    #   'branch':'dev',
    #   'project_name':'services',
    #   'version_txt_path':'services',
    # }
    # 'source_code_url':'http://192.168.1.******************chive/dev.zip',
    # 'source_code_zip':'service-services.zip'
    # self.dir_path = r'E:\java_xm\service\mobile\risk-pro'
    # self.zip_filename = 'service-mobile'

    self.building_number=self.build_info['building_number'] #构建编号
    self.execution=self.build_info['execution']  #禅道迭代 id
    self.product = self.build_info['product']  #禅道产品id
    self.project_zt=self.build_info['project_zt']  #产品 禅道项目id
    self.build_name=self.build_info['build_name']   #创建下个新版本的名称
    self.build_name_keywords = self.build_info['build_name_keywords']   #标识字符,用于找到在版本名称找到换个字符标书,编辑补充发行包和描述,下载地址等等信息
    self.scmPath=self.build_info['scmPath']   #代码地址
    self.filePath=self.build_info['filePath']  #下载地址
    self.desc_doc=self.build_info['desc_doc'] # 版本描述
    self.files_path=self.build_info['files_path'] #r'E:/java_xm/service-admin.jar,E:/java_xm/service-admin.jar' 附件路径
    self.branch=self.build_info['branch']  #代码分支
    self.project_name = self.build_info['project_name']  # jenkins项目名称
    self.exclude_dir=self.build_info.get('exclude_dir','node_modules') #打包要删除的目录node_modules
    self.version_file=self.build_info.get('version_file','')
    # self.source_code_zip=self.build_info['source_code_zip']  #源码包名
    # self.source_code_url =self.build_info['source_code_url'] #源码链接





    self.url ='http://192.168.1.52:81'
    self.account="jenkins"
    self.password='jenkins135766'
    # self.building_number='265' #构建编号
    # self.execution='3'  #迭代
    # self.product = '2'  #产品
    # self.build_name='*v1.0.1.h5.***'  #创建下个新版本的名称
    # self.build_name_keywords = '*,h5'  #标识字符,用于找到在版本名称找到换个字符标书,编辑补充发行包和描述,下载地址等等信息
    # self.scmPath='代码地址'  #代码地址
    # self.filePath='下载地址' #下载地址
    # self.desc_doc="[APP\n]"
    # self.files_path=r'E:/java_xm/service-admin.jar,E:/java_xm/service-admin.jar'

    self.file_path_list=[]
    self.Package_Name=''

    self.source_code_zip=''
    self.current_time = datetime.datetime.now().strftime("%Y-%m-%d")
    self.now_time=datetime.datetime.now().strftime("%Y%m%d%H%M%S")
    self.token=self.login()     #'fa7f18713d8921d98d84cffd567cb6a9'###self.login()
    self.headers = {
      'Token':  self.token,
      'Cookie': f'zentaosid= {self.token}'
    }

  def zipdir(self,dir_path,):
    """
    压缩指定路径中的所有文件和子目录到一个ZIP文件中。
    :param path: 要压缩的路径
    :param ziph: ZipFile对象,用于写入压缩文件
    :param exclude_dir: 要排除的目录名,默认为None表示不排除
    """
    # 创建 ZipFile 对象,并调用自定义的 zipdir() 函数进行压缩
    # zip_filename = self.Package_Name   #      self.Package_Name = f'{build_name}-{os.path.basename(file_path)}'
    zip_filename = f"{self.Package_Name}.zip"
    with zipfile.ZipFile(zip_filename, mode='w') as ziph:
      logging.info(f"正在将目录 {dir_path} 打包成 {zip_filename}...")
      # zipdir(dir_path, z, exclude_dir)

      for root, dirs, files in os.walk(dir_path):
        if self.exclude_dir and self.exclude_dir in dirs:
          dirs.remove(self.exclude_dir)  # 排除指定的目录
        for file in files:
          file_path = os.path.join(root, file)
          ziph.write(file_path, os.path.relpath(file_path, dir_path))

      zip_filename_path=r'./%s' % zip_filename

      self.file_path_list.append(zip_filename_path)

      return zip_filename_path



  def files_converting(self, dir_path):
    '''
    判断传来的参数是目录还是文件,是目录打包成压缩包输出路径,是文件直接输出路径

    :param dir_path:
    :return:
    '''
    if os.path.isfile(dir_path):

      file_name = os.path.basename(dir_path)

      new_path = f'{self.Package_Name}'


      logging.info(f'{dir_path},是一个文件')

      dir_path = [dir_path, new_path]
    elif os.path.isdir(dir_path):
      logging.info(f'{dir_path},是一个目录')
      zip_filename = f"{self.Package_Name}.zip"
      dir_path =[ self.zipdir(dir_path),zip_filename]
    else:
      logging.info('无法判断', dir_path, '是文件还是目录')
      raise
    logging.info(f'{dir_path}')
    return dir_path

  def changes(self):
    changes = ''
    #self.desc_doc = self.desc_doc.replace('[', '').replace(']', '')
    n=1
    logging.info(f'更新内容:{self.desc_doc}')
    for i in self.desc_doc.split('\n'):

      if i != '':
        #<p><span>1.描述描述描述</span></p
        changes = changes + f'<p><span>{n}.{i}</span></p'
        #changes= changes + f'{n}.{i}\n'
      n += 1
    if changes != '':
      changes= f'<p><span>变更记录:(AFS)</span></p{changes}'

    else:
      changes = f'<p><span>变更记录:(AFS)</span></p<p><span>本次没有发生变化</span></p'
    logging.info(f'更新内容:{changes}')
    return changes

  def requests_api(self,path,payload,method,parame_type,file=None):
    url = f"{self.url}/{path}"
    if parame_type=='josn':
      parameter={'josn':payload}

    elif parame_type=='data':
      parameter={'data':payload}
    elif parame_type=='params':
      parameter={'params':payload}
    else:
      logging.error(f'输入的参数类型[{parame_type}]不符合要求!!!!')
      raise

    if file==None:
      file={}


    try:
      response = requests.request(method, url, headers=self.headers,**parameter,files=file)
      resp_dic = response.json()
      #logging.info(response.status_code)

    except Exception as e:
      resp_dic={"response":f'{e}'}
      logging.error(f'请求失败:{resp_dic}')
      raise


    return resp_dic

  def login(self): #登录
    url = f"{self.url}/zentao/api.php/v1/tokens"

    payload={
      'account':self.account,
      'password':self.password
    }
    response = requests.request("POST", url, headers={}, json=payload)
    resp_dic=response.json()
    #logging.info(resp_dic)
    if resp_dic.get('token','')=='':
      logging.error(f'登录失败!{resp_dic}')
      raise
    return resp_dic['token']

  def executions_builds_list(self,): #获取版本列表
    path = f"zentao/api.php/v1/executions/{self.execution}/builds"
    payload = {}
    response = self.requests_api( path, payload, 'GET', 'data',)
    #logging.info(f'获取版本列表:{response}')
    return response

  #版本详情
  def builds_info(self):
    path = f"zentao/api.php/v1/builds/366"
    payload={}
    response = self.requests_api(path, payload, 'GET', 'data', )
    logging.info(response)
    return response


  def add_version(self): #新增版本
    path = f"zentao/build-create-{self.execution}.json"

    payload = {
               #'isIntegrated': 'no',
               'execution': f'{self.execution}',
               'product': f'{self.product}',
               'name': self.build_name.replace('.***',f'.{int(self.building_number)+1}.***'),
               'builder': 'Jenkins',
               'date': self.current_time,
               # 'scmPath': '代码地址',
               # 'filePath': '下载地址',
               # 'desc': '<p>1.描述描述描述</p><p><span>2.描述描述描述</span></p>',
               #  'uid': '643603d229574',
               'project': self.project_zt
               }

    response = self.requests_api(path, payload, 'POST', 'data', )
    logging.info(f'新增下个版本:{response}')
    return response


  def edit_version(self,id,edit=1): #编辑版本

    if edit==1: #编辑
      path = f"zentao/build-edit-{id}.json"
    elif edit==2: #新增
      path = f"zentao/build-create-{self.execution}.json"
    else:
      logging.error(f'edit参数异常[{edit}]!!)')
      raise

    #'*v1.0.0.6.web.***'
    build_name=self.build_name.replace('.***',f'.{self.building_number}.***').replace("*","")
    try:
      with open(self.version_file, "r") as f:
        build_name = f.read()
        logging.info(f'读取新的版本号:{build_name}')
    except Exception as e:
      logging.info(f'没有读取到新本号,出现异常({e})')
      raise
      # build_name = f'{build_name}{self.now_time}'
      # logging.info(f'生成新版本号:({build_name})')



    payload = {

      #'branch[]': ' 0',
      'execution': f'{self.execution}',
      'product': f'{self.product}',
      #.replace('.***',f'.{self.building_number}.***')
      'name': build_name,
      'builder': 'Jenkins',
      'date': self.current_time,
      'scmPath': self.scmPath,
      'filePath': self.filePath,
      'desc':self.changes(),  #'1.版本描述',
      # 'uid': '6437b2ec9764a'
      'project': self.project_zt
    }
    files=[]
    files_path_list=self.files_path.split(',')

    #files_path_list.append(self.source_code_zip)
    logging.info(f'{files_path_list}')

    for file_path in files_path_list:
      self.Package_Name = f'{build_name}-{os.path.basename(file_path)}'
      file_path = self.files_converting(file_path)



      n=1
      while True:
        if n>180:
          logging.error('打压缩包超时……………………')
          raise

        try:
          logging.info(file_path)
          files.append(('files[]', (file_path[1], open(file_path[0], 'rb'))))
          break
        except Exception as e:

          logging.info(f'{file_path}')
          logging.info(f'打压缩包中……{e}')
          time.sleep(1)

      n+=1

    response = self.requests_api(path, payload, 'POST', 'data', files) #""#
    logging.info(f'新增或编辑版本:{response}')


    return response

  def main(self):
    #self.download_source()
    version_exists=True #版本是否存在的标识 默认版本不存在True,成功找到版本后 编辑成功后 修改标识为False 版本存在
    for build in self.executions_builds_list()['builds']:
      keywords_lsit=[]
      for keywords in self.build_name_keywords.split(','): #匹配版本找到后获取到版本id 进行编辑
        keywords_lsit.append(keywords in build['name'] ) #所有的版本标识 都存在 为T

      if False not in keywords_lsit:  # 列表中没有False
        logging.info(f'获取到版本id【{build["id"]}】')  #获取到了版本id
        logging.info(f'版本信息:{build}')

        self.edit_version(build["id"])    #编辑版本
        version_exists=False   #编辑版本存在的
        break
    if version_exists: #当版本不存在时 创建新版本,输入完整的数据 发行包 源码等等
      self.edit_version('',edit = 2)


    self.add_version() #创建下个版本


    for file_path in self.file_path_list: #删除之前创建的压缩包

      if os.path.exists(file_path):
        os.remove(file_path)
        logging.info(f"删除上传完成的压缩包文件[{file_path}]")
      else:
        logging.info(f'压缩包file不存在[{file_path}]')






if __name__=="__main__":
  VersionMan=VersionManagement()
  VersionMan.main()






2. 配置Jenkins服务器 执行zentao_add_edit_version.py

在这里插入图片描述
在这里插入图片描述

cd ..
set build_info="{'building_number':'%BUILD_NUMBER%','execution':'108','product':'35','project_zt':'104','build_name':'*v1.1.0.h5.***','build_name_keywords':'*,h5','scmPath':'%GIT_URL%','filePath':'%GIT_URL%','desc_doc':'%SCM_CHANGELOG%','files_path':r'%WORKSPACE%\\risk-pro\\dist,%WORKSPACE%','branch':'release','project_name':'%PROJECT_NAME%','version_file':r'%WORKSPACE%\risk-pro\public\version.txt'}"
python  D:\anaconda\jks\zentao_add_edit_version.py %build_info%

3. 版本创建/编辑完成

在这里插入图片描述

4. 提交BUG选择创建的版本

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/702627.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据仓库系列:StarRocks 入门培训教程

文章目录 1. 什么是StarRocks?1.1. 适用场景1.2. [产品特性](https://docs.starrocks.io/zh-cn/latest/introduction/Features) 2. 系统架构2.1. 系统架构2.1.1. 整体架构2.1.2. 高可用实现方式 2.2. 数据如何管理&#xff1f; 3. 表模型3.1. 明细模型3.2. 聚合模型3.3. 更新模…

冷链NO.1技能,物流人第一天就应该学会!

储藏室的温湿度是许多行业中的关键因素&#xff0c;如医疗、食品、冷链物流等。确保储藏室内的温湿度在规定的范围内是保护物品品质和价值的关键。 储藏室温湿度远程监控是一项重要的任务&#xff0c;特别适用于需要实时掌握储藏室环境条件的场景。通过远程监控&#xff0c;可以…

凸优化理论基础

目录 一&#xff0c;仿射集 1&#xff0c;仿射集(affine set) 2&#xff0c;仿射组合(affine combination) ​编辑 3&#xff0c;仿射包(affine hull) 二&#xff0c;凸集 1&#xff0c;凸集 2&#xff0c;凸组合 3&#xff0c;凸包(convex hull) 本文部分内容来自网友…

JavaEE(系列22) -- IP协议和以太网

目录 1. IP协议 1.1 协议头格式 1.2 解决IPV4地址不够用的问题 1.3 IP地址管理 1.4 路由选择 2. 以太网 (数据链路层) 1. IP协议 P协议是位于OSI模型中第三层(网络层)的协议, 在这层上工作的不止这一个协议, 但IP协议是网络层传输所使用的最主流的一种协议, 有IPv4和IPv6两…

实现旋转切换效果的轮播图。

下面视频是实现后的效果图。具体实现方法可以通过下面链接进行观看 实现旋转切换效果的轮播图。_ღ张明宇࿐的博客-CSDN博客https://blog.csdn.net/zmx781284440/article/details/131466113 旋转切换轮播图

httprunner2.0 概述及使用说明

目录 一、概述 二、系统流程 三、文件组织 1、项目文件目录结构 四、用例编写 1、用例编写 2、编写用例注意事项 五、变量或函数引用 六 环境变量引用 1、编辑.env文件 2、引用环境变量 七、参数化数据驱动 一、概述 HttpRunner是一款面向 HTTP(S) 协议的通用测试…

2023亚马逊云科技中国峰会:如何让AI前景更广阔

今天&#xff0c;2023亚马逊云科技中国峰会的第二天&#xff0c;峰会现场精彩不断绽放&#xff01; 值得关注的是&#xff0c;峰会上&#xff0c;亚马逊云科技大中华区产品总经理陈晓建在《专注创新&#xff0c;摆脱基础架构束缚》主题演讲中提出&#xff0c;云服务是支持数字创…

「UG/NX」BlockUI 树列表(回调函数)

✨博客主页何曾参静谧的博客📌文章专栏「UG/NX」BlockUI集合📚全部专栏「UG/NX」NX二次开发「UG/NX」BlockUI集合「VS」Visual Studio「QT」QT5程序设计「C/C+&#

如何创建WooCommerce会员网站

Web网站内容货币化的一种非常标准的方法是通过会员社区提供对内容的有限访问。您可以使用 WordPress 的众多付费专区插件之一轻松创建它。有些使用MemberPress或其他顶级 WordPress 会员插件&#xff0c;还有一些使用 WooCommerce。当您想到会员网站时&#xff0c;WooCommerce可…

Tomcat服务器的使用

一。Tomcat的概念 1.服务器 服务器&#xff1a;分为服务器硬件和服务器软件。在硬件服务器&#xff08;其实就是一台计算机&#xff09;上安装了服务器软件&#xff0c;才可以对外提供服务。 1.硬件&#xff1a;通常是指在互联网上具有独立IP的计算机&#xff0c;通常配置比…

u盘刷新系统

1.百度u盘制作将u盘进行刷成系统盘 点击添加系统 确认 关掉即可 到这里就制作完成了&#xff0c;u盘里也有系统了&#xff0c;下一步就是进入电脑的 bios 一般是f8 或者f2 或者esc 看你是什么电脑自己手机百度一下&#xff0c; 当进入u盘系统时候会发现一键刷机工具找不到镜像&…

【前端基础知识】iframe如何实现项目集成?如何防止被XFS?

目录 iframe介绍iframe语法如何实现集成效果如何将自己的网站实现禁止访问 iframe介绍 HTML 内联框架元素 (<iframe>) 表示嵌套的 browsing context。它能够将另一个 HTML 页面嵌入到当前页面中。 iframe语法 <iframe src"" name"" width"…

115.使用JS让移动导航工作起来

● 还记得我们之前的移动导航吗&#xff1f;需要手动添加类才能使其生效&#xff0c;现在我们用js来自动实现 const btnNavEl document.querySelector(".btn-mobile-nav"); const headerEl document.querySelector(".header"); btnNavEl.addEventListe…

【滤波】自适应滤波器

%matplotlib inline#format the book import book_format book_format.set_style()简介 到目前为止&#xff0c;我们已经考虑了跟踪与我们的过程模型相关的表现良好的对象的问题。例如&#xff0c;我们可以使用恒速滤波器来跟踪直线运动的物体。只要物体以合理的恒定速度沿直线…

文心一言vs通义千问 之前端文件夹命名

今天心血来潮想试试国内百度和腾讯的AI在解决前端难题–文件命名方面的效果。 如下&#xff1a; 综上&#xff0c;是百度会更贴近一些哈 大伙有什么命名的好工具嘛&#xff1f;

Flutter学习四:Flutter开发基础(六)调试Flutter应用

目录 0 引言 1 调试Flutter应用 1.1 日志与断点 1.1.1 debugger() 声明 1.1.2 print和debugPrint 1.1.3 调试模式、中间模式、发布模式 1.1.4 断点 1.2 调试应用程序层 1.2.1 转储Widgets树 1.2.2 转储渲染树 1.2.3 转储Layer树 1.2.4 转储语义树 1.2.5 调度&…

PyEcharts 学习总结

—— 如何用 pyecharts 绘制一切你想象得到的交互式图表&#xff1f; pyecharts 分为 v0.5.x 和 v1.0.0 两个版本&#xff0c;这篇总结针对新版本。 本文不包含基础例子的演示&#xff0c;主要记录一些细节方面的理解。示例看 gallery.pyecharts.org 一、简介 – Echarts &am…

基于Java网上手机商城设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

js获取文字的宽度

通过canvas api 获取文字宽度 const getTextWidth () > {const measureText document.createElement("canvas");const ctx measureText.getContext(2d)!return (name: string) > {const { width } ctx.measureText(name);return width 20 px} }const ge…

Java版企业工程项目管理系统源码-全面的工程项目管理+spring cloud

​ ​工程项目管理系统是指从事工程项目管理的企业&#xff08;以下简称工程项目管理企业&#xff09;受业主委托&#xff0c;按照合同约定&#xff0c;代表业主对工程项目的组织实施进行全过程或若干阶段的管理和服务。 如今建筑行业竞争激烈&#xff0c;内卷严重&#xff0c…