react项目Jest+Enzyme单元测试集成至gitlab-下篇

上一篇文章我们介绍了从零搭建至集成到gitlab 中,认真看上一篇文章的同学知道我们在代码提交前进行了pre-commit,单测不通过的代码是不行进行提交的,但是这只是进行本地的一个控制,还是有很多手段是可以略过这一步的;我们需要从服务端进行一个强控制;单测不通过的合并请求是无法进行合并的,并对单测失败的成员进行了一个消息的提示,包括邮件提示、通讯工具的提示(eg:企业微信、云之家、钉钉)

一、gitlab 单元测试流水线的计划配置

 我们上一篇文章介绍的是每一次pushes 都会自动跑一次流水线,这是在yml 配置文件中的每个stages 中的only 参数进行配置的,假如我们把only 参数配置成schedules,那我们就可以定制流水线执行的时机,是每天还是每周执行一次,亦或是每一天执行n次;

这里附上每个工作日10点、24点各执行一次的配置:

循环周期: 自定义  0 12,24 * * 1-5

二、代码合并前流水线必须通过的配置

进行了这个配置,单测跑不过的合并请求是无法进行合并的;

三、 邮件通知以及钉钉消息通知

    3.1 邮件通知这个功能是相对简单的,只需要在gitlab 上进行简单的配置;

3.2 接下来介绍一下钉钉、企业微信等的消息通知(包括通知所有成员以及特定的提交成员)

首先我们必须对wehook 有一定了解, 这里不做过多介绍,不懂得可以问问度娘;

我们需要先(钉钉、云之家)在一个群中创建并开启一个自定义机器人,并拿到其相应的webhook地址:****

拿到了webhook 地址之后,我们需要在yml中添加一个消息通知的作业

  notify-job:  stage: notify  image: node:13  script:    - chmod +x py/Notify.py; ./py/Notify.py $MERGE_URL ${JOB_URL} $CI_COMMIT_REF_NAME $SONAR_CHECK_URL;  when: on_failure
复制代码

注意: 这里的这个消息通知作业只会在前面的作业失败的情况下触发,正常情况下执行python 脚本需要用到python 镜像,我这里通过在脚本顶部添加以下命令:#! /usr/bin/env python;让Python脚本像SHELL脚本一样直接执行

对yml 有一定了解的同学肯定知道,处于同一个stage 的作业(job) 是可以并行执行的,只要你gitlab-runner config.toml配置设置的concurrent 大于1(默认是1), when: on_failure 这里的触发条件是前面的作业只要有失败就会触发,那么我们怎么知道是哪一个作业是失败的呢?找了很多资料,我也没找到好的参数/办法,最后还是找到一个土办法(在每个job执行脚本之后,往一个文件里面写内容,然后当job 执行失败的时候把这个文件通过artifacts上传,artifacts 可实现不同作业之间的通讯),在消息通知的那个作业通过读取上传的这个文件的内容来判断是哪个作业失败

sonarqube-check:  before_script:    - echo "FAIL" > .job_status  stage: test  image: sonarsource/sonar-scanner-cli:latest  script:      - sonar-scanner -Dsonar.projectKey=${CI_PROJECT_NAME} -Dsonar.sourceEncoding=UTF-8 -Dsonar.java.binaries=. -Dsonar.java.source=11 -Dsonar.pullrequest.branch=${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} -Dsonar.pullrequest.key=${CI_MERGE_REQUEST_IID} -Dsonar.pullrequest.base=${CI_MERGE_REQUEST_TARGET_BRANCH_NAME} -Dsonar.projectDescription=${CI_PROJECT_TITLE} -Dsonar.links.homepage=${CI_PROJECT_URL} -Dsonar.java.binaries=target/classes -Dsonar.java.test.binaries=target/test-classes -Dsonar.java.surefire.report=target/surefire-reports -Dsonar.gitlab.ref_name=${CI_COMMIT_REF_NAME} -Dsonar.gitlab.commit_sha=${CI_COMMIT_SHA} -Dsonar.gitlab.project_id=${CI_PROJECT_PATH} -Dsonar.pullrequest.gitlab.repositorySlug=$CI_PROJECT_ID -Dsonar.qualitygate.wait=true      - echo "SUCCESS" > .job_status  only:    - merge_requests  artifacts:    paths:      - .job_status    when: on_failure    expire_in: 30 mins 4 secnotify-job:  stage: notify  image: node:13  script:    - if [ "$(cat .job_status)" == FAIL ]; then chmod +x py/NoticeToYZJ.py; ./py/NoticeToYZJ.py sonarqube-check $MERGE_URL ${JOB_URL} $CI_COMMIT_REF_NAME $SONAR_CHECK_URL; fi  only:    - merge_requests  when: on_failure
复制代码

    其实我们可以发现每个作业除了script 还有 before_script、after_script 而且after_script 不论是作业失败还是成功,都会执行,我们可以利用这个特点,进行每个作业的失败消息提示

unit-test:  before_script:    - echo "FAIL" > .job_status  script:    - rm -rf node_modules    - unzip -q node_modules.zip    - npm run test:ci    - echo "SUCCESS" > .job_status  stage: test  only:    - merge_requests  image: node:13  artifacts:    paths:      - coverage/lcov-report/  coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'  after_script:    - if [ "$(cat .job_status)" == FAIL ]; then chmod +x py/NoticeToYZJ.py; ./py/NoticeToYZJ.py ${CI_JOB_NAME} $MERGE_URL ${JOB_URL} $CI_COMMIT_REF_NAME $SONAR_CHECK_URL; fi
复制代码

作业添加后,我们来开始编写消息通知脚本 ,我们这里实现了通知了所有人,以及通知特定消息通知对象两种方式:

一: 通知所有人

#! /usr/bin/env python# This Python file uses the following encoding: utf-8import reimport osimport urllib2import jsonimport sys def getData(job_name, job_url, branch_name, sonar_check_url):    if job_name == 'unit-test':        return {             "content":  '@all ' + '\n' +                '##' + '单元测试失败告警:' + '##' + '\n' +                '分支:%s' %branch_name + '\n' +                '查看链接:%s' %job_url + '\n'        }    elif job_name == 'sonarqube-check':        return {             "content":  '@all ' + '\n' +                '##' + '代码扫描失败告警:' + '##' + '\n' +                '分支:%s' %branch_name + '\n' +                '查看链接:%s' %sonar_check_url + '\n'        }    else:        return None def getContent():    content = (os.popen("git log --pretty=format:\"%an-&%h-&%s\" -1 ").read()).split("-&")    return content  def doNotify(content):    print(sys.argv)    global sonar_check_url, job_name, job_url, commit_url, branch_name, name, shortcodenum, explain, posturl, headers, request    job_name = sys.argv[1]    commit_url = sys.argv[2]    job_url = sys.argv[3]    branch_name = sys.argv[4]    sonar_check_url = sys.argv[5]    name = content[0]    shortcodenum = content[1]    explain = content[2]
    posturl = "*****"    data = getData(job_name, job_url, branch_name, sonar_check_url)    string_textMsg1 = json.dumps(data)    request = urllib2.Request(posturl)    request.add_header('Content-Type', 'application/json;charset=utf-8')    urllib2.urlopen(request, string_textMsg1) if __name__ == "__main__":    string_textMsg = {}    content = getContent()    doNotify(content)
复制代码

一: 通知特定人

#! /usr/bin/env python# This Python file uses the following encoding: utf-8import reimport osimport urllib2import jsonimport syssys.path.append("/py")import globalVar as globalVar def get_data(name, job_name, job_url, branch_name, shortcodenum, explain, phone, sonar_check_url):    if job_name == 'unit-test':        return {             "content":  '##' + '单元测试失败告警:' + '##' + '\n' +                '负责人:%s' %name + '\n' +                '提交分支:%s' %branch_name + '\n' +                '提交SHA:%s' %shortcodenum + '\n' +                '提交信息:%s' %explain + '\n' +                '查看链接:%s' %job_url + '\n'    ,        "notifyParams": [           {            "type": "mobiles",            "values": [                phone            ]           }]        }    elif job_name == 'sonarqube-check':        return {             "content":  '##' + '代码扫描失败告警:' + '##' + '\n' +                '负责人:%s' %name + '\n' +                '提交分支:%s' %branch_name + '\n' +                '提交SHA:%s' %shortcodenum + '\n' +                '提交信息:%s' %explain + '\n' +                '查看链接:%s' %sonar_check_url + '\n'    ,        "notifyParams": [           {            "type": "mobiles",            "values": [                phone            ]           }]        }    else:        return Nonedef get_content():    content = (os.popen("git log --pretty=format:\"%an-&%h-&%s\" -1 ").read()).split("-&")    return content  def post_notify(content):    print(sys.argv, content)    global sonar_check_url, job_name, job_url, commit_url, branch_name, name, shortcodenum, explain, webhookurl, headers    job_name = sys.argv[1]    commit_url = sys.argv[2]    job_url = sys.argv[3]    branch_name = sys.argv[4]    sonar_check_url = sys.argv[5]    name = content[0]    shortcodenum = content[1]    explain = content[2]    webhookurl = "***webhookurl"    for i in globalVar.gitlabMembers:        global phone        if i["name"] == name:          phone = i["phone"]    data = get_data(name, job_name, job_url, branch_name, shortcodenum, explain, phone, sonar_check_url)    string_textMsg = json.dumps(data)    request = urllib2.Request(webhookurl)    request.add_header('Content-Type', 'application/json;charset=utf-8')    urllib2.urlopen(request, string_textMsg) if __name__ == "__main__":    string_textMsg = {}    content = get_content()    post_notify(content)
复制代码

好了,到这里文章也到尾声了,自己在做这个消息通知的这一块过程中也是碰到一些坑,有问题或者有更好实现的同学欢迎交流~

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享