头图
本文来自:
杨周 极狐GitLab 高级解决方案架构师

代码越写越规范是优秀开发者的成长之路,但很多人对老项目感到有心无力,因为太不规范了,所有人停下来一起修复也要花费很长时间,而且一次改动太多难以确保可靠性,怎么办?

有的语言可以借助 Git diff 把本次修改的代码挑出来,实现增量扫描,但 Java 很难这么做。

有的人在持续集成里配置了规范扫描工具,但报错之后需要在成千上万行 log 里查找,降低了研发效率。

Checkstyle 是业界知名的开源扫描工具,可扫描 Sun、Google 等代码规范,提供Maven、Gradle 插件。本文以 Java 项目配置 Checkstyle 扫描工具为例,分享消灭这些问题的办法:

1. 将代码规范问题显示在「合并请求页面」,大幅度提高研发效率;

2. 增量代码规范报告。

下文分别介绍「Java Maven 项目」「Java Gradle 项目」的配置方法。

通过极狐GitLab CI 平滑落地 Java 增量代码规范Checkstyle Maven

在项目中引入 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 个新问题了:

通过极狐GitLab CI 平滑落地 Java 增量代码规范 Checkstyle Gradle

「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 增量代码规范,让项目代码越来越优雅。


极狐GitLab
64 声望36 粉丝

极狐(GitLab) 以“核心开放”为原则,面向中国市场,提供开箱即用的开放式一体化安全DevOps平台——极狐GitLab。通过业界领先的优先级管理、安全、风险和合规性功能,实现产品、开发、QA、安全和运维团队间的高效协同...