代码越写越规范是优秀开发者的成长之路,但很多人对老项目感到有心无力,因为太不规范了,所有人停下来一起修复也要花费很长时间,而且一次改动太多难以确保可靠性,怎么办?
有的语言可以借助 Git diff 把本次修改的代码挑出来,实现增量扫描,但 Java 很难这么做。
有的人在持续集成里配置了规范扫描工具,但报错之后需要在成千上万行 log 里查找,降低了研发效率。
Checkstyle 是业界知名的开源扫描工具,可扫描 Sun、Google 等代码规范,提供 Maven、Gradle 插件。本文以 Java 项目配置 Checkstyle 扫描工具为例,分享消灭这些问题的办法:
1. 将代码规范问题显示在「合并请求页面」,大幅度提高研发效率;
2. 增量代码规范报告。
下文分别介绍「Java Maven 项目」和「Java Gradle 项目」的配置方法。
在项目中引入 Checkstyle 插件,并下载代码规范:
$ vi pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<violationSeverity>warning</violationSeverity>
<configLocation>config/checkstyle/checkstyle.xml</configLocation>
</configuration>
</plugin>
$ mkdir -p config/checkstyle/
$ wget https://raw.githubusercontent.com/checkstyle/checkstyle/checkstyle-9.3/src/main/resources/google_checks.xml -O config/checkstyle/checkstyle.xml
执行全量扫描命令,查看效果:
$ ./mvnw checkstyle:check
[WARN] Demo.java:6:1: 缺少 Javadoc 。 [MissingJavadocType]
[WARN] Demo.java:9:1: 行内含有制表符 tab 。 [FileTabCharacter]
[WARN] Demo.java:9:9: 'method def modifier' 缩进了8个缩进符,应为2个。 [Indentation]
在极狐GitLab 持续集成中执行强制扫描:
$ vi .gitlab-ci.yml
checkstyle:
script:
- ./mvnw checkstyle:check
当扫描工具报错,持续集成退出,想看代码规范问题,需要到 log 中查找。很多持续集成产品只做到了这一步,但这降低了开发效率,因此极狐 GitLab 更进一步——采集「代码质量报告」。
在项目中引入 violations-maven-plugin,它会将 Checkstyle 报告转换成极狐 GitLab 标准格式。
$ vi pom.xml
<plugin>
<groupId>se.bjurr.violations</groupId>
<artifactId>violations-maven-plugin</artifactId>
<version>1.50.4</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>violations</goal>
</goals>
<configuration>
<!-- Optional config -->
<!-- 0 is disabled -->
<maxReporterColumnWidth>0</maxReporterColumnWidth>
<maxRuleColumnWidth>0</maxRuleColumnWidth>
<maxSeverityColumnWidth>0</maxSeverityColumnWidth>
<maxLineColumnWidth>0</maxLineColumnWidth>
<maxMessageColumnWidth>30</maxMessageColumnWidth>
<!-- Will create a CodeClimate JSON report. -->
<codeClimateFile>gl-code-quality-report.json</codeClimateFile>
<!-- Global configuration, remove if you dont want to report violations
for the entire repo. -->
<!-- INFO, WARN or ERROR -->
<minSeverity>INFO</minSeverity>
<!-- PER_FILE_COMPACT, COMPACT or VERBOSE -->
<detailLevel>VERBOSE</detailLevel>
<!-- Will fail the build if total number of found violations is higher -->
<maxViolations>99999999</maxViolations>
<!-- Will print violations found in diff -->
<printViolations>true</printViolations>
<!-- Diff configuration, remove if you dont want to report violations
for files changed between specific revisions. -->
<!-- Can be empty (ignored), Git-commit or any Git-reference -->
<diffFrom></diffFrom>
<!-- Same as above -->
<diffTo></diffTo>
<!-- INFO, WARN or ERROR -->
<diffMinSeverity>INFO</diffMinSeverity>
<!-- PER_FILE_COMPACT, COMPACT or VERBOSE -->
<diffDetailLevel>VERBOSE</diffDetailLevel>
<!-- Will fail the build if number of violations, in the diff within
from/to, is higher -->
<diffMaxViolations>99</diffMaxViolations>
<!-- Will print violations found in diff -->
<diffPrintViolations>true</diffPrintViolations>
<!-- Where to look for Git -->
<gitRepo>.</gitRepo>
<!-- This is mandatory regardless of if you want to report violations
between revisions or the entire repo. -->
<violations>
<violation>
<parser>CHECKSTYLE</parser>
<reporter>Checkstyle</reporter>
<folder>.</folder>
<pattern>.*/target/checkstyle-result\.xml$</pattern>
</violation>
</violations>
</configuration>
</execution>
</executions>
</plugin>
在极狐 GitLab CI 中采集代码规范报告:
image: eclipse-temurin:8
cache:
paths:
- /root/.m2
stages:
- lint
- build
checkstyle:
allow_failure: true
stage: lint
script:
- ./mvnw checkstyle:check
artifacts:
when: always
untracked: true
report:
stage: lint
script:
- ./mvnw validate
needs:
- job: checkstyle
artifacts: true
artifacts:
reports:
codequality: gl-code-quality-report.json
compile:
stage: build
script:
- ./mvnw package -Dmaven.test.skip=true
artifacts:
untracked: true
可以看到在开发人员频繁使用的「合并请求」页面,直接显示了「代码规范问题」,供开发人员自助修复以及提醒评审的同事注意,这样可以有效提高研发效率。
老项目第一次配置代码规范可能会出现很多错误(比如上图有 7746 个),没关系,先将规范合并进入主干,下次修改代码发起合并请求时,极狐 GitLab 将展示「增量代码质量报告」,而无需任何复杂设置。比如下图就只有 5 个新问题了:
「Java Gradle 项目」和「Java Maven 项目」的配置方法一致:
在项目中引入 Checkstyle 插件,并下载代码规范:
$ vi build.gradle
plugins {
id 'checkstyle'
}
checkstyle {
toolVersion = '9.3'
maxWarnings = 0
maxErrors = 0
}
$ mkdir -p config/checkstyle/
$ wget https://raw.githubusercontent.com/checkstyle/checkstyle/checkstyle-9.3/src/main/resources/google_checks.xml -O config/checkstyle/checkstyle.xml
执行全量扫描命令,查看效果:
$ ./gradlew check
[WARN] Demo.java:6:1: 缺少 Javadoc 。 [MissingJavadocType]
[WARN] Demo.java:9:1: 行内含有制表符 tab 。 [FileTabCharacter]
[WARN] Demo.java:9:9: 'method def modifier' 缩进了8个缩进符,应为2个。 [Indentation]
在极狐GitLab 持续集成中执行强制扫描:
$ vi .gitlab-ci.yml
checkstyle:
script:
- ./gradlew check
同样,在项目中引入 violations-maven-plugin,它会将 Checkstyle 报告转换成极狐 GitLab 标准格式。
$ vi build.gradle
buildscript {
repositories {
maven { url 'https://plugins.gradle.org/m2/' }
}
dependencies {
classpath "se.bjurr.violations:violations-gradle-plugin:1.52.2"
}
}
task violations(type: se.bjurr.violations.gradle.plugin.ViolationsTask) {
//
// Optional config
//
maxReporterColumnWidth = 0 // 0 means "no limit"
maxRuleColumnWidth = 60
maxSeverityColumnWidth = 0
maxLineColumnWidth = 0
maxMessageColumnWidth = 50
codeClimateFile = file('gl-code-quality-report.json') // Will create a CodeClimate JSON report.
violationsFile = file('violations-file.json') // Will create a normalized JSON report.
//
// Global configuration, remove if you dont want to report violations for
// the entire repo.
//
minSeverity = 'INFO' // INFO, WARN or ERROR
detailLevel = 'VERBOSE' // PER_FILE_COMPACT, COMPACT or VERBOSE
maxViolations = 99999999 // Will fail the build if total number of found violations is higher
printViolations = true // Will print violations found in diff
//
// Diff configuration, remove if you dont want to report violations for
// files changed between specific revisions.
//
// diff-properties can be supplied with something like:
//
// ./gradlew violations -PdiffFrom=e4de20e -PdiffTo=HEAD
//
// And in Travis, you could add:
//
// script:
// - 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then bash ./gradlew check -PdiffFrom=$TRAVIS_PULL_REQUEST_BRANCH -PdiffTo=$TRAVIS_BRANCH ; fi'
//
diffFrom = project.properties.diffFrom // Can be empty (ignored), Git-commit or any Git-reference
diffTo = project.properties.diffTo // Same as above
diffMinSeverity = 'INFO' // INFO, WARN or ERROR
diffDetailLevel = 'VERBOSE' // PER_FILE_COMPACT, COMPACT or VERBOSE
diffMaxViolations = 99 // Will fail the build if number of violations, in the diff within from/to, is higher
diffPrintViolations = true // Will print violations found in diff
gitRepo = file('.') // Where to look for Git
//
// This is mandatory regardless of if you want to report violations between
// revisions or the entire repo.
//
// Many more formats available, see: https://github.com/tomasbjerre/violations-lib
violations = [
["CHECKSTYLE", buildDir.path, ".*/checkstyle/.*\\.xml\$", "Checkstyle"]
]
}
在极狐 GitLab CI 中采集代码规范报告:
image: eclipse-temurin:8
cache:
paths:
- /root/.m2
stages:
- lint
- build
checkstyle:
allow_failure: true
stage: lint
script:
- ./gradlew check
artifacts:
when: always
untracked: true
report:
stage: lint
script:
- ./gradlew violations
needs:
- job: checkstyle
artifacts: true
artifacts:
reports:
codequality: gl-code-quality-report.json
compile:
stage: build
script:
- ./gradlew build -x check -x test
artifacts:
untracked: true
剩余步骤与「Java Gradle 项目」一致:开发人员频繁使用的「合并请求」页面,直接显示了「代码规范问题」,供开发人员自助修复以及提醒评审的同事注意,有效提高研发效率。
老项目第一次配置代码规范可能会出现很多错误(比如上图有 7746 个),没关系,先将规范合并进入主干,下次修改代码发起合并请求时,极狐 GitLab 将展示「增量代码质量报告」,而无需任何复杂设置,比如下图只有 5 个新问题:
这样,我们就通过极狐 GitLab 平滑落地了 Java 增量代码规范,让项目代码越来越优雅。