栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

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

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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

主要功能先上图

生成ReleaseNotes 邮件:生成ReleaseNotes Text: 关键代码:

Git Log筛选getCommitDate_byFwVer 获取版本号对应的log hashgetFilterLog_byHash输出ReleaseNotes到Text输出ReleaseNotes到Emailgui_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 )

例如:

对log进行格式化显示,比如下面命令,就会指定显示一行,显示的日期格式,Log内容等:

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

同时可以在上面log里 ,再使用 Grep 过滤出需要的log,进行筛选

getCommitDate_byFwVer 获取版本号对应的log hash

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

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: nn')
        file.write(f'- Software Version: {SW_VER_END}n')
        file.write(f'- Application Version: {VER_APPLICATION}n')
        file.write(f'- Bootloader Version: {VER_BOOTLOADER}nn')

        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('nnGenerated 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())} nn')

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

输出ReleaseNotes到Email

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

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

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

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

    msgStyle = """ 
    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;
    }
  """

    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 = 'New Software Release of : ' + SW_VER_END + ' '
    wikiUrlTag = ' + BLOG_PAGE_PATH + '>Blog link: https://blog.csdn.net/HowieXue '
    svnUrlTag = ' + DOWNLOAD_PAGE_PATH + '>Download: link of Package '

    header_Data = titleTag + wikiUrlTag + 'n' + svnUrlTag + 'n'
    body_Data = '
'+ rlsNotesContent +'
' 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('', OnSoftwareVersionModified)
    # Et_FwVersion.bind('', OnSoftwareVersionModified)
    # Et_FwVersion.bind('', 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('', OnStartSoftwareVersionModified)
    # Et_FwVersion_Start.bind('', OnStartSoftwareVersionModified)
    # Et_FwVersion.bind('', 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安装及使用(安装测试+实例演示)


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/768324.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号