Code Quality

使用 Code Quality 来分析源代码的质量和复杂性,有助于使您的项目代码简单、可读且易于维护。Code Quality 应该补充您的其他评审流程,而不是取代它们。

Code Quality 使用开源 Code Climate 工具,并选择插件来分析您的源代码。 要确认您的代码的语言是否包含在内,请参阅支持的可维护性语言的 Code Climate 列表。 您可以使用 Code Climate 分析插件自定义工具来扩展代码覆盖率。

在 CI/CD 流水线中运行 Code Quality 报告,验证变更不会降低代码质量,然后再将它们提交到默认分支。

产品级别功能摘要

不同的极狐GitLab 产品级别提供不同的功能,如下表所示:

能力 基础版 专业版 旗舰版
配置扫描器
集成自定义扫描器
在合并请求部件中查看结果
生成 JSON 或 HTML 报告产物
查看 CI 流水线中的报告
在合并请求差异视图中查看结果

查看 Code Quality 结果

Code Quality 结果显示在:

  • 合并请求部件
  • 合并请求变更视图
  • 流水线详情视图
  • 项目质量视图

合并请求部件

如果来自目标分支的报告可用于比较,Code Quality 分析结果将显示在合并请求部件区域中。

Code Quality Widget

查看 Code Climate 支持的可维护性语言列表。

合并请求变更视图

  • 引入于 13.11 版本,在 codequality_mr_diff 功能标志后面默认禁用。
  • 默认启用于 13.12 版本。
  • 默认禁用于 14.0 版本。
  • 于 14.1 版本添加了行内注释,并删除了功能标志。

Code Quality 结果显示在合并请求变更视图中。对于包含 Code Quality 问题的行,会在装订线旁边显示标记。将鼠标悬停在标记上可以了解问题的详细信息。

Code Quality MR diff report

流水线详情视图

流水线生成的 Code Quality 违规的完整列表显示在流水线详细信息页面的代码质量选项卡中。

Code Quality Report

项目质量视图

项目质量视图显示代码质量调查结果的概览。

Code Quality Summary

启用 Code Quality

先决条件:

  • 极狐GitLab CI/CD 配置(.gitlab-ci.yml)必须包括 test 阶段。
  • 如果您使用的是共享 runner,则必须为 Docker-in-Docker 工作流 配置 Code Quality 作业。
  • 如果您使用私有 runner,您应该使用推荐的替代配置,更有效地运行 Code Quality 分析。
  • Runner 必须有足够的磁盘空间来存储生成的 Code Quality 文件。例如,在极狐GitLab 项目上,文件大约为 7 GB。

要启用代码质量,您需要在 .gitlab-ci.yml 文件中包含 Code Quality 模板。

示例:

  include:
  - template: Jobs/Code-Quality.gitlab-ci.yml

  code_quality:
    image: registry.gitlab.cn/gitlab-cn/docker:20.10.12
    services:
      - name: 'registry.gitlab.cn/gitlab-cn/docker:20.10.12-dind'
        command: ['--tls=false', '--host=tcp://0.0.0.0:2375']
        alias: docker
    variables:
      CODECLIMATE_PREFIX: "registry.gitlab.cn/"

Code Quality 现在在流水线中运行。

caution 在私有化部署版实例上,如果恶意行为者破坏 Code Quality 作业定义,他们可以在 runner 主机上执行特权 Docker 命令。拥有适当的访问控制策略,通过只允许受信任的参与者访问来减缓这种攻击向量。

使用私有 runners 提升 Code Quality 性能

如果您有私有 runner,您应该使用以下配置来提高 Code Quality 的性能:

  • 不使用特权模式。
  • 不使用 Docker-in-Docker。
  • Docker 镜像,包括所有 CodeClimate 镜像都被缓存,并且不会为后续作业重新获取。

此替代配置使用套接字绑定与作业环境共享 Runner 的 Docker 守护进程。在实施此配置之前,请考虑其限制

使用私有 runners:

  1. 注册一个新的 runner:

    $ gitlab-runner register --executor "docker" \
      --docker-image="docker:stable" \
      --url "https://jihulab.com/" \
      --description "cq-sans-dind" \
      --tag-list "cq-sans-dind" \
      --locked="false" \
      --access-level="not_protected" \
      --docker-volumes "/cache"\
      --docker-volumes "/builds:/builds"\
      --docker-volumes "/var/run/docker.sock:/var/run/docker.sock" \
      --registration-token="<project_token>" \
      --non-interactive
    
  2. 可选,但推荐:将构建目录设置为 /tmp/builds,以便定期从 runner 主机中清除作业产物。如果跳过这一步,您必须自己清理默认的构建目录(/builds)。您可以通过在上一步中,将以下两个标志添加到 gitlab-runner register 来做到这一点。

    --builds-dir "/tmp/builds"
    --docker-volumes "/tmp/builds:/tmp/builds" # Use this instead of --docker-volumes "/builds:/builds"
    

    生成的配置:

    [[runners]]
      name = "cq-sans-dind"
      url = "https://jihulab.com/"
      token = "<project_token>"
      executor = "docker"
      builds_dir = "/tmp/builds"
      [runners.docker]
        tls_verify = false
        image = "docker:stable"
        privileged = false
        disable_entrypoint_overwrite = false
        oom_kill_disable = false
        disable_cache = false
        volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock", "/tmp/builds:/tmp/builds"]
        shm_size = 0
      [runners.cache]
        [runners.cache.s3]
        [runners.cache.gcs]
    
  3. 对模板创建的 code_quality 作业应用两个覆盖:

    include:
      - template: Code-Quality.gitlab-ci.yml
    
    code_quality:
      services:            # Shut off Docker-in-Docker
      tags:
        - cq-sans-dind     # Set this job to only run on our new specialized runner
    

Code Quality 现在在标准 Docker 模式下运行。

禁用 Code Quality

如果存在 $CODE_QUALITY_DISABLED CI/CD 变量,则 code_quality 作业不会运行。有关如何定义变量的更多信息,请参阅极狐GitLab CI/CD 变量

要禁用 Code Quality,请创建一个名为 CODE_QUALITY_DISABLED 的自定义 CI/CD 变量,用于:

自定义扫描设置

您可以使用 .gitlab-ci.yml 中的 CI/CD 变量,更改 Code Quality 扫描设置。

配置 Code Quality 作业:

  1. 在包含模板后,声明一个与 Code Quality 作业同名的作业。
  2. 在作业中指定附加键。

有关示例,请参阅下载 JSON 格式的输出

可用的 CI/CD 变量

您可以通过定义可用的 CI/CD 变量来自定义 Code Quality:

CI/CD 变量 描述
SOURCE_CODE 要扫描的源代码的路径。
TIMEOUT_SECONDS codeclimate analyze 命令的自定义超时。
CODECLIMATE_DEBUG 设置启用 Code Climate debug 模式
CODECLIMATE_DEV 设置为启用 --dev 模式,该模式允许您运行 CLI 未知的引擎。
REPORT_STDOUT 设置将报告打印到 STDOUT,而不是生成通常的报告文件。
REPORT_FORMAT 设置控制生成的报告文件的格式。例如:json\|html
ENGINE_MEMORY_LIMIT_BYTES 设置引擎的内存限制,默认为 1,024,000,000 字节。
CODE_QUALITY_DISABLED 阻止 Code Quality 作业运行。
CODECLIMATE_PREFIX 设置前缀以用于 CodeClimate 引擎中的所有 docker pull 命令,适用于离线扫描

输出

Code Quality 会创建一个名为 gl-code-quality-report.json 的文件。此文件的内容在内部处理,结果显示在 UI 中。要查看原始结果,您可以配置 Code Quality 作业允许下载此文件。格式选项是 JSON 格式、HTML 格式或两者都有。使用 HTML 格式以更易于阅读的格式查看报告。例如,您可以在 Pages 上发布 HTML 格式文件,以便更轻松地查看。

下载 JSON 格式的输出

为了能够下载 JSON 格式的代码质量报告,请将 gl-code-quality-report.json 文件声明为 code_quality 作业的产物:

include:
  - template: Code-Quality.gitlab-ci.yml

code_quality:
  artifacts:
    paths: [gl-code-quality-report.json]

完整的 JSON 文件可作为 code_quality 作业的可下载产物使用。

下载 JSON 和 HTML 格式的输出

HTML 报告格式引入于 13.6 版本。

note 要创建 HTML 格式文件,Code Quality 作业必须运行两次,每种格式一次。 在此配置中,创建了 JSON 格式文件,但仅在内部处理。

要能够以 JSON 和 HTML 格式下载 Code Quality 报告,请使用 extends: code_quality 向您的模板添加另一个作业:

include:
  - template: Code-Quality.gitlab-ci.yml

code_quality_html:
  extends: code_quality
  variables:
    REPORT_FORMAT: html
  artifacts:
    paths: [gl-code-quality-report.html]

JSON 和 HTML 文件都可以作为 code_quality 作业的可下载产物使用。

仅以 HTML 格式下载输出

要仅下载 HTML 格式文件的 Code Quality 报告,请在现有作业中将 REPORT_FORMAT 设置为 html

note 此操作不会创建 JSON 格式文件,因此 Code Quality 结果不会显示在合并请求部件、流水线报告或变更视图中。
include:
  - template: Code-Quality.gitlab-ci.yml

code_quality:
  variables:
    REPORT_FORMAT: html
  artifacts:
    paths: [gl-code-quality-report.html]

HTML 文件可作为 code_quality 作业的可下载产物

将 Code Quality 与合并请求流水线一起使用

默认 Code Quality 配置不允许 code_quality 作业在合并请求流水线上运行。

要使 Code Quality 能够在合并请求流水线上运行,请覆盖代码质量 rulesworkflow: rules,以便它们与您当前的rules 相匹配。

例如:

include:
  - template: Code-Quality.gitlab-ci.yml

code_quality:
  rules:
    - if: $CODE_QUALITY_DISABLED
      when: never
    - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Run code quality job in merge request pipelines
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH      # Run code quality job in pipelines on the default branch (but not in other branch pipelines)
    - if: $CI_COMMIT_TAG                               # Run code quality job in pipelines for tags

使用私有容器镜像库

引入于 13.7 版本

使用私有容器镜像仓库可以减少下载镜像的时间,也可以减少外部依赖。由于容器执行的嵌套架构,镜像库前缀必须专门配置为向下传递到 CodeClimate 的后续单个 engine 的 docker pull 命令中。

以下变量可以解决所有必需的镜像拉取:

  • CODE_QUALITY_IMAGE:一个完全前缀的镜像名称,可以位于从您的工作环境访问的任何位置。GitLab Container Registry 可用于托管您自己的副本。
  • CODECLIMATE_PREFIX:您预期的容器镜像库的域名,这是 CodeClimate CLI 支持的配置选项。您必须:
    • 包括尾部斜杠 (/)。
    • 不包括协议前缀,例如 https://
  • CODECLIMATE_REGISTRY_USERNAME:一个可选变量,用于指定从 CODECLIMATE_PREFIX 解析的镜像库域名的用户名。
  • CODECLIMATE_REGISTRY_PASSWORD:一个可选变量,用于指定从 CODECLIMATE_PREFIX 解析的镜像库域名的密码。
include:
  - template: Code-Quality.gitlab-ci.yml

code_quality:
  variables:
    CODE_QUALITY_IMAGE: "my-private-registry.local:12345/codequality:0.85.24"
    CODECLIMATE_PREFIX: "my-private-registry.local:12345/"

此示例特定于 Code Quality。有关如何使用镜像库镜像配置 DinD 的更多一般说明,请参阅相关文档

必需的镜像

默认的 .codeclimate.yml 需要以下镜像:

  • codeclimate/codeclimate-structure:latest
  • codeclimate/codeclimate-csslint:latest
  • codeclimate/codeclimate-coffeelint:latest
  • codeclimate/codeclimate-duplication:latest
  • codeclimate/codeclimate-eslint:latest
  • codeclimate/codeclimate-fixme:latest
  • codeclimate/codeclimate-rubocop:rubocop-0-92

如果您使用自定义的 .codeclimate.yml 配置文件,则必须在私有容器镜像库中添加指定的插件。

使用经身份验证的 DockerHub

您可以使用 DockerHub 作为 Code Quality 镜像的替代来源。

先决条件:

要使用 DockerHub,请在 .gitlab-ci.yml 文件中配置以下变量:

  • CODECLIMATE_PREFIX
  • CODECLIMATE_REGISTRY_USERNAME
  • CODECLIMATE_REGISTRY_PASSWORD

示例:

include:
  - template: Jobs/Code-Quality.gitlab-ci.yml

code_quality:
  variables:
    CODECLIMATE_PREFIX: "registry-1.docker.io/"
    CODECLIMATE_REGISTRY_USERNAME: $DOCKERHUB_USERNAME
    CODECLIMATE_REGISTRY_PASSWORD: $DOCKERHUB_PASSWORD

使用 Dependency Proxy

您可以使用 Dependency Proxy 来减少下载依赖项所花费的时间。

先决条件:

要引用 Dependency Proxy,请在 .gitlab-ci.yml 文件中配置以下变量:

  • CODE_QUALITY_IMAGE
  • CODECLIMATE_PREFIX
  • CODECLIMATE_REGISTRY_USERNAME
  • CODECLIMATE_REGISTRY_PASSWORD

例如:

include:
  - template: Code-Quality.gitlab-ci.yml

code_quality:
  variables:
    ## You must add a trailing slash to `$CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX`.
    CODECLIMATE_PREFIX: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/
    CODECLIMATE_REGISTRY_USERNAME: $CI_DEPENDENCY_PROXY_USER
    CODECLIMATE_REGISTRY_PASSWORD: $CI_DEPENDENCY_PROXY_PASSWORD

使用自定义工具

您可以将自定义工具集成到极狐GitLab 中,提供 Code Quality 报告。

Code Quality 报告产物 JSON 文件必须包含具有以下属性的对象数组:

名称 描述
description 代码质量违规的描述。
fingerprint 用于识别代码质量违规的唯一指纹。例如,MD5 哈希。
severity 严重性字符串(可以是 infominormajorcriticalblocker)。
location.path 包含代码质量违规的文件的相对路径。
location.lines.begin or location.positions.begin.line 发生代码质量违规的行。
note 尽管 Code Climate 规范支持更多属性,但极狐GitLab 会忽略这些属性。极狐GitLab 解析器不允许在文件开头使用字节顺序标记。

要使用自定义 Code Quality 工具:

  1. 在生成 Code Quality 报告产物.gitlab-ci.yml 文件中定义一个作业。
  2. 配置工具,将 Code Quality 报告产物生成为 JSON 文件,该文件实现了 Code Climate 规范

示例:

[
  {
    "description": "'unused' is assigned a value but never used.",
    "fingerprint": "7815696ecbf1c96e6894b779456d330e",
    "severity": "minor",
    "location": {
      "path": "lib/index.js",
      "lines": {
        "begin": 42
      }
    }
  }
]

使用分析插件

可以使用 Code Climate 分析插件 扩展 Code Quality 功能。

例如,要使用 SonarJava 分析器

  1. 将名为 .codeclimate.yml 的文件添加到仓库的根目录。
  2. 将插件的 enablement code 添加到仓库根目录的 .codeclimate.yml 中:
  version: "2"
  plugins:
    sonar-java:
      enabled: true

这样会将 SonarJava 添加到包含在您的项目中的默认 .codeclimate.ymlplugins: 部分。

plugins: 部分的更改不会影响默认 .codeclimate.ymlexclude_patterns 部分。有关详细信息,请参阅[排除文件和文件夹] (https://docs.codeclimate.com/docs/exclude-files-and-folders)的 Code Climate 文档。

故障排除

更改默认配置无效

一个常见的问题是术语 Code QualityCode Climate(使用的引擎)非常相似。您必须添加 .codeclimate.yml 文件来更改默认配置,不是 .codequality.yml 文件。如果您使用了错误的文件名,仍使用默认的 .codeclimate.yml

合并请求中不显示 Code Quality 报告

这可能是由于多种原因:

  • 您刚刚在 .gitlab-ci.yml 中添加了 Code Quality 作业。该报告还没有任何可比较的内容,因此无法显示任何信息。它仅在将来的合并请求有可比较的内容后显示。
  • 您的流水线未设置为在目标分支上运行代码质量作业。如果目标分支没有生成报告,则您的 MR 分支报告没有可比性。在这种情况下,您将看到一条错误消息,指出 Base pipeline codequality artifact not found
  • artifacts:expire_in CI/CD 设置可能导致 Code Quality 产物比预期的更快过期。
  • 小部件使用最新提交到目标分支的流水线。如果提交到不运行代码质量作业的默认分支,可能会导致合并请求小部件没有用于比较的基本报告。
  • 如果使用 REPORT_STDOUT 环境变量,则不会生成报告文件,合并请求中也不会显示任何内容。

仅显示一个 Code Quality 报告,但定义了更多

从 15.7 版本开始,Code Quality 结合流水线中所有作业的结果。

在以前的版本中,极狐GitLab 仅使用最新创建的作业(具有最大的作业 ID)中的 Code Quality 产物。 如果流水线中的多个作业生成 Code Quality 产物,则忽略较早作业的 Code Quality 产物。

为避免混淆,请仅配置一项作业生成 gl-code-quality-report.json 文件。

RuboCop 错误

在 Ruby 项目上使用 Code Quality 作业时,您可能会遇到运行 RuboCop 的问题。 例如,使用非常新或非常旧版本的 Ruby 时可能会出现以下错误:

/usr/local/bundle/gems/rubocop-0.52.1/lib/rubocop/config.rb:510:in `check_target_ruby':
Unknown Ruby version 2.7 found in `.ruby-version`. (RuboCop::ValidationError)
Supported versions: 2.1, 2.2, 2.3, 2.4, 2.5

这是由于检查引擎使用的默认 RuboCop 版本不包括对正在使用的 Ruby 版本的支持。

要使用支持项目使用的 Ruby 版本的自定义版本的 RuboCop,您可以通过在项目仓库中创建 .codeclimate.yml 文件覆盖配置。

例如,要指定使用 RuboCop 版本 0.67

version: "2"
plugins:
  rubocop:
    enabled: true
    channel: rubocop-0-67

使用自定义工具时,合并请求上不显示 Code Quality

如果您的合并请求在使用自定义工具时未显示任何 Code Quality 更改,请确保 line 属性是 integer

错误:Could not analyze code quality

您可能会遇到以下错误:

error: (CC::CLI::Analyze::EngineFailure) engine pmd ran for 900 seconds and was killed
Could not analyze code quality for the repository at /code

如果您启用了任何 Code Climate 插件,并且 Code Quality CI/CD 作业失败并显示此错误消息,则该作业可能需要比默认超时 900 秒更长的时间。

要解决此问题,请在 .gitlab.-ci.yml 文件中将 TIMEOUT_SECONDS 设置为更高的值。

例如:

variables:
  TIMEOUT_SECONDS: 3600

将 Code Quality 与 Kubernetes CI 执行器一起使用

Code Quality 需要 Docker in Docker 设置才能工作。Kubernetes 执行器已经对此提供支持

为确保 Code Quality 作业可以在 Kubernetes 执行器上运行:

错误:x509: certificate signed by unknown authority

如果将 CODE_QUALITY_IMAGE 设置为托管在 Docker 镜像库中的镜像,该镜像使用不受信任的 TLS 证书(例如自签名证书),您会看到如下所示的错误:

$ docker pull --quiet "$CODE_QUALITY_IMAGE"
Error response from daemon: Get https://gitlab.example.com/v2/: x509: certificate signed by unknown authority

要解决此问题,请将 Docker daemon 配置为信任证书,方法是将证书放入 /etc/docker/certs.d 目录中。

此 Docker daemon 暴露给极狐GitLab Code Quality 模板中的后续 Code Quality Docker 容器,并且应该暴露您希望在其中应用证书配置的任何其他容器。

Docker

如果您有权访问极狐GitLab Runner 配置,请将目录添加为卷挂载

gitlab.example.com 替换为镜像库的实际域名。

示例:

[[runners]]
  ...
  executor = "docker"
  [runners.docker]
    ...
    privileged = true
    volumes = ["/cache", "/etc/gitlab-runner/certs/gitlab.example.com.crt:/etc/docker/certs.d/gitlab.example.com/ca.crt:ro"]

Kubernetes

如果您有权访问极狐GitLab Runner 配置和 Kubernetes 集群,则可以挂载 ConfigMap

gitlab.example.com 替换为镜像库的实际域名。

  1. 使用证书创建 ConfigMap:

    kubectl create configmap registry-crt --namespace gitlab-runner --from-file /etc/gitlab-runner/certs/gitlab.example.com.crt
    
  2. 更新极狐GitLab Runner config.toml 指定 ConfigMap:

    [[runners]]
      ...
      executor = "kubernetes"
      [runners.kubernetes]
        image = "alpine:3.12"
        privileged = true
        [[runners.kubernetes.volumes.config_map]]
          name = "registry-crt"
          mount_path = "/etc/docker/certs.d/gitlab.example.com/ca.crt"
          sub_path = "gitlab.example.com.crt"