自动化 DevOps 使用 Codeclimate 执行代码质量分析

目录

1、Codeclimate 介绍

Codeclimate 是为代码质量分析平台提供的一个命令行接口工具,通过它可以在本机 Docker 容器中对要分析的代码执行质量分析,并生成分析报告。我们熟知常用的代码质量检测工具例如 SonarQube、CheckStyle 等等,而 Codeclimate 是这些各种代码类型质量分析工具的集合,而且支持我们自定义检测工具,命令行简单,非常方便操作。我们可以使用 Codeclimate 进行代码质量分析,并将其作为持续集成流程中的一个环节,是很有必要的。

2、环境、软件准备

本次演示环境,我是在本机 Mac OX 上操作,以下是安装的软件及版本:

  1. Docker:version 17.03.1-ce
  2. Codeclimate:version 0.71.2

注意:这里 Codeclimate 是需要依赖本地 Docker 容器来运行执行代码分析的,所以需要提前安装好 Docker, 这里忽略 Docker 的安装过程。

3、Codeclimate 安装

Codeclimate 的安装很简单,如果本机安装了 Docker,那么最简单的安装方式就是下载 Codeclimate 镜像就可以直接运行了。

$ docker pull codeclimate/codeclimate

$ docker run \
>   --interactive --tty --rm \
>   --env CODECLIMATE_CODE="$PWD" \
>   --volume "$PWD":/code \
>   --volume /var/run/docker.sock:/var/run/docker.sock \
>   --volume /tmp/cc:/tmp/cc \
>   codeclimate/codeclimate help
Usage: codeclimate COMMAND ...

Available commands:
    analyze [-f format] [-e engine[:channel]] [path]    Run analysis with the given arguments
    console                                             Open a ruby console for the CLI. Useful for developing against the CLI.
    engines:install                                     Pull the latest images for enabled engines in your configuration
    engines:list                                        List all available engines
    help [command]                                      Display help information.
    prepare [--allow-internal-ips]                      Run the commands in your prepare step.
    validate-config                                     Validate your .codeclimate.yml or .codeclimate.json.
    version                                             Display the CLI version.

这样就使用 Codeclimate 运行了 help 命令,我们可以看到打印出来的 Codeclimate 帮助文档。当然,这样操作会觉得比较麻烦,不太方便,我们还可以通过另外几种方式安装到机器上。

  • brew 安装
# 安装
brew tap codeclimate/formulae
brew install codeclimate
# 更新升级
brew update
brew upgrade codeclimate
  • 二进制编译安装
curl -L https://github.com/codeclimate/codeclimate/archive/master.tar.gz | tar xvz
cd codeclimate-* && sudo make install

安装完毕之后,通过命令行 codeclimate help 即可查看命令行帮助文档。

4、Codeclimate 基本命令使用

Codeclimate 是一个命令行工具集,通过 codeclimate help 命令可以列举出 Codeclimate 所有的可用命令,下边针对这些命令简单的说明一下。

$ codeclimate help
Usage: codeclimate COMMAND ...

Available commands:
    analyze [-f format] [-e engine[:channel]] [path]    Run analysis with the given arguments
    console                                             Open a ruby console for the CLI. Useful for developing against the CLI.
    engines:install                                     Pull the latest images for enabled engines in your configuration
    engines:list                                        List all available engines
    help [command]                                      Display help information.
    prepare [--allow-internal-ips]                      Run the commands in your prepare step.
    validate-config                                     Validate your .codeclimate.yml or .codeclimate.json.
    version                                             Display the CLI version.
  • analyze 该命令会在当前目录下,执行代码分析。注意这里存在一个配置文件 .codeclimate.yml,该文件是配置 Codeclimate 执行本次分析所设置的所有引擎列表,待会下边我会讲该如何使用该配置文件。它还有几个可选参数 -f(format) 表示设置本次分析结果输出格式,它支持(jsontexthtml)三种格式输出。-e 表示本次执行使用哪种分析引擎,例如 -e checkstyle 则表示本次使用 CheckStyle 引擎来执行分析。-dev 表示以开发模式进行调试,当我们使用自定义引擎来测试时,可以使用。另外一个很重要的参数 exclude_paths,表示排除某些目录不进行分析,默认会遍历当前所有目录。
  • console 该命令会开启一个交互式会话,来提供对 CLI 内部 Class 的访问,对开发人员比较有用。
  • engines:install 该命令会比较配置文件 .codeclimate.yml 中的引擎配置,来更新已经安装的引擎镜像到最新版,同时拉取本地未安装的引擎镜像到本地。
  • engines:list 该命令会打印出所有可用的引擎列表,可以从 CodeClimate Docker Hub 中查看各个引擎镜像列表。
  • validate-config 该命令会验证 .codeclimate.yml 配置文件是否有问题。
  • version 该命令查看当前 Codeclimate 版本信息。

好了,简单介绍了一下 Codeclimate 的基本命令,接下来我们来使用一下该命令行来执行代码分析吧!

首选我们创建一个测试的文件夹,生成一个 PHP 类型代码文件,使用命令行对其进行代码分析。

$ mkdir test
$ cd test
$ cat test.php
<?php

/**
 * 首页
 */

class MobileController extends AbstractController {

    public $authorize = self::MAYBE_LOGIN;
    public $init_viewer = true;

    public function indexAction() {
        $page = new Page_Mobile_Home();
        $this->render_page($page);

    }
}

# 使用 json 输出方式,使用 phpmd 引擎来执行分析
$ codeclimate analyze -f json -e phpmd
[{"type":"issue","check_name":"Controversial/CamelCasePropertyName","description":"The property $init_viewer is not named in camelCase.","categories":["Style"],"remediation_points":500000,"location":{"path":"test.php","lines":{"begin":8,"end":18}},"content":{"body":"\nSince: PHPMD 0.2\n\nIt is considered best practice to use the camelCase notation to name attributes.\n\n\nExample:\n\n```php\n\n  class ClassName {\n      protected $property_name;\n  }\n\n\n```\n\nSource: http://phpmd.org/rules/controversial.txt"},"fingerprint":"56027498261b4b1ca168bb3fe849c290","engine_name":"phpmd","severity":"minor"}]

可以看到,已经生成了 json 格式的检测结果,不过不太直观查看输出结果,我们可以使用 html 格式输出结果,并生成到当前目录指定文件 result.html 中,然后通过浏览器访问即可。

$ codeclimate analyze -f html -e phpmd > result.html

浏览器打开 result.html 文件,我们可以清晰的看到分析结果。
这里写图片描述

当然,不同的引擎检查结果有而不太一样,例如同样的 PHP 代码,我们换另一个引擎 phan 来分析看下。

$ codeclimate analyze -f html -e phan > result_phan.html

这里写图片描述

我们发现,分析的结果条目增多了,说明不同的引擎执行分析的规则不一样,导致检测的结果也不一样了,实际应用中,我们可以选择某一个分析比较全的引擎,或者是选择多个引擎分析,获取多个检测结果,待会下边会讲到。

上边我们讲到 Codeclimate 使用本机 Docker 容器对当前目录代码执行质量分析的,我们可以验证一下是否如此,我们在执行上述命令的时候,可以在新开客户端窗口中执行 docker ps 命令查看是否有对应容器运行。

$ docker ps
CONTAINER ID        IMAGE                     COMMAND                  CREATED                  STATUS                  PORTS                                              NAMES
65282e7c8857        codeclimate/codeclimate   "/usr/src/app/bin/co…"   Less than a second ago   Up Less than a second                                                      trusting_mestorf

$ docker images
REPOSITORY                             TAG                 IMAGE ID            CREATED             SIZE
codeclimate/codeclimate                latest              bc2aa56b8520        2 weeks ago         97.7MB
codeclimate/codeclimate-phan           latest              045ea1dac22d        4 months ago        70.9MB
codeclimate/codeclimate-phpmd          latest              9d7a53405aa0        11 months ago       37MB

我们可以看到,确实是有运行本机 Docker 容器中,而且分析完毕后,容器自动销毁。如果我们不太清楚 Codeclimate 支持那些可用引擎的话,可以使用命令行 codeclimate engines:list 查看。

$ codeclimate engines:list
Available engines:
- apexmetrics: ApexMetrics is a static code analysis tool for Salesforce.com Apex.
- brakeman: A static analysis tool which checks Ruby on Rails applications for security vulnerabilities.
- bundler-audit: Patch-level verification for Bundler.
- checkstyle: Helps programmers write Java that adheres to a coding standard.
- codescan: A static analysis tool for Salesforce.com Apex, Visual Force, Aura and Lightning.
- coffeelint: A style checker for CoffeeScript.
- credo: A static code analysis tool for the Elixir language with a focus on code consistency and teaching.
- csslint: Automated linting of Cascading Stylesheets.
- duplication: Structural duplication detection for Ruby, Python, Java, JavaScript, and PHP.
- eslint: A JavaScript/JSX linting utility.
- fixme: Finds FIXME, TODO, HACK, etc. comments.
- flog: Easy to read reporting of complexity/pain for Ruby code.
- foodcritic: Lint tool for Chef cookbooks.
- git-legal: License compliance and compatibility analysis.
- gnu-complexity: Checks complexity of C code.
- gofmt: Checks the formatting of Go programs.
- golint: A linter for Go.
- govet: Reports suspicious constructs in Go programs.
- grep: Detects specified patterns in files.
- haml-lint: A tool for writing clean and consistent HAML.
- haxe-checkstyle: Checkstyle is a development library to help developers write Haxe code that adheres to a coding standard.
- hlint: A linter for Haskell programs.
- kibit: Static code analyzer for Clojure, ClojureScript, cljx and other Clojure variants.
- markdownlint: Flags style issues within Markdown files.
- nodesecurity: Security tool for Node.js dependencies.
- pep8: Static analysis tool to check Python code against the style conventions outlined in PEP-8.
- phan: Phan is a static analyzer for PHP.
- phpcodesniffer: Detects violations of a defined set of coding standards in PHP.
- phpmd: A PHP static analysis tool.
- pmd: A source code analyzer for Java.
- proselint: A linter for prose.
- radon: Python tool used to compute Cyclomatic Complexity.
- reek: Reek examines Ruby classes, modules, and methods and reports any code smells it finds.
- requiresafe: Security tool for Node.js dependencies.
- rubocop: A Ruby static code analyzer, based on the community Ruby style guide.
- rubymotion: Rubymotion-specific rubocop checks.
- rustfmt: A tool for formatting Rust code according to style guidelines.
- scss-lint: A configurable tool for writing clean and consistent SCSS.
- shellcheck: A static analysis tool for shell scripts.
- sonar-java: Over 400 checks for bugs, vulnerabilities, and code smells in Java code.
- sonar-php: SonarLint for PHP.
- sonar-python: SonarLint for Python.
- structure: Performs structural checks on code.
- stylelint: A mighty, modern CSS linter.
- swiftlint: A tool to enforce Swift style and conventions.
- tailor: Cross-platform static analyzer and linter for Swift.
- tslint: An extensible linter for the TypeScript language
- vint: Fast and Highly Extensible Vim script Language Lint implemented by Python.
- watson: A young Ember Doctor to help you fix your code.

可以从支持的列表中选择对应代码语言的检测引擎,例如针对 Java 语言,可使用 checkstyle、duplication、pmd、sonar-java 这几个引擎。

5、Codeclimate 高级使用

上边提到过,对于包含了多种类型语言代码的项目,例如:Java、Html、CSS、JS等等 如果要执行全面的质量分析,那么就需要指定多个引擎来分析了,上边的基本使用中,我们使用命令行 -e 参数指定了一种类型来执行分析,可以使用 .codeclimate.yml 配置文件来指定引擎来分析。我们先看下该配置文件的写法。

$ cat .codeclimate.yml
version: "1"
plugins:
  phpmd:
    enabled: false
  phan:
    enabled: true
  shellcheck:
    enabled: true

该配置文件定义了三个引擎 phpmd、phan、shellcheck 并且关闭 shellcheck 引擎检测,意味着使用该配置文件执行代码分析时,会只执行 phan、shellcheck 引擎检测。此时我们通过命令行执行 codeclimate analyze -f html > result_yml.html 即可完成检测。为了方便演示,我们增加一个 test.sh 和一个 Test.java 文件到当前目录。

$ cat test.sh
#!/bin/bash

name="This is shell test."
echo "name=${name}"

if [ -z "${version}" ]; then
    echo "version is empty, exit"
    exit 1
fi

$ cat Test.java
package test.hwy;

public class Test {

    public static String getSameEndChart(String[] args){
        String result = "";
        if(args.length > 1){
            int args_length = args.length;
            String first = args[0];
            int first_length = first.length();
            for(int j=1;j <= first_length;j++){
                String a = first.substring(first_length-j, first_length);
                for(int i=1;i < args_length;i++){
                    String b = args[i];
                    int b_length = b.length();
                    if(b_length >= j){
                        String c = b.substring(b_length-j, b_length);
                        if(a.equals(c)){
                            result = a;
                        }else{
                            System.out.println("args 第" + (i+1) + "个字符串尾数字符串"+c+"不匹配首字符串尾字符"+a);
                            result = first.substring(first_length-j+1, first_length);
                            return result;
                        }
                    }else{
                        System.out.println("args 第" + (i+1) + "个字符串长度不够,忽略比较。");
                        result = first.substring(first_length-j+1, first_length);
                        return result;
                    }
                }
            }
        }
        return result;
    }

    public static void main(String[] args) {
        String[] ss = {"123456", "14456", "00123456", "456"};
        System.out.println(getSameEndChart(ss));
    }
}

$ codeclimate analyze -f html > result_yml.html

我们来看下 result_yml.html 文件是否执行了配置的引擎分析,从页面可以明显的看到,Engine 下拉框中有三种引擎可选择 phan、shellcheck、structure,而且选择对应的 Engine 可以切换显示该引擎对应的检测结果。
这里写图片描述

这里写图片描述

这里会有人问了,为什么我没有配置 structure 但是却执行了该引擎分析呢?这里要说明一下,当我们第一次执行上边命令行是,会提示响应超时失败,这是因为它需要拉取该引擎对应的镜像需要花些时间,而且默认会拉取 codeclimate/codeclimate-duplicationcodeclimate/codeclimate-structure 这两个镜像,这两个镜像都挺大的,导致拉取时间超时。此时我们可以通过命令行 codeclimate engines:install 执行安装,安装完毕后,就可以执行上边命令行了。

$ codeclimate engines:install
Pulling docker images.
latest: Pulling from codeclimate/codeclimate-structure
2a72cbf407d6: Already exists
a3ed95caeb02: Pulling fs layer
......
Digest: sha256:b6ee14587a178b1e462202779579affd9186e2be8ca94b141f3c09a3c8862b71
Status: Downloaded newer image for codeclimate/codeclimate-structure:latest
latest: Pulling from codeclimate/codeclimate-duplication
2a72cbf407d6: Already exists
a3ed95caeb02: Pulling fs layer
......
Digest: sha256:a2355a74fb4134b526716a3416b9e841cebbadcfe72f240308686c5ebf424171
Status: Downloaded newer image for codeclimate/codeclimate-duplication:latest
latest: Pulling from codeclimate/codeclimate-phpmd
244d757dc677: Already exists
......
Digest: sha256:799d7eb629cfad2ee35a3f0e8a45fda34edf40bd92a43b0f06ac5505ca81ffc6
Status: Image is up to date for codeclimate/codeclimate-phpmd:latest
latest: Pulling from codeclimate/codeclimate-phan
1160f4abea84: Already exists
......
Status: Image is up to date for codeclimate/codeclimate-phan:latest
latest: Pulling from codeclimate/codeclimate-shellcheck
c19324d1d971: Already exists

$ docker images
REPOSITORY                             TAG                 IMAGE ID            CREATED             SIZE
codeclimate/codeclimate-duplication    latest              a864651fe3d2        7 days ago          2.36GB
codeclimate/codeclimate-structure      latest              d12a28ef9ccc        8 days ago          2.35GB
codeclimate/codeclimate                latest              bc2aa56b8520        2 weeks ago         97.7MB
codeclimate/codeclimate-phan           latest              045ea1dac22d        4 months ago        70.9MB
codeclimate/codeclimate-shellcheck     latest              c46113b2195f        5 months ago        57.8MB
codeclimate/codeclimate-phpmd          latest              9d7a53405aa0        11 months ago       37MB

而且从上边 codeclimate engines:list 命令行显示的引擎列表说明可以得到如下信息:

- duplication: Structural duplication detection for Ruby, Python, Java, JavaScript, and PHP.
- structure: Performs structural checks on code.

该引擎是对代码结构执行结构检测用的,如果我们不想使用该插件,可以在配置文件中设置该插件不开启 enabled: false 即可。

好了,如果现在我们需要针对某些目录或者文件不执行检测,该如何配置呢?Codeclimate 也是可以配置的,只需要在 .codeclimate.yml 配置文件中配置 exclude_paths 即可,接下来在当前目录增加一个 a.sh,同时增加一个 others 文件下,在该文件夹下新增 a.php 文件。

$ mkdir others
$ cat others/a.php
<?php
abc;
$array = array(
    "foo" => "bar",
    42    => 24
    "multi" => array(
         "dimensional" => array(
             "array" => "foo"
         )
    )
);

var_dump($array["foo"][]);
var_dump($array[43]);
var_dump($array["multi"]["dimensional"]["array"]);

$ cat a.sh
#!/bin/bash

#./codeclimate.sh > ./result.html

echo $name
codeclimate analyze -f html -e phan

OK 为了方便对比结果,在修改 .codeclimate.yml 配置文件之前,我们先执行本次分析看下输出的结果如何吧!
这里写图片描述

这里写图片描述

接下来我们修改下 .codeclimate.yml 配置文件,增加 exclude_paths 配置,排除 others/a.php 和 当前目录 a.sh 文件。

version: "1"
plugins:
  phpmd:
    enabled: false
  structure:
    enabled: false
  phan:
    enabled: true
    exclude_paths:
      - others/a.php
  shellcheck:
    enabled: true
    exclude_paths:
      - a.sh

再次执行分析命令 codeclimate analyze -f html > result_yml_new.html,查看本次生成的结果页面是否排除了对上述文件的分析吧。
这里写图片描述

这里写图片描述

妥妥的排除在外了。当然,这样针对某些引擎过滤某些文件或者路径固然是好,但是当要排除的文件过多时,或者说某些目录对所有的引擎都排除在外,不进行分析时,就不太方便啦!Codeclimate 当然也是支持这种方式的,也是修改 .codeclimate.yml 配置文件,增加 exclude_patterns 项配置即可。

version: "1"
plugins:
  phpmd:
    enabled: false
  ......
exclude_patterns:
  - others/
  - exclude_dir/**/*
  - exclude_another_dir/**/*

类似如上配置即可过滤指定目录,这里我就不在演示了。

6、Auto DevOps 流程使用 Codeclimate

我们知道在自动化开发运维流程中,或者是持续集成流程中,对代码执行质量检测分析,是非常有必要的一步,它可以有效避免由于误操作而导致的代码问题,可以持续改善程序猿代码风格和水平,同时能够在上线前及时发现隐藏的问题,降低由于代码问题导致的线上故障,总之,好处多多。那么这里我简单介绍一下两种方式,在自动化 DevOps 流程中使用 Codeclimate 来进行代码质量分析。

方式一:在持续集成流程中使用 Codeclimate + git 方式对代码进行全量或增量质量分析

此方案,通过在持续集成流程中构建完毕,新增一个质量分析节点,来完成对本次上线代码的全量或者增量分析。全量代码分析很简单,只需要 git checout 到指定 branch | tag 即可,对该项目下所有路径使用 Codeclimate 执行代码分析,生成 Html | Json 格式的检测结果,同时反馈到前端页面展示即可。但是对于代码量比较大的项目,执行一次全量会比较费时间,也不太方便有针对性的查看本次上线的代码分析,此时可以选择增量代码分析,意思就是只针对本次上线的代码执行分析即可,这里就需要使用到 git archive 命令检出上线增量包,然后使用 Codeclimate 执行代码分析,这里举个例子。

# 例如线上版本为 v1.0.0 本次上线版本 v1.0.1,对本次上线增量文件执行检测,以 qd_api 为例。
$ git diff --name-only v1.0.0 v1.0.1
src/main/java/com/sina/qd/controller/MachineController.java
src/main/java/com/sina/qd/controller/PlatformTransferService.java
src/main/java/com/sina/qd/controller/ProjectInstanceController.java
src/main/java/com/sina/qd/utils/HttpClientUtil.java

# 使用 git archive 命令打包输出两个版本间的改变增量归档
# 大致的命令格式:git archive -o <path>/<filename.filetype> xxx(新提交 commit_id | tag) $(git diff --name-only yyy(旧提交 commit_id | tag) xxx) 
$ git archive -o /data0/latest.tar.gz v1.0.1 $(git diff --name-only v1.0.0 v1.0.1)

$ tar -zxvf /data0/latest.tar.gz -C /data0/latest
$ tree /data0/latest
latest
└── src
    └── main
        └── java
            └── com
                └── sina
                    └── qd
                        ├── controller
                        │   ├── MachineController.java
                        │   ├── PlatformTransferService.java
                        │   └── ProjectInstanceController.java
                        └── utils
                            └── HttpClientUtil.java

8 directories, 4 files

# 执行代码检测
$ cd /data0/latest
$ codeclimate analyze -f html -e sonar-java > result.html

这里写图片描述

这里简单演示了一下核心操作,实际操作中,可以更加丰富一下,比如流程开始前,可以选择全量 | 增量检测、勾线检测引擎来执行分析、选择输出的格式等等,通过这些勾选参数,我们可以通过模板生成一个 ..codeclimate.yml 配置文件执行代码分析等等

方式二:可以通过 GitLab CI 方式运行代码检测,会将检测结果自动上传并展示到 GitLab。

此方案,是 GitLab 新版本默认支持的方式,我们只需要修改配置 .gitlab-ci.yml 增加 Codequality Job 即可完成代码检测,前提是配置的 ci-runner 运行环境支持 docker。

$ cat .gitlab-ci.yml
...
codequality:
  image: docker:stable
  variables:
    DOCKER_DRIVER: overlay2
  allow_failure: true
  services:
    - docker:stable-dind
  script:
    - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
    - docker run
        --env SOURCE_CODE="$PWD"
        --volume "$PWD":/code
        --volume /var/run/docker.sock:/var/run/docker.sock
        "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
  artifacts:
    paths: [codeclimate.json]

这个是官网实例配置,会将生成的分析结果 codeclimate.json 并上传到 GitLab,GitLab 会解析该文件并将结果显示到 merge request 页面,用户可以直观看到结果。

参考资料

猜你喜欢

转载自blog.csdn.net/aixiaoyang168/article/details/80014647