目录
- 1、Codeclimate 介绍
- 2、环境、软件准备
- 3、Codeclimate 安装
- 4、Codeclimate 基本命令使用
- 5、Codeclimate 高级使用
- 6、Auto DevOps 流程使用 Codeclimate
1、Codeclimate 介绍
Codeclimate 是为代码质量分析平台提供的一个命令行接口工具,通过它可以在本机 Docker 容器中对要分析的代码执行质量分析,并生成分析报告。我们熟知常用的代码质量检测工具例如 SonarQube、CheckStyle 等等,而 Codeclimate 是这些各种代码类型质量分析工具的集合,而且支持我们自定义检测工具,命令行简单,非常方便操作。我们可以使用 Codeclimate 进行代码质量分析,并将其作为持续集成流程中的一个环节,是很有必要的。
2、环境、软件准备
本次演示环境,我是在本机 Mac OX 上操作,以下是安装的软件及版本:
- Docker:version 17.03.1-ce
- Codeclimate:version 0.71.2
注意:这里 Codeclimate 是需要依赖本地 Docker 容器来运行执行代码分析的,所以需要提前安装好 Docker, 这里忽略 Docker 的安装过程。
3、Codeclimate 安装
Codeclimate 的安装很简单,如果本机安装了 Docker,那么最简单的安装方式就是下载 Codeclimate 镜像就可以直接运行了。
代码语言:javascript复制$ 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)
表示设置本次分析结果输出格式,它支持(json
、text
、html
)三种格式输出。-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 类型代码文件,使用命令行对其进行代码分析。
代码语言:javascript复制$ 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.2nnIt is considered best practice to use the camelCase notation to name attributes.nnnExample:nn```phpnn class ClassName {n protected $property_name;n }nnn```nnSource: http://phpmd.org/rules/controversial.txt"},"fingerprint":"56027498261b4b1ca168bb3fe849c290","engine_name":"phpmd","severity":"minor"}]
可以看到,已经生成了 json 格式的检测结果,不过不太直观查看输出结果,我们可以使用 html 格式输出结果,并生成到当前目录指定文件 result.html 中,然后通过浏览器访问即可。
代码语言:javascript复制$ codeclimate analyze -f html -e phpmd > result.html
浏览器打开 result.html 文件,我们可以清晰的看到分析结果。
当然,不同的引擎检查结果有而不太一样,例如同样的 PHP 代码,我们换另一个引擎 phan 来分析看下。
代码语言:javascript复制$ 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-duplication
和 codeclimate/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 页面,用户可以直观看到结果。
参考资料
- Codeclimate Github
- Codeclimate 官网
- Codeclimate 官网文档
- Codeclimate Docker Hub
- GitLab Doc Code Quality