Code Quality

为了确保您的项目代码保持简单、可读和易于贡献,您可以使用极狐GitLab CI/CD 来分析您的源代码质量。

例如,当您实施一项功能时,您可以运行 Code Quality 报告来分析您的改进如何影响您的代码质量。您可以使用此信息来确保您的更改正在提高而不是降低性能。

Code Quality:

产品级别功能摘要

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

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

Code Quality 部件

更进一步,如果来自目标分支的报告可用于比较,极狐GitLab 可以在合并请求小部件区域中显示代码质量报告:

Code Quality Widget

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

差异视图中的 Code Quality

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

合并请求中对文件的更改可能会导致合并后代码质量下降。在这些情况下,合并请求的差异视图会在新的代码质量违规行旁边显示一个指示器。例如:

Code Quality MR diff report

示例配置

这个例子展示了如何使用极狐GitLab CI/CD 和 Docker 在您的代码上运行 Code Quality。

在任一配置中,Runner 都必须有足够的磁盘空间来处理生成的代码质量文件。

设置极狐GitLab Runner 后,在 CI 配置中包含 Code Quality 模板

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

上面的示例在您的 CI/CD 流水线中创建了一个 code_quality 作业,它会扫描您的源代码中的代码质量问题。该报告保存为 Code Quality 报告产物,您可以稍后下载和分析。

也可以通过设置 CODE_QUALITY_IMAGE CI/CD 变量来覆盖 Code Quality 镜像的 URL。如果您想锁定特定版本的 Code Quality,或者使用它的一个分支,这将特别有用:

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

code_quality:
  variables:
    CODE_QUALITY_IMAGE: "registry.example.com/codequality-fork:latest"

在 13.4 及更高版本中,您可以覆盖 Code Quality 环境变量:

variables:
  TIMEOUT_SECONDS: 1

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

默认情况下,报告产物不可下载。如果您需要在作业详细信息页面上下载它们,您可以将 gl-code-quality-report.json 添加到产物路径,如下所示:

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

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

包含的 code_quality 作业在 test 阶段运行,因此需要将其包含在您的 CI 配置中,如下所示:

stages:
  - test
note此信息会自动提取并显示在合并请求小部件中。
caution在私有化部署实例上,如果恶意行为者破坏了 Code Quality 作业定义,他们可以在 runner 主机上执行特权 Docker 命令。拥有适当的访问控制策略,通过只允许受信任的参与者访问,来减轻这种攻击向量。

在没有 Docker-in-Docker 的情况下,为 Code Quality 设置私有 runner

可以配置自己的 runner 并避免使用 Docker-in-Docker。您可以使用能大大加快作业执行速度的配置,而无需 runner 以特权模式运行。

此替代配置使用套接字绑定与作业环境共享 Runner 的 Docker 守护程序。请注意,此配置需要考虑很多重要因素,您的用例可能更可取。

  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
    

最终结果是:

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

推荐使用 Docker-in-Docker,而不是暴露 docker.sock

禁用代码质量作业

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

要禁用 code_quality 作业,请将 CODE_QUALITY_DISABLED 添加为自定义 CI/CD 变量。 可以这样做:

  • 对于整个项目
  • 对于单个流水线运行:

    1. 转到 CI/CD > 流水线
    2. 点击 运行流水线
    3. 添加 CODE_QUALITY_DISABLED 作为变量键,使用任意值。

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

Code Quality 模板提供的配置不允许 code_quality 作业在合并请求流水线上运行。

如果启用了合并请求流水线,则必须重新定义 code_quality:rules

该模板具有用于 code quality 作业的这些rules

code_quality:
  rules:
    - if: $CODE_QUALITY_DISABLED
      when: never
    - if: $CI_COMMIT_TAG || $CI_COMMIT_BRANCH

如果您使用合并请求流水线,您的 rules(或 workflow: rules)可能类似于以下示例:

job1:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Run job1 in merge request pipelines
    - if: $CI_COMMIT_BRANCH == "main"                  # Run job1 in pipelines on the main branch (but not in other branch pipelines)
    - if: $CI_COMMIT_TAG                               # Run job1 in pipelines for tags

为了使它们一起工作,您需要覆盖代码质量 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

配置 Code Quality 使用私有容器镜像库

引入于 13.7 版本

为了减少网络时间和外部依赖,您可以使用自己的容器镜像库来托管 Code Quality Docker 镜像。由于容器执行的嵌套架构,镜像库前缀必须专门配置为向下传递到 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: Jobs/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 的更多一般说明,请参阅相关文档

配置 Code Quality 使用依赖代理

先决条件:

以下是如何配置 Code Quality 使用依赖代理的示例:

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

code_quality:
  variables:
    CODE_QUALITY_IMAGE: "$CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/codequality:0.85.24"
    ## 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

配置 Code Quality 使用已身份验证的 Dockerhub

以下是如何配置 Code Quality 以使用带有已身份验证的 Dockerhub 的示例:

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

您应该在项目中将用户名和密码添加为受保护的 CI/CD 变量

实施自定义工具

可以让自定义工具在极狐GitLab 中提供 Code Quality 报告:

  1. 在您的 .gitlab-ci.yml 文件中定义一个生成代码质量报告产物的作业。
  2. 配置您的工具,将 Code Quality 报告产物生成为 JSON 文件,该文件实现 Code Climate spec 的子集。

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

名称 描述
description 代码质量违规的描述。
fingerprint 用于识别代码质量违规的唯一指纹。例如,MD5 哈希。
severity 严重性字符串(可以是 infominormajorcriticalblocker)。
location.path 包含代码质量违规的文件的相对路径。
location.lines.begin or location.positions.begin.line 发生代码质量违规的行。

示例:

[
  {
    "description": "'unused' is assigned a value but never used.",
    "fingerprint": "7815696ecbf1c96e6894b779456d330e",
    "severity": "minor",
    "location": {
      "path": "lib/index.js",
      "lines": {
        "begin": 42
      }
    }
  }
]
note尽管 Code Climate spec 支持更多属性,但系统忽略了这些属性。极狐GitLab parser 不允许在文件开头使用字节顺序标记。

Code Quality 报告

Code Quality Report

在 Code Quality 作业完成之后:

  • Code Quality 的潜在变化直接显示在合并请求中。合并请求中的 Code Quality 部件,比较来自分支的 base 和 head 的报告,然后列出合并分支时解决或创建的任何违规。
  • 完整的 JSON 报告可作为 code_quality 作业的可下载产物获得。
  • 流水线生成的代码质量违规的完整列表,显示在流水线详细信息页面的代码质量选项卡中。

生成 HTML 报告

在 13.6 及更高版本中,可以通过将 REPORT_FORMAT CI/CD 变量设置为 html 来生成 HTML 报告文件。如果您只想以更易于阅读的格式查看报告,或在极狐GitLab Pages 上发布此产物以便更轻松地查看,这将非常有用。

要同时生成 JSON 和 HTML 报告文件,请使用 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]
note添加作业意味着您的代码被扫描两次:一次生成 JSON 报告,一次生成 HTML 报告。

您还可以只生成 HTML 报告,而不是标准的 JSON 报告,要这样做,请在现有作业中将 REPORT_FORMAT 设置为 html

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

code_quality:
  variables:
    REPORT_FORMAT: html
  artifacts:
    paths: [gl-code-quality-report.html]
caution如果您只生成 HTML 报告,则无法在合并请求部件流水线报告差异视图中查看结果。这些功能需要 JSON 报告。

扩展功能

使用分析插件

如果需要扩展 Code Quality 提供的默认功能,可以使用分析插件

例如,要使用 SonarJava 分析器,请添加一个名为 .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 Quality 镜像

如果您将 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 守护进程配置为信任证书,方法是将证书放入 /etc/docker/certs.d 目录。

这个 Docker 守护进程在 Code Quality 模板,并且应该公开您希望在其中应用证书配置的任何其他容器。

Docker

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

[[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"]

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

Kubernetes

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

  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"
    

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

故障排除

更改默认配置无效

一个常见的问题是术语 Code Quality代码气候(使用的引擎)非常相似。您必须添加 .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 环境变量,则不会生成报告文件,合并请求中也不会显示任何内容。
  • 已知大的 gl-code-quality-report.json 文件(尤其是 >10 MB)会阻止显示报告。作为一种解决方法,请尝试删除系统忽略的属性。您可以:
    • 将 Code Quality 工具配置为不输出这些类型。
    • 在作业完成之前,使用 .gitlab-ci.yml 脚本中的 sedawk 或类似命令来编辑 gl-code-quality-report.json

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

极狐GitLab 仅使用来自最新创建的作业(具有最大的作业 ID)的 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

启用 Code Climate 插件的 Code Quality CI 作业失败并出现错误

如果您启用了任何 Code Climate 插件,并且 Code Quality CI 作业失败并出现以下错误,则作业花费的时间可能比默认超时时间 900 秒长:

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

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

例如:

variables:
  TIMEOUT_SECONDS: 3600