You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ratis.apache.org by iv...@apache.org on 2026/10/23 01:17:20 UTC

(ratis) branch master updated: RATIS-2772. Add ErrorProne into Ratis verification pipeline (#1658)

This is an automated email from the ASF dual-hosted git repository.

ivandika3 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ratis.git


The following commit(s) were added to refs/heads/master by this push:
     new f549f144e RATIS-2772. Add ErrorProne into Ratis verification pipeline (#1658)
f549f144e is described below

commit f549f144ef383e80ed21930a2468dcc1bb21c718
Author: Ivan Andika <iv...@apache.org>
AuthorDate: Fri Oct 23 09:17:14 2026 +0800

    RATIS-2772. Add ErrorProne into Ratis verification pipeline (#1658)
---
 .github/dependabot.yml               |  3 ++
 .github/workflows/ci.yaml            |  9 ++++
 BUILDING.md                          | 22 ++++++++++
 dev-support/checks/errorprone.sh     | 57 ++++++++++++++++++++++++
 dev-support/tests/test-errorprone.sh | 85 ++++++++++++++++++++++++++++++++++++
 pom.xml                              | 44 +++++++++++++++++++
 6 files changed, 220 insertions(+)

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index e33f4fcc2..1e49f962d 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -42,6 +42,9 @@ updates:
         versions: [">=4.9.0.0"]
       - dependency-name: "org.mockito:mockito-core"
         versions: [">=5.0.0"]
+      # Error Prone runs on Java 17 in CI
+      - dependency-name: "com.google.errorprone:error_prone_core"
+        versions: [">=2.43.0"]
       # requires Java 17
       - dependency-name: "org.apache.hadoop:*"
         versions: [">=3.5.0"]
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 49e0caeb3..b523fc8d6 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -97,6 +97,15 @@ jobs:
     secrets:
       DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
 
+  errorprone:
+    uses: $/.github/workflows/check.yaml
+    with:
+      java-version: '17'
+      script: errorprone
+      timeout-minutes: 30
+    secrets:
+      DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
+
   unit:
     strategy:
       matrix:
diff --git a/BUILDING.md b/BUILDING.md
index 68b4c0b88..930a5223a 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -30,6 +30,28 @@ $ mvn clean package -DskipTests
 Note: subsequent builds could be faster with skiping shading/protobuf compile steps.
 See the next section for more info.
 
+## Error Prone
+
+Run [Error Prone](https://errorprone.info/) static analysis with JDK 17 or 21:
+
+```
+$ dev-support/checks/errorprone.sh
+```
+
+The check compiles main and test sources without running tests. Reports are written to
+`target/errorprone`: `output.log` contains the complete build output, `diagnostics.txt`
+contains compiler diagnostics, and `summary.txt` contains errors. Warnings do not fail the check.
+Generated sources are excluded from Error Prone analysis.
+
+The Maven profile can also be used directly:
+
+```
+$ mvn clean test-compile -Perrorprone -DskipTests
+```
+
+Normal builds do not enable Error Prone and continue to support Java 8.
+To test the check script's report handling, run `bash dev-support/tests/test-errorprone.sh`.
+
 # Thirdparty
 
 All bundled thirdparty dependencies are centralized in the *ratis-thirdparty* module
diff --git a/dev-support/checks/errorprone.sh b/dev-support/checks/errorprone.sh
new file mode 100755
index 000000000..4ca4a9e59
--- /dev/null
+++ b/dev-support/checks/errorprone.sh
@@ -0,0 +1,57 @@
+#!/usr/bin/env bash
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -u -o pipefail
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+cd "$DIR/../.." || exit 1
+
+source "${DIR}/../find_maven.sh"
+
+REPORT_DIR=${OUTPUT_DIR:-"$DIR/../../target/errorprone"}
+OUTPUT_LOG=$(mktemp)
+trap 'rm -f "$OUTPUT_LOG"' EXIT
+
+MAVEN_OPTIONS='-B -fae -Perrorprone -DskipTests -Djacoco.skip'
+# Cached compilation does not emit compiler diagnostics.
+MAVEN_OPTIONS="$MAVEN_OPTIONS -Ddevelocity.cache.local.enabled=false"
+# Timestamp prefixes would prevent matching diagnostics.
+MAVEN_OPTIONS="$MAVEN_OPTIONS -Dorg.slf4j.simpleLogger.showDateTime=false"
+
+#shellcheck disable=SC2086
+${MVN} ${MAVEN_OPTIONS} clean test-compile "$@" 2>&1 | tee "$OUTPUT_LOG"
+rc=$?
+
+# Create reports after clean, which removes the default report directory.
+mkdir -p "$REPORT_DIR"
+mv "$OUTPUT_LOG" "${REPORT_DIR}/output.log"
+trap - EXIT
+
+MAVEN_DIAGNOSTIC_PATTERN='^\[(ERROR|WARNING)\] .*:\[[0-9]+,[0-9]+\] \[[^]]+\]'
+JAVAC_DIAGNOSTIC_PATTERN='^.*:[0-9]+: (error|warning): \[[^]]+\]'
+grep -E "${MAVEN_DIAGNOSTIC_PATTERN}|${JAVAC_DIAGNOSTIC_PATTERN}" "${REPORT_DIR}/output.log" \
+  | awk '!seen[$0]++' > "${REPORT_DIR}/diagnostics.txt"
+
+grep -E '^\[ERROR\]|:[0-9]+: error:' "${REPORT_DIR}/diagnostics.txt" > "${REPORT_DIR}/summary.txt" || true
+if [[ ${rc} -ne 0 && ! -s "${REPORT_DIR}/summary.txt" ]]; then
+  echo 'Unknown failure, check output.log' > "${REPORT_DIR}/summary.txt"
+fi
+wc -l < "${REPORT_DIR}/summary.txt" | tr -d ' ' > "${REPORT_DIR}/failures"
+
+if [[ -s "${REPORT_DIR}/summary.txt" ]]; then
+  exit 1
+fi
+exit ${rc}
diff --git a/dev-support/tests/test-errorprone.sh b/dev-support/tests/test-errorprone.sh
new file mode 100755
index 000000000..f407a6e4a
--- /dev/null
+++ b/dev-support/tests/test-errorprone.sh
@@ -0,0 +1,85 @@
+#!/usr/bin/env bash
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -eu
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+TEST_DIR=$(mktemp -d)
+trap 'rm -rf "$TEST_DIR"' EXIT
+export TEST_DIR
+export OUTPUT_DIR="${TEST_DIR}/report"
+export MAVEN="${TEST_DIR}/mvn"
+
+cat > "$MAVEN" <<'EOF'
+#!/usr/bin/env bash
+printf '%s\n' "$@" > "${TEST_DIR}/args"
+# A clean build removes reports created before Maven runs.
+rm -rf "$OUTPUT_DIR"
+cat "${TEST_DIR}/stdout"
+cat "${TEST_DIR}/stderr" >&2
+exit "${MAVEN_EXIT_CODE}"
+EOF
+chmod +x "$MAVEN"
+
+run_check() {
+  local expected=$1
+  local actual=0
+  bash "${DIR}/../checks/errorprone.sh" -Dtest.option=true > "${TEST_DIR}/output" 2>&1 || actual=$?
+  if [[ "$actual" -ne "$expected" ]]; then
+    cat "${TEST_DIR}/output"
+    echo "Expected exit $expected, got $actual" >&2
+    exit 1
+  fi
+}
+
+export MAVEN_EXIT_CODE=1
+cat > "${TEST_DIR}/stdout" <<'EOF'
+[WARNING] /src/Legacy.java:[1,1] [JdkObsolete] warning finding
+[ERROR] /src/Format.java:[2,1] [FormatString] error finding
+[ERROR] /src/Format.java:[2,1] [FormatString] error finding
+[ERROR] Failed to execute goal compiler:compile
+EOF
+cat > "${TEST_DIR}/stderr" <<'EOF'
+/src/Raw.java:3: warning: [Custom-Rule_1] raw warning
+/src/Raw.java:4: error: [RawError] raw error
+EOF
+run_check 1
+[[ $(wc -l < "$OUTPUT_DIR/diagnostics.txt") -eq 4 ]]
+[[ $(wc -l < "$OUTPUT_DIR/summary.txt") -eq 2 ]]
+[[ $(cat "$OUTPUT_DIR/failures") -eq 2 ]]
+grep -q 'JdkObsolete' "$OUTPUT_DIR/diagnostics.txt"
+grep -q 'RawError' "$OUTPUT_DIR/summary.txt"
+! grep -q 'warning\|WARNING\|Failed to execute' "$OUTPUT_DIR/summary.txt"
+for arg in -Perrorprone -DskipTests clean test-compile -Dtest.option=true; do
+  grep -qx -- "$arg" "${TEST_DIR}/args"
+done
+
+export MAVEN_EXIT_CODE=0
+printf '%s\n' '[WARNING] /src/Legacy.java:[1,1] [JdkObsolete] warning finding' > "${TEST_DIR}/stdout"
+: > "${TEST_DIR}/stderr"
+run_check 0
+[[ $(wc -l < "$OUTPUT_DIR/diagnostics.txt") -eq 1 ]]
+[[ ! -s "$OUTPUT_DIR/summary.txt" ]]
+[[ $(cat "$OUTPUT_DIR/failures") -eq 0 ]]
+
+export MAVEN_EXIT_CODE=1
+printf '%s\n' '[ERROR] Dependency resolution failed' > "${TEST_DIR}/stdout"
+run_check 1
+[[ ! -s "$OUTPUT_DIR/diagnostics.txt" ]]
+grep -qx 'Unknown failure, check output.log' "$OUTPUT_DIR/summary.txt"
+[[ $(cat "$OUTPUT_DIR/failures") -eq 1 ]]
+
+echo 'Error Prone check tests passed'
diff --git a/pom.xml b/pom.xml
index 6b02d878a..1235a70cc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -164,6 +164,8 @@
     <protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
     <cyclonedx.version>2.9.3</cyclonedx.version>
 
+    <errorprone.version>2.42.0</errorprone.version>
+
     <spotbugs.version>4.8.6</spotbugs.version>
     <spotbugs-plugin.version>4.8.6.8</spotbugs-plugin.version>
 
@@ -785,6 +787,48 @@
   </build>
 
   <profiles>
+    <profile>
+      <id>errorprone</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-compiler-plugin</artifactId>
+            <configuration>
+              <fork>true</fork>
+              <annotationProcessorPaths combine.children="append">
+                <path>
+                  <groupId>com.google.errorprone</groupId>
+                  <artifactId>error_prone_core</artifactId>
+                  <version>${errorprone.version}</version>
+                </path>
+              </annotationProcessorPaths>
+              <compilerArgs combine.children="append">
+                <arg>-XDaddTypeAnnotationsToSymbol=true</arg>
+                <arg>-XDcompilePolicy=simple</arg>
+                <arg>--should-stop=ifError=FLOW</arg>
+                <arg>-Xplugin:ErrorProne -XepDisableWarningsInGeneratedCode -XepExcludedPaths:.*/target/generated(-test)?-sources/.*</arg>
+                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
+                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
+                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
+                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
+                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
+                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
+                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
+                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
+                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
+                <arg>-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
+                <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
+                <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
+                <!-- Forces the compiler process to output in English -->
+                <arg>-J-Duser.language=en</arg>
+                <arg>-J-Duser.country=US</arg>
+              </compilerArgs>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
     <profile>
       <id>experiments-build</id>
       <activation>