GitLab + Sonar 做代码质量分析

3,217 阅读4分钟

由于近期想尝试对自建的gitlab中的代码在每次代码提交时进行代码质量分析,所有有了这篇文章的素材。文中有不正确的欢迎指正,废话不多说,首先来讲下gitlab的安装,为了方便服务的安装都是基于docker安装的,对docker不熟的请自补。
关于docker以及docker-compose的安装方式这里我就不赘述了,网上一大把。

一、GitLab 安装

gitlab的docker-compose.yml配置文件

# docker-compose.yml for GitLab
version: "3"
services:
  web:
    image: 'gitlab/gitlab-ce:latest'
    container_name: gitlab
    hostname: 'gitlab.xxxx.com' #gitlab 将要使用的域名
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'http://gitlab.xxx.com' 

        gitlab_rails['gitlab_shell_ssh_port'] = 2289
        gitlab_rails['gitlab_shell_git_timeout'] = 800

		# 配置邮件服务
        gitlab_rails['smtp_enable'] = true
        gitlab_rails['smtp_address'] = "smtp.exmail.qq.com"
        gitlab_rails['smtp_port'] = 465
        gitlab_rails['smtp_user_name'] = "noreply@xxx.com"
        gitlab_rails['smtp_password'] = "xxxxxx"
        gitlab_rails['smtp_authentication'] = "login"
        gitlab_rails['smtp_enable_starttls_auto'] = true
        gitlab_rails['smtp_tls'] = true
        gitlab_rails['gitlab_email_from'] = 'noreply@xxx.com'
        gitlab_rails['gitlab_email_reply_to'] = 'noreply@xxx.com'

		# 配置备份的远程对象存储服务, 这里我用的是自建的 minio 对象存储,也可以用oss/aws等
        gitlab_rails['backup_upload_connection'] = {
          'provider' => 'AWS',
          'region' => 'us-east-1',
          'aws_access_key_id' => 'xxxx',
          'aws_secret_access_key' => 'xxxx',
          'aws_signature_version' => 4,
          'path_style' => true,
          'host' => '172.16.10.235',
          'endpoint' => 'http://172.16.10.235:7000'
        }
        gitlab_rails['backup_upload_remote_directory'] = 'gitlab-backup'
        gitlab_rails['backup_keep_time'] = 604800
    ports:
    	# 将端口映射到宿主机
      - '8929:80'
      - '2289:22'
    volumes:
      - '/home/docker/gitlab/config:/etc/gitlab'
      - '/home/docker/gitlab/logs:/var/log/gitlab'
      - '/home/docker/gitlab/data:/var/opt/gitlab'
    restart: always

配置好之后,再yml同级目录执行 docker-compose up -d 一个gitlab服务安装好了。
为了更好的URL体验再宿主机上面配置下nginx代理,具体配置如下:

# gitlab.xxx.com.conf
server
{
    listen  80;
    server_name gitlab.xxx.com;

    access_log logs/gitlab.xxx.com-access.log  combined;
    error_log  logs/gitlab.xxx.com-error.log crit;

    location / { # 如果你希望通过子路径访问,此处修改为子路径,注意以 / 开头并以 / 结束
      proxy_set_header   Host             $http_host;
      proxy_set_header   X-Real-IP        $remote_addr;
      proxy_set_header   X-Forwarded-Proto  $scheme;
      proxy_set_header   X-Forwarded-Host  $http_host;
      proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

      proxy_pass http://127.0.0.1:8929;
    }
}

最后通过url:gitlab.xxx.com 进行访问,默认的帐号是root,首次打开会要求设置密码。

二、SonarQube 安装

SonarQube的docker-compose.yml配置文件

# docker-compose.yml for Sonar
version: "3"
services:
  # db 服务
  database:
    image: postgres:10.12-alpine
    container_name: sonar-postgres
    privileged: true # root 权限
    restart: always
    environment:
      - POSTGRES_USER=sonar 
      - POSTGRES_PASSWORD=sonar
      - POSTGRES_DB=sonar
      - PGDATA=/var/lib/postgresql/data # 数据存储文件夹
    volumes:
      - ./postgres/data:/var/lib/postgresql/data
    ports:
      - 5432:5432
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
  # sonarQube
  sonarqube:
    image: sonarqube:8.4-community
    container_name: sonarqube-server
    restart: always
    ports:
      - "9090:9000"
    volumes:
        - /etc/localtime:/etc/localtime:ro
        - ./sonarqube/extensions:/opt/sonarqube/extensions
        - ./sonarqube/logs:/opt/sonarqube/logs
        - ./sonarqube/data:/opt/sonarqube/data
        - ./sonarqube/conf:/opt/sonarqube/conf
    links:
      - database
    environment:
      - SONARQUBE_JDBC_USERNAME=sonar
      - SONARQUBE_JDBC_PASSWORD=sonar
      - SONARQUBE_JDBC_URL=jdbc:postgresql://database:5432/sonar
    depends_on:
      - database

如同Gitlab服务一样,在yml文件统计目录执行命令 docker-compose up -d 就将SonarQube服务安装成功了,同样的再宿主机上配置好nginx代理就能通过域名访问Sonar了。nginx配置如下

server
{
  listen  80;
  server_name sonar.xxx.com;

  access_log logs/sonar.xxx.com-access.log  combined;
  error_log  logs/sonar.xxx.com-error.log crit;

  location / { # 如果你希望通过子路径访问,此处修改为子路径,注意以 / 开头并以 / 结束
    proxy_set_header   Host             $http_host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-Proto  $scheme;
    proxy_set_header   X-Forwarded-Host  $http_host;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

    proxy_pass http://127.0.0.1:9090;
  }
}

重启nginx生效后,直接打开浏览器访问 sonar.xxx.com/ 即可。默认管理员账号密码为: admin/admin
然后可以安装中文插件,以及一些代码分析器插件。
image.png
image.png
同时为了跟gitlab联合使用需要安装sonar-gitlab-plugin插件,插件地址:github.com/gabrie-alla…
将下载来的插件放入目录sonarqube/extensions/plugins/重启服务插件就被启用了,如图:
image.png
配置>通用配置中会出现GitLab选项,配置好其中 GitLab url 为自己的gitlab地址,GitLab User Tokens 为gitlab用户创建的Access Tokens 且开启了api权限,gitlab.xxx.com/profile/per…
image.png
image.png
此时还需要在 sonar.xxx.com/account/sec… 页面添加一个令牌后面需要用到。
image.png
到这里两个服务算是安装完成了。接下来就是两个服务之间的嵌入了。由于是在git commit 之后进行代码质量分析所以需要借助gitlab的ci/cd,亦须安装gitlab的gitlab-runner服务。

三、gitlab-runner服务安装

同样也是使用docker-compose 安装,docker-compose.yml如下:

# docker-compose.yml for gitlab-runner
version: "3"
services:
  runner:
    image: gitlab/gitlab-runner
    restart: always
    container_name: gitlab-runner
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /home/docker/gitlab-runner/config:/etc/gitlab-runner
      - /home/docker/gitlab-runner/cache:/cache

安装好gitlab-runner服务后,为执行Sonar注册runner。
根据gitlab.xxxx.com/admin/runner页面Setup a shared Runner manually的步骤进行注册,如下图:
image.png
在宿主机上执行命令以注册runner。

# docker exec -it 容器名称 命令
docker exec -it gitlab-runner gitlab-runner register #gitlab-runner register注册一个runner
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/): #http://gitlab.xxx.com/admin/runners中对应的URL
http://gitlab.xxxx.com
Please enter the gitlab-ci token for this runner:  #http://gitlab.xxx.com/admin/runners中对应的token
1SpVgbxxxxxxxxGGv
Please enter the gitlab-ci description for this runner: #此runner的描述,会记录在gitlab runner页面中
[1a197e3371d1]: SonarQube_runner
Please enter the gitlab-ci tags for this runner (comma separated): #为此runner打一些tag标签
analyze
Please enter the executor: kubernetes, parallels, shell, ssh, virtualbox, docker, docker-ssh, docker+machine, docker-ssh+machine: #选择一个executor用来跑job
docker
Please enter the default Docker image (e.g. ruby:2.1): #选择一个默认的镜像仓库作为每个job的base image,每个job默认将基于此镜像运行
docker:latest
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

注册完成之后我们可以看到runner生成的配置文件

# config/config.toml
concurrent = 20
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "SonarQube_Runner"
  url = "http://gitlab.xxx.com/"
  token = "z-SMW3FyVUhg2Eswdr7D"
  executor = "docker"
  output_limit = 8192
  cache_dir = "/cache"
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
  [runners.docker]
    tls_verify = false
    image = "docker:latest"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    shm_size = 0

在gitlab.xxx.com/admin/runner页面,我们可以看到新建的runner。
image.png
runner支持同时多个job运行,修改config/config.toml 文件中 concurrent=20 来作为并发运行多个job,这里根据自身需求来修改。
回到gitlab.xxx.com/admin/runner页面,编辑新建的runner以添加可以使用此runner的项目,即需要做代码质量分析的项目。

四、配置.gitlab-ci.yml

最后在需要做代码质量分析的项目根目录中添加.gitlab-ci.yml文件,详细配置参考docs.gitlab.com/ee/ci/yaml/…
这里我给出2个已经配置好的.gitlab-ci.yml以作参考。
Maven项目:

# .gitlab-ci.yml for Maven
cache:
  key: ${CI_PROJECT_NAME}
  paths:
    - .m2/repository
    
variables:
  SONAR_TOKEN: "a1a0xxffxxxx9" # 安装sonar服务时创建的令牌
  SONAR_HOST_URL: "http://sonar.xxx.com" # sonar服务地址
  SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
  GIT_DEPTH: 0
  MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
  
stages:
  - analyze
  
sonar_analyze:
  image: registry.cn-hangzhou.aliyuncs.com/acs/maven:3-jdk-8
  stage: analyze
  script:
    - |
        mvn -B clean package sonar:sonar \
        -Dmaven.test.skip=true \  #不执行测试用例,也不编译测试用例类
        -Dsonar.gitlab.project_id=$CI_PROJECT_PATH \   #明确gitlab项目的id,在分析结束后将结果评论在commit记录中,且sonar集成需要
        -Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA \   #明确gitlab项目分支本次commit的SHA,sonar集成时需要
        -Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME \  #明确gitlab项目本次执行分析的分支,sonar集成时需要
        -Dsonar.projectKey=$CI_PROJECT_NAME \   #定义sonar本次分析项目的key 
        -Dsonar.projectName=$CI_PROJECT_NAME \  #定义sonar本次分析项目的名称
        -Dsonar.gitlab.comment_no_issue=true #无论本次扫描结果有无issue都可以追加评论,默认false
  allow_failure: true
  tags:
    - analyze
  only:
    - merge_requests
    - develop

NodeJs项目:

# .gitlab-ci.yml for NodeJs
cache:
  key: ${CI_PROJECT_NAME}
  paths:
    - .sonar/cache
    
variables:
  SONAR_TOKEN: "a1a0xxffxxxx9" # 安装sonar服务时创建的令牌
  SONAR_HOST_URL: "http://sonar.xxx.com" # sonar服务地址
  SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
  GIT_DEPTH: 0
  
stages:
  - analyze
  
sonar_analyze:
  image: sonarsource/sonar-scanner-cli:latest
  stage: analyze
  script:
    - |
        sonar-scanner -Dsonar.gitlab.project_id=$CI_PROJECT_PATH \   #明确gitlab项目的id,在分析结束后将结果评论在commit记录中,且sonar集成需要
        -Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA \   #明确gitlab项目分支本次commit的SHA,sonar集成时需要
        -Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME \  #明确gitlab项目本次执行分析的分支,sonar集成时需要
        -Dsonar.projectKey=$CI_PROJECT_NAME \   #定义sonar本次分析项目的key 
        -Dsonar.projectName=$CI_PROJECT_NAME \  #定义sonar本次分析项目的名称
        -Dsonar.gitlab.comment_no_issue=true #无论本次扫描结果有无issue都可以追加评论,默认false
  allow_failure: true
  tags:
    - analyze
  only:
    - merge_requests
    - develop

五、结果

分析完成后的结果会上传到sonar服务上,同时也会在本次git commit 下面进行评论,如图:
image.png
image.png