美文网首页
每日git commit汇总钉钉通知脚本实现

每日git commit汇总钉钉通知脚本实现

作者: elesg | 来源:发表于2019-03-18 22:35 被阅读0次

    背景

    公司一直倡导测试要对开发改动的代码进行codereview。
    小的需求一般在一个项目里面几个commit的情况下,的确所花的review成本也不高。
    但是一旦项目比较大型,涉及的代码仓库比较多,且前期开发提交频繁的情况下,一旦等到提测才进行codereview,这个堆积的工作量就太大了,看着就有一种不想review的感觉呢。
    而且这么多的commit的情况下,一次性光看commit message都觉得负担很重,谈何review?

    解决思路

    既然一次过review的量太大,我们为何不尝试每天抽时间完成当天提交的review呢?
    在提测之前提前介入review,还能及时发现问题,把bug扼杀在开发阶段~
    于是我们基于jenkins和钉钉机器人做了一个每日git commit汇总钉钉通知小工具。

    • 支持多仓库汇总
    • 支持一个仓库多分支汇总
    • 支持同时发送多个机器人消息

    具体实现

    所用到的工具

    • jenkins——用于定期执行+仓库配置
    • GitPython——一个git操作的python库
    • 钉钉机器人——发送通知

    流程

    1. 从命令行中获取到git url以及钉钉机器人token(支持以列表形式传入)
    2. 根据git url将项目有仓库克隆到本地
    3. 获取仓库中一天以内的commit,解析获取其中的commit message、committer、基于giturl拼接成的commit 详情URL。形成一个字典数组
    4. 拼接成markdown格式的文案
    5. 根据命令行中的token,给对应机器人发送钉钉通知

    效果图

    image.png

    核心代码

    以下代码python版本为2.7.10。

    git仓库操作

    def getCommitMessages( repos,day_count ):
        repos_list = repos.split(";")
        summary=[]
        # 遍历列表中所有仓库
        for repo_str in repos_list:
            # 执行前清空临时文件夹
            deleteDir(tmp_path)
            repo = json.loads(repo_str)
            project_name = repo['url'].split('/')[-1]
            project_title = project_name+'-'+repo['branch']
            repo['title'] = project_title
            work_dir = os.path.join(tmp_path,project_title)
            if 'http' not in repo['url']:
                repo['error']='仓库链接仅支持http/https的格式,请修改仓库链接。当前的仓库链接为:{}'.format(repo['url'])
                summary.append(repo)
                continue
            try:
                # 克隆到本地
                git.Repo.clone_from(repo['url'], work_dir, branch=repo['branch'], progress=None)
                repository = git.Repo(work_dir)
                results=[]
                # 获取每一个n天以内的commit并打印出时间和拼接详情链接
                today = datetime.now()
                last_commit_date = time.mktime((today - timedelta(days=day_count)).timetuple())
                commits=repository.iter_commits(rev=None,paths='', max_age=last_commit_date)
                for commit in commits:
                    result={}
                    commit_date = datetime.fromtimestamp(commit.committed_date)
                    result['date'] = str(commit_date)
                    result['committer'] = commit.author.name.encode('utf-8')
                    # 需要对markdown的标签进行转义
                    result['message']= commit.message.replace('# ','\# ') \
                        .replace('* ',"\* ") \
                        .replace('\r\n\r\n',' >>> ') \
                        .replace('\n','  ') \
                        .replace('\r','  ') \
                        .split('Conflicts:')[0] \
                        .encode('utf-8')
                    result['url']= '{}/commit/{}'.format(repo['url'], str(commit))
                    results.append(result)
                repo['commits']=results
                if results == []:
                    repo['error'] = '暂无更新'
            except Exception as e:
                repo['error']='仓库克隆失败,请检查是否仓库地址有误或是否有权限问题。仓库地址:{}'.format(repo['url'])
                print (str(e))
            summary.append(repo)
        return summary
    
    

    转换成markdown格式

    # 生成对应格式的的message
    def summaryToMarkdown( summary ):
        message=''
        for repo in summary:
            message += '#### {}:  \n'.format(repo['title'])
            message += '>  \n'
            if repo.has_key('error') :
                message += repo['error']+"\n\n"
                continue
            for commit in repo['commits']:
                message += '* 【{} **{}**】[{}]({})  \n'.format(commit['date'], commit['committer'], commit['message'], commit['url'])
            message += '\n\n'
        return message
    
    

    发送钉钉消息

    # 发送钉钉消息  
    def sent_dingding_message(token,content,
                              template="""## 最近24小时内git commit汇总情况如下:  \n {}"""):
        headers = {'content-type': 'application/json'}
        payload = {
            "msgtype": "markdown",
            "markdown": {
                "title": "每日git commit汇总",
                "text": template.format(content)
            }
        }
        s = requests.session()
        resp = s.post('https://oapi.dingtalk.com/robot/send?access_token={}'.format(token),
                      headers=headers,
                      data=json.dumps(payload))
        if resp.status_code != 200:
            resp.encoding="utf-8"
            print(resp.text)
            raise Exception("消息发送失败")
    

    如何使用

    1. 将脚本上传到一个git仓库保存。
    2. 在jenkins的宿主机安装好GitPython依赖库
    pip install gitpython
    
    1. 新建一个jenkins 自由风格的Job
      1. 在源码管理中添加脚本的仓库。
      2. 新增一个日程表,每天定时执行。
      3. 新增一个Execute Shell脚本,按照以下格式填写即可。
      # 这里修改钉钉机器人token
      export token=token1,token2
      # 按照如下格式配置需要汇总的仓库和分支,通过英文分号;隔开,同一个仓库的多个分支需要分开两条写
      export repos='{"url":"http://github.com/xx/xx","branch":"develop"};{"url":"http://github.com/xx/xx","branch":"master"}'
      python gitCommitNotice.py
      

    相关文章

      网友评论

          本文标题:每日git commit汇总钉钉通知脚本实现

          本文链接:https://www.haomeiwen.com/subject/syuimqtx.html