一起养成写作习气!这是我参加「日新方案 4 月更文应战」的第13天,点击查看活动概况。

在项目开发的过程中,为了确保代码质量,咱们会运用诸多代码质量检测东西,这些东西或是在本地,或是在云端,虽然东西能够检测出反常问题,可是这些问题仍是需求咱们程序员来修正,假如咱们不强制一切人有必要修正反常问题,某些人可能就会越过反常检测,将代码合入骨干。为了处理这个问题,咱们需求强制门禁体系,所谓门禁便是经过检测的才干合入,不经过检测的不能合入。GitLab自身就为咱们提供了这样的设置,咱们只需求装备检测规则就能够了。

敞开代码合入门禁

在项目设置中,装备只答应流水线成功的兼并恳求

配置GitLab流水线和门禁系统

GitLab Runner

要完结流水线的履行,当然需求有履行进程和环境了。GitLab为咱们提供了CI东西-GitLab Runner,经过装备GitLab Runner,将环境注册到GitLab上,提交代码的时分,GitLab才干运用履行环境来跑咱们的检测功用。

下载装置

虽然也能够经过docker进行装置,可是GitLab Runner只是一个二进制文件,下载后直接就能够在机器上运转,并且运用docker布置的话,履行指令也是在docker中,假如需求一些其他的环境装备,也有必要在docker中装置,这是比较费事的。

gitlab-runner-downloads.s3.amazonaws.com/latest/bina…

# 复制下载的文件到 /usr/local/bin 目录下
mv gitlab-runner-linux-amd64 /usr/bin/gitlab-runner
# 增加履行权限
chmod +x gitlab-runner
# 装置生成装备
gitlab-runner install --user=root --working-directory=/data/gitlab-runner
# 发动服务
gitlab-runner start

注册服务到GitLab

装置今后咱们需求把GitLab Runner注册到GitLab上,咱们能够选择同享Runner和指定Runner的方法。同享Runner便是咱们运用管理员账号获取的大局注册信息,注册后此Runner能够给一切代码库运用;指定Runner是给每一个库房装备的特定Runner,只能跑本库房的流水线。我主张大家注册成同享Runner,由于同享Runner也能够设置为多个代码库的Runner,这样比较便利。

  • 运用管理员账号登录Git Lab后台

配置GitLab流水线和门禁系统

  • 注册同享Runner
gitlab-runner register

配置GitLab流水线和门禁系统

url和token便是上图中展示的,描绘和tag自己随意输入,tag要记住,后边要运用的

  • 查看Runner注册是否成功

配置GitLab流水线和门禁系统

  • 发动Runner服务
# 这个是前台运转的指令,需求运用nohup转为后端运转
# 也有人说经过sudo注册的gitlab-runner直接便是后台运转
gitlab-runner run

测验GitLab流水线

  • 创立.gitlab-ci.yml

在项目根目录创立 .gitlab-ci.yml 文件,内容可做如下装备:

stages:
  - sonarcheck
sonarcheck:
  stage: sonarcheck
  script:
    - echo $CI_PROJECT_DIR
    - cd $CI_PROJECT_DIR
    - sonar-scanner
  tags:
    - sonar

stages:指定流水线一切过程

script:当时过程的履行指令

$CI_PROJECT_DIR:默许环境变量,本次流水线履行时下载的代码目录

tags:运用的runner

假如想要查看一切内置的环境变量,能够做如下装备

script:
  - export  // linux下运用此指令
  - 'dir env:'  // Windows运用此指令

提交代码后,就会看见流水线主动履行

配置GitLab流水线和门禁系统

对接sonarqube

gitlab流水线装备好今后,咱们就能够对接sonarqube来完结代码上库门禁了

建立sonarqube环境

请参考咱们的上一篇文章:建立 sonarqube 代码质量扫描环境

装备门禁关联

这一块我耗费了很长时刻,在网上也没找到相应的教程,在最终要抛弃之前,总算搞定了。原本我的主意是每个人在向骨干提交MR的时分,发动流水线,假如流水线经过就运转合入,假如流水线不经过就不能合入。依据这种主意我搞了好久都没有完结,最后才搞理解,GitLab里边装备的“只答应兼并流水线成功的兼并恳求”意思是在兼并恳求当中,假如流水线是成功的就答应。这儿并不是在提交MR的时分才去跑流水线,而是跑完流水线今后,在提交MR,此刻GitLab会获取本次合入所对应的流水线状况,假如状况是成功,那么就答应合入,假如不成功就不答应合入。因而我最后装备为每次提交都跑一次流水线使命,这样在合入的时分就能正确地拿到状况,并阻止不成功的合入。

装备流水线使命

在项目根目录创立.gitlab-ci.yml文件,这样GitLab就会在提交的时分主动检测此文件的装备,依照装备跑使命。对于文件的装备方法这儿不做具体的描绘,网上有许多类似的文章,并且咱们一般运用的都比较简单,首要逻辑都是在script里边取完结的。

stages:
  - sonarcheck
  - checkresult
variables:
  access_token: xxxx
  secret: xxxx
  check_path: /data/xxxx/sonardata
  project: xxxx
sonarcheck:
  stage: sonarcheck
  script:
    - echo $CI_PROJECT_DIR
    - cd $CI_PROJECT_DIR
    - sonar-scanner
  tags:
    - sonar
checkresult:
  stage: checkresult
  script:
    - cd $check_path
    - python3 sonar.py $project $access_token $secret
  tags:
    - sonar
  • stages:装备履行阶段,假如不装备的话,会有默许的几个阶段。
  • variables:装备变量。
  • sonarcheck/checkresult:这是属于使命名,能够随意起,我这儿运用和阶段相同的名称。
  • stage:用来指定当时使命对应的是哪个阶段。
  • script:使命履行指令。
  • tags:当时使命需求跑到哪个Runner上,这儿装备的是Runner的标签。
  • only:装备履行分支、条件等,假如不装备那么一切分支提交时都会跑使命
  • $CI_PROJECT_DIR:本次使命所下载的代码途径,这个是环境变量,能够运用上面介绍的方法答应一切的

成果检测脚本

由于咱们运用的sonarqube进行代码质量检测,Runner履行的sonar-scanner 只是把sonarqube扫描指令调起来,成功或许失利成果是不会收到的,因而即便sonarqube检测的代码有问题,流水线也不会报失利,所以需求咱们自己写代码来检测sonarqube是否检测到反常,假如有反常就抛出过错。

import os
import sys
from sonarqube import SonarQubeClient
from dingtalkchatbot.chatbot import DingtalkChatbot, CardItem, ActionCard
# 获取sonarqube检测成果
def getSonarqubeInfo(branch="master", component=None, url=None, username=None, password=None):
    sonar = SonarQubeClient(sonarqube_url=url)
    sonar.auth.authenticate_user(login=username, username=username, password=password)
    component_data = sonar.measures.get_component_with_specified_measures(
        component=component,
        branch=branch,
        fields="metrics,periods",
        # metricKeys="""
        # code_smells,bugs,coverage,duplicated_lines_density,ncloc,
        # security_rating,reliability_rating,vulnerabilities,comment_lines_density,
        # ncloc_language_distribution,alert_status,sqale_rating
        # """
        metricKeys="code_smells,bugs,vulnerabilities"
    )
    result_dict = {}
    for info_dict in component_data["component"]["measures"]:
        result_dict[info_dict["metric"]] = info_dict["value"]
    return result_dict
# 发送钉钉音讯,通知本次反常成果
def send_dingding_msg(access_token, secret, result_dict, project, url):
    webhook = f'https://oapi.dingtalk.com/robot/send?access_token={access_token}'
    chatbot = DingtalkChatbot(webhook, secret=secret)
    btns = [CardItem(title="查看概况", url=f"{url}/project/issues?id={project}&resolved=false")]
    actioncard = ActionCard(title='亲,本次修正有问题哦!!!',
                             text=f'代码检测成果如下:\n\nBug:{result_dict["bugs"]}\n\n缝隙:{result_dict["vulnerabilities"]}\n\n异味:{result_dict["code_smells"]}',
                             btns=btns,
                             btn_orientation=1,
                             hide_avatar=1)
    chatbot.send_action_card(actioncard)
if __name__ == '__main__':
    url = "http://192.168.1.123:9000"
    username = "admin"
    password = "123456"
    branch = 'master'
    project = sys.argv[1]
    access_token = sys.argv[2]
    secret = sys.argv[3]
    sonarqube_data = getSonarqubeInfo(branch=branch, component=project, url=url, username=username, password=password)
    if (sonarqube_data['bugs'] != 0) or (sonarqube_data['vulnerabilities'] != 0) or (sonarqube_data['code_smells'] != 0):
        print('代码检测反常:', sonarqube_data)
        send_dingding_msg(access_token=access_token, secret=secret, result_dict=sonarqube_data, project=project, url=url)
        sys.exit(1)
    else:
        print('本次提交十分完美!Perfect')

写好脚本后,咱们将它放到履行机器上,是否上库依据个人需求,咱们的意图是在sonarqube履行完后,跑这个脚原本履行。

测验门禁作用

我运用的门禁装备如下:

stages:
  - sonarcheck
  - checkresult
  - build
  - deploy
variables:
  access_token: xxxxx
  secret: xxxxx
  check_path: /data/xxxxx/sonardata
  project: xxxxx
  deploy_path: /data/xxxxx/frontend
sonarcheck:
  stage: sonarcheck
  script:
    - echo $CI_PROJECT_DIR
    - cd $CI_PROJECT_DIR
    - sonar-scanner
  tags:
    - sonar
  except:
    - master
checkresult:
  stage: checkresult
  script:
    - cd $check_path
    - python3 sonar.py $project $access_token $secret
  tags:
    - sonar
  except:
    - master
build:
  stage: build
  script:
    - cd $CI_PROJECT_DIR
    - yarn
    - yarn build
  tags:
    - sonar
  only:
    - master
  cache:
    paths:
      - dist/
deploy:
  stage: deploy
  script:
    - rm -rf $deploy_path/*
    - cd $CI_PROJECT_DIR
    - cp -r $CI_PROJECT_DIR/dist/* $deploy_path
  tags:
    - sonar
  only:
    - master
  dependencies:
    - build
  cache:
    paths:
      - dist/
    policy: pull

总共有四个履行阶段:

  • sonarcheck

在非master分支下,履行sonar-scanner查看

  • checkresult

在非master分支下,履行sonar.py脚本获取sonarqube检测成果

  • build

在master分支下,履行前端打包,然后将dist目录缓存下来

  • deploy

在master分支下,build使命履行成功后才干履行,将上一步缓存的内容下载到dist/目录,清空前端布置目录,再将打包好的dist目录中文件复制到前端布置目录下。

提交代码发动流水线使命

当咱们提交代码时,会触发流水线使命

配置GitLab流水线和门禁系统

点击流水线使命,能够看到履行阶段

配置GitLab流水线和门禁系统

假如要查看具体的履行日志,能够点击具体阶段进行查看

配置GitLab流水线和门禁系统

当履行完今后,能够提交合入恳求

提交合入恳求

配置GitLab流水线和门禁系统

能够看到合入恳求中会显示流水线使命状况,当流水线使命还未履行完结时,会看到如下界面

配置GitLab流水线和门禁系统

等流水线履行完结后,显示如下界面:

配置GitLab流水线和门禁系统

假如流水线履行失利,兼并按钮不行点击,这样就确保了每次合入都有必要经过查看。由于咱们装备了master分支打包布置,因而当兼并代码后,会主动发动打包布置流水线。

履行打包布置

配置GitLab流水线和门禁系统

总结

在装备的过程中,有一些需求了解的问题,Runner的装备和CI文件的装备。在CI文件的装备中需求注意缓存的处理,默许状况下每一个阶段的履行都会清理环境到最洁净的状况,也便是生成的一切中心文件或许修正文件都会在下一阶段履行前康复成与Git库房同步的状况。针对这种状况,CI为咱们提供了缓存机制,缓存分为本地缓存和服务器缓存,服务器缓存首要是为了处理分布式流水线履行,一般选用本地缓存就能够了。本地缓存会在本地生成一个cache目录,咱们想要缓存某个阶段的文件或许目录,就在某个阶段装备cache,当然也能够在大局进行装备,这样缓存便是对每个阶段都生效的。咱们在示例中只装备了缓存途径path,这样一切的流水线都会缓存到一个目录中,假如需求每个分支缓存到不同文件,那么就需求增加key的装备,除了装备key以外,还有缓存战略装备,默许的战略是下载/上传,可是在有些使命中,咱们只需求运用上一阶段的缓存文件即可,因而咱们能够装备为pull战略,这样就只会下载上一步的缓存文件,不会继续上传到缓存地址。