Python: Git Log自动生成Release Notes,并调用Outlook发送至邮件

2023-05-16

Python: Git Log自动生成Release Notes,并调用Outlook发送至邮件

  • 主要功能
  • 先上图
    • 生成ReleaseNotes 邮件:
    • 生成ReleaseNotes Text:
  • 关键代码:
    • Git Log筛选
    • getCommitDate_byFwVer 获取版本号对应的log hash
    • getFilterLog_byHash
    • 输出ReleaseNotes到Text
    • 输出ReleaseNotes到Email
    • gui_Display() 显示
    • 版本号格式检查(正则)
  • 博主热门文章推荐:

主要功能

主要功能是 :在两个软件版本号之间,对Git Log进行过滤,筛选出所需要的Log(比如ReleaseNotes中需要的已解决Issue、实现的Feature等),将相关内容生成Text版本的ReleaseNotes文件,并自动发送至Email (Outlook方式)

其中UI是通过Tkinter 做版本号输入框和Button进行交互

先上图

在这里插入图片描述

生成ReleaseNotes 邮件:

在这里插入图片描述

生成ReleaseNotes Text:

分别有版本号、Issue/Feature、Generated Info等相关内容:
在这里插入图片描述

关键代码:

Git Log筛选

直接使用的Git Log命令+ Grep 获取相关命名规则的log:
(Git Log命令使用参考: https://git-scm.com/docs/git-log )

首先需要优化下Git log显示的内容和格式

对log进行格式化显示,只提取显示需要的内容,

例如 我只想显示Commit Hash/时间/作者信息,并且每条都显示为一行,则只需下面命令,就会指定显示format,包括显示的日期格式,Log内容等:

git log --no-merges --pretty=oneline --format="%H, %ad, %s" --date=format:"%Y-%m-%d %H:%M"

在这里插入图片描述

其中pretty format选项常用的有:

  • %s: commit log
  • %H: commit的完整哈希值
  • %h: commit的简化哈希值(前9Byte)
  • %an: author Name, 作者名字
  • %ad: Date, 既作者修改的日期

比如上面命令的%H 改为%h,则会显示简化hash:

在这里插入图片描述

同时可以在上面log里 ,再使用 Grep 按关键字过滤出任意需要的log,实现筛选

getCommitDate_byFwVer 获取版本号对应的log hash

基于上面的log筛选, 通过getCommitDate_byFwVer(fwVersion) 根据输入的版本号,获取log中出版本号对应的 hash、date

因为前面排列已经是固定按hash、date,所以这里直接截取字符串位置,就可以得到commitHash 和commitDate

def getCommitDate_byFwVer(fwVersion):
    cmd = "git log --no-merges --pretty=oneline --format=\"%H, %ad, %s\" --date=format:\"%Y-%m-%d %H:%M\" | grep \"Version: " + fwVersion + "\""
    ret = executeGitCmd(cmd)
    print(ret)
    commitHash = ret[0:40]
    commitDate = ret[42:58]

    return commitHash, commitDate

如下面示例,即可过滤出版本号所对应的Log:
在这里插入图片描述

getFilterLog_byHash

getFilterLog_byHash() 通过上一步获取的版本号对应的LogHash,筛选出两个版本号之间所需要的 Log内容以及提交信息

(其中 %an 是提交作者,%ad是提交日期)
例如下面示例:

def getFilterLog_byHash(Hash_Start, Hash_End, KEYWORD):
    GREP_STR = " | grep -i -E \"" + KEYWORD + "\""
    cmd = "git log --no-merges --pretty=oneline --format=\"\t* %s - (by %an, %ad)\" --date=short " + Hash_Start + "..." + Hash_End + GREP_STR
    ret = executeGitCmd(cmd)

    return ret

输出ReleaseNotes到Text

根据以上的Log,将获取到的log、Hash、Date等,输出到Text文件里,这一步比较常规,不多介绍了

 print(">>>Writing to "+ FILE_RLSNOTES_NAME)

    with open(FILE_RLSNOTES_PATH, 'w+') as file:
        file.write('New Release for Howard CSDN Blog Demo as below: \n\n')
        file.write(f'- Software Version: {SW_VER_END}\n')
        file.write(f'- Application Version: {VER_APPLICATION}\n')
        file.write(f'- Bootloader Version: {VER_BOOTLOADER}\n\n')

        file.write('Release Notes:\n')
        file.write('  1.Resolved Issues:\n')
        file.write(commits_Defect)
        file.write('\n')
        file.write('  2.Added Feature/User Story:\n')
        file.write(commits_Story)

        file.write('\n\nGenerated Info:\n')
        file.write(f'--Hash from: {Hash_Start} to: {Hash_End} \n')
        file.write(f'--Date from: {Date_Start} to: {Date_End} \n')
        file.write(f'--Version from: {SW_VER_START} to: {SW_VER_END} \n')
        file.write(f'--Generate Date: {str(datetime.date.today())} \n\n')

        file.write('//Auto Generated by Release Notes Tools from HowardXue.\n')

输出ReleaseNotes到Email

在ReleaseNotes文件生成后,开始自动生成并发送Email:
通过读取Text文件,使用win32.Dispatch(‘outlook.application’) 调用Outlook,然后填充Email的内容:

mail相关调用的API:

  • mail.To 填写发送方
  • mail.Subject填写邮件主题
  • mail.HTMLBody 填充HTML格式 的ReleaseNotes内容,如相关版本号、标题、内容详情等
  • mail.Attachments.Add() 添加附件text
  • mail.display() 显示待发送的邮件
  • mail.send() 发送邮件

其中显示内容通过 body_Data = '<pre>'+ rlsNotesContent +'</pre>',就可以在Html格式中Body显示前面生成的Txt文件内容

在这里插入图片描述

def autoEmailOutlook():
    global FILE_RLSNOTES_PATH
    with open(FILE_RLSNOTES_PATH) as record:
        rlsNotesContent = record.read()

    print(">>>Generating Email content.... ")

    msgStyle = """ <style>
    pre {
	  font:12pt Times New Roman;
      width: 900px;
      padding: .5rem;
      border: 2px solid #d0e579;
      margin: 1rem auto;
      white-space: pre-wrap;
      word-wrap: break-word;
	  background-color:#f2e7ca;
    }
  </style>"""

    outlook = win32.Dispatch('outlook.application')
    mail = outlook.CreateItem(0)
    mail.To = MAIL_SEND_TO
    global SW_VER_END
    mail.Subject = MAIL_SUBJECT + SW_VER_END

    titleTag = '<h2>New Software Release of : ' + SW_VER_END + '</h2> '
    wikiUrlTag = '<h4><a href=' + BLOG_PAGE_PATH + '>Blog Link: https://blog.csdn.net/HowieXue </a></h4>'
    svnUrlTag = '<h4><a href=' + DOWNLOAD_PAGE_PATH + '>Download: Link of Package </a></h4>'

    header_Data = titleTag + wikiUrlTag + '\n' + svnUrlTag + '\n'
    body_Data = '<pre>'+ rlsNotesContent +'</pre>'

    mail.HTMLBody = msgStyle + header_Data + body_Data
    print(mail.HTMLBody)

    # To attach a file to the email (optional):
    attachment = FILE_RLSNOTES_PATH
    mail.Attachments.Add(attachment)

    mail.display()

gui_Display() 显示

和之前的blog一样,也是使用Tkinter lib增加一些显示Button和文本输入框,方便输入版本号点击Button 交互使用:
然后因为执行需要些时间,所以加了个滑动条显示进度。。。
在这里插入图片描述


def gui_Display():
    global root
    root = Tk()
    root.geometry('600x300')
    root.title('Auto Release Notes Generator v1.0 for Blog Usage         (contact: Howard Xue)')
    root.config(bg='#f0ffff')

    intro_FwVersion = Label(root, text='Generate SW Release Notes between version:  Start -> Target', anchor="w", font=("Calibri 13"), \
                            bg='#f0ffff', \
                            fg='blue', \
                            width=30, \
                            height=5)
    intro_FwVersion.place(relx=0.1, rely=0.13, relwidth=0.8, relheight=0.1)

    # Entry
    global Et_FwVersion
    Et_FwVersion = Entry(root, bd=2, bg="white", relief=GROOVE, font=("Calibri 13"))

    Et_FwVersion.place(relx=0.47, rely=0.33, relwidth=0.21, relheight=0.1)
    Et_FwVersion.bind('<Return>', OnSoftwareVersionModified)
    # Et_FwVersion.bind('<Leave>', OnSoftwareVersionModified)
    # Et_FwVersion.bind('<FocusOut>', OnSoftwareVersionModified)
    Et_FwVersion.insert(0,SW_VER_END)

    intro_FwVersion = Label(root, text='Target Software Version:', anchor="w", font=("Calibri 13"),\
                            bg='#f0ffff', \
                            fg='black', \
                            width=30, \
                            height=5)
    intro_FwVersion.place(relx=0.14, rely=0.33, relwidth=0.32, relheight=0.1)

    # Entry
    global Et_FwVersion_Start
    Et_FwVersion_Start = Entry(root, bd=2, bg="white", relief=GROOVE, font=("Calibri 13"))

    Et_FwVersion_Start.place(relx=0.47, rely=0.53, relwidth=0.21, relheight=0.1)
    Et_FwVersion_Start.bind('<Return>', OnStartSoftwareVersionModified)
    # Et_FwVersion_Start.bind('<Leave>', OnStartSoftwareVersionModified)
    # Et_FwVersion.bind('<FocusOut>', OnSoftwareVersionModified)
    Et_FwVersion_Start.insert(0, SW_VER_START)

    intro_FwVersion_Start = Label(root, text='Start Software Version:', anchor="w", font=("Calibri 13"), \
                            bg='#f0ffff', \
                            fg='black', \
                            width=30, \
                            height=5)
    intro_FwVersion_Start.place(relx=0.14, rely=0.53, relwidth=0.32, relheight=0.1)


    btn_Generate = Button(root, text="Generate", command=GenerateBtn, font=("Calibri 13") ,\
                          fg='black', \
                          width=20, \
                          height=5)

    btn_Generate.place(relx=0.35, rely=0.71, relwidth=0.2, relheight=0.15)

    global p1
    p1 = ttk.Progressbar(root, length=120, mode="determinate", maximum=100, orient=HORIZONTAL)
    p1.grid(row=1, column=1)
    p1.place(relx=0.35, rely=0.89)


    root.mainloop()

版本号格式检查(正则)

因为版本号有格式要求,所以增加一个版本号检查,避免误操作:输入版本号后,如果不满足 0.1.2.3 这种数字格式,就会报错:
在这里插入图片描述

实现简单用re.match():

def OnStartSoftwareVersionModified(*args):
    global SW_VER_START, Et_FwVersion
    Version_Input = Et_FwVersion_Start.get()
    if Version_Input == "":
        return False
    # pattern = r'[0-9][0-9].[0-9][0-9].[0-9][0-9].[0-9][0-9]\Z'
    pattern = r'\d+.\d+.\d+.\d+\Z'
    result = re.match(pattern, Version_Input)
    # print(result)

    if result == None:
        tkinter.messagebox.showerror('Error: Start Software Version', 'Please Input Correct Version, eg: 0.1.2.3')
        return False
    else:
        SW_VER_START = Version_Input
        print("Last FV Start Input:" + SW_VER_START)
        return True

博主热门文章推荐:

一篇读懂系列:

  • 一篇读懂无线充电技术(附方案选型及原理分析)
  • 一篇读懂:Android/iOS手机如何通过音频接口(耳机孔)与外设通信
  • 一篇读懂:Android手机如何通过USB接口与外设通信(附原理分析及方案选型)

LoRa Mesh系列:

  • LoRa学习:LoRa关键参数(扩频因子,编码率,带宽)的设定及解释
  • LoRa学习:信道占用检测原理(CAD)
  • LoRa/FSK 无线频谱波形分析(频谱分析仪测试LoRa/FSK带宽、功率、频率误差等)

网络安全系列:

  • ATECC508A芯片开发笔记(一):初识加密芯片
  • SHA/HMAC/AES-CBC/CTR 算法执行效率及RAM消耗 测试结果
  • 常见加密/签名/哈希算法性能比较 (多平台 AES/DES, DH, ECDSA, RSA等)
  • AES加解密效率测试(纯软件AES128/256)–以嵌入式Cortex-M0与M3 平台为例

嵌入式开发系列:

  • 嵌入式学习中较好的练手项目和课题整理(附代码资料、学习视频和嵌入式学习规划)
  • IAR调试使用技巧汇总:数据断点、CallStack、设置堆栈、查看栈使用和栈深度、Memory、Set Next Statement等
  • Linux内核编译配置(Menuconfig)、制作文件系统 详细步骤
  • Android底层调用C代码(JNI实现)
  • 树莓派到手第一步:上电启动、安装中文字体、虚拟键盘、开启SSH等
  • Android/Linux设备有线&无线 双网共存(同时上内、外网)

AI / 机器学习系列:

  • AI: 机器学习必须懂的几个术语:Lable、Feature、Model…
  • AI:卷积神经网络CNN 解决过拟合的方法 (Overcome Overfitting)
  • AI: 什么是机器学习的数据清洗(Data Cleaning)
  • AI: 机器学习的模型是如何训练的?(在试错中学习)
  • 数据可视化:TensorboardX安装及使用(安装测试+实例演示)

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python: Git Log自动生成Release Notes,并调用Outlook发送至邮件 的相关文章

  • 已成功与服务器建立连接,但是在登录过程中发生错误。 (provider: TCP 提供程序, error: 0 - 远程主机强迫关闭了一个现有的连接。)

    数据库SQL Server 2008 R2 xff0c 网站突然登不了了 重启iis xff0c 重启数据库服务 xff0c 重启服务器都不行 解决方法 xff1a 打开SQL Server配置管理器 xff0c 找到MSSQLSERVER
  • Math.floor(Math.random()*3+1)

    Math random 获取0 1随机数 Math floor method rounds a number DOWNWARDS to the nearest integer and returns the result 小于等于 x xf
  • 定时打开或关闭服务器上的软件

    部署在服务器上的软件 xff0c 会莫名其妙的停止运行 xff0c 还必须得手动关闭重启 xff0c 太麻烦啦 xff01 在大神的建议下 xff0c 做一个让软件自动关闭进程 xff0c 然后重启的操作 废话少说 xff0c 上车 第一步
  • FFmpeg

    FFmpeg是一套可以用来记录 转换数字音频 视频 xff0c 并能将其转化为流的开源计算机程序 采用LGPL或GPL许可证 它提供了录制 转换以及流化音视频的完整解决方案 它包含了非常先进的音频 视频编解码库libavcodec xff0
  • 不懂PO 设计模式?这篇实战文带你 PO

    为UI页面写测试用例时 xff08 比如web页面 xff0c 移动端页面 xff09 xff0c 测试用例会存在大量元素和操作细节 当UI变化时 xff0c 测试用例也要跟着变化 xff0c PageObject 很好的解决了这个问题 x
  • archlinux 中文本地化配置

    参考 xff1a http www wiki org 本地化配置 xff0c 其实就是设置locale 一 显示中文 要显示中文 xff0c 需要生成中文语言包和安装中文字体 1 生成中文语言包 archlinux使用locale gen脚
  • 【Ubuntu】安装Go语言

    sudo apt install golang go version
  • linux系统中使用X11 获取系统窗体信息

    在X Window System中 xff0c 每个窗口都有一个唯一的标识符 xff0c 称为窗口ID 要查找特定窗口的ID号 xff0c 可以使用Xlib库中的XQueryTree函数来获取窗口树结构 xff0c 并遍历整个树结构以查找目
  • 三维重建:多点透视cvSolvePNP的替代函数(Code)

    xfeff xfeff 在调试JNI程序时 xff0c 所有的Shell都已经加载完成 xff0c 而唯一真正核心的cv SolvePnP却不能在JNI里面获得通行证 xff0c 经过反复测试都不能运行 xff0c 因此只能忍痛舍弃 xff
  • 利用Pycharm工具将Python+Qt项目打包成exe应用程序

    博客小白第一次发博客 xff0c 已参加工作 xff0c 仅用于记录一下自己空余时间学习Python的进程 xff0c 学习过程中遇到问题也借鉴了很多博客的解决办法 xff0c 因此也想记录下自己的遇到的问题 xff0c 希望对跟我一样刚起
  • BOSS 业务运营支撑系统

    今天又简单的介绍几个概念 xff0c 我觉得要深入了解某个技术 xff0c 首先要把概念搞清楚 xff0c 这样在宏观理解上将更加深入 本人工作所属电信行业 xff0c 所以下面所介绍的几个概念都是基于电信行业的 BSS Business
  • JAVA版本:判断101-200之间有多少个素数,并输出所有素数。

    题目 xff1a 判断101 200之间有多少个素数 xff0c 并输出所有素数 程序分析 xff1a 判断素数的方法 xff1a 用一个数分别去除2到这个数 xff0c 如果至少有一个数能被整除 xff0c 则表明此数不是素数 xff0c
  • arm64架构ubuntu18.04国内镜像源

    jetson xavier nx下换国内源 xff0c 步骤如下 xff1a span class token shebang important bin bash span span class token function cp spa
  • 安装和配置OpenStack客户端(Jesse翻译)

    xfeff xfeff 安装和配置 OpenStack 客户端 xff08 Jesse 翻译 xff09 原文来自 icehouse的OpenStack文档 回忆 xff1a 在前面部分 xff0c 你已经使用了 keystone 客户端
  • 联通家庭宽带光猫DDNS设置

    1 目前家里宽带光猫ppoe拨号获取的IP全部都是非公网IP 打96169宽带专家转人工客服申请更换公网IP 一天内会有专人联系 更换成公网IP后 重启光猫 在公司或者其他地方ping下家里光猫获取到的公网IP看下是否能ping通 2 申请
  • Matlab如何抓取excell表格里的指定数据

    每次从示波器上采集的数据总是会带有示波器的相关信息 xff0c 没法直接load到matlab里 xff0c 每次手动删除让人感到疲惫 xff0c 特别是数据量达到100 43 的时候 瞬间emmm 示波器采到的数据如下图 xff1a 于是
  • nginx更改进程名称 学习笔记

    如何更改进程名称 在进入正题之前 xff0c 我们需要了解一下以下参数的作用 xff1a span class token keyword int span span class token function main span span
  • Apache 2部署SSL证书

    在Ubuntu系统Apache 2部署SSL证书 本文介绍了如何在Ubuntu系统以及Apache 2中安装阿里云SSL证书 前提条件 已从SSL证书控制台下载Apache服务器证书 已安装Open SSL 环境准备 操作系统 xff1a
  • NVDIA Jetson TX2软件介绍

    介绍 JETSON TX2 模块 它是一台基于 NVIDIA Pascal 架构的 AI 单模块超级计算机 它性能强大 xff0c 但外形小巧 xff0c 节能高效 xff0c 非常适合机器人 无人机 智能摄像机和便携医疗设备等智能终端设备
  • 12.6V/8.4V锂离子或锂聚合物电池充电器

    AL1261是一款专门为高精度的线性锂电池充电器而设计的电路 xff0c 非常适合那些低成本 便携式的充电器使用 它集高精度预充电 恒定电流充电 恒定电压充电 电池状态检测 充电结束低泄漏 充电状态指示等性能于一身 xff0c 可以广泛地使

随机推荐