Springプロジェクトでjavadocコマンドの結果をGithub ActionsでCIしたい

2021.02.26

こんにちは。

サービスGの金谷です。

JavadocのチェックといえばCheck Styleを使うことが多そうですが、そこまで細部までチェックする必要がなかったり、

Gradleのjavadocコマンドの結果と整合性を合わせるのが地味に大変だったりするということがあると思います。

特にある程度開発が進んでからCheck Styleを導入するとエラーの山で真っ赤に・・・なんてことがよくあります。

なので今回はgradleのjavadocコマンドの実行結果をGithub Actionsで表示するようにしてみます。

(全体的にやや力技です)

環境等

JavaはOpenJDK Runtime Environment Corretto-8.282.08.1

gradleは6.8.2を利用しました。

(プロジェクトの作成にはSpring initializrを利用)

javadoc failOnError

通常は特に何もせず、最初からGradleで用意されているjavadocコマンドを実行すればエラーが発生した場合に異常終了できます。

 

ただし、警告のみの場合は正常終了します。

./gradlew javadoc

これはGradleのjavadoc failOnErrorがtrueの場合の挙動です(デフォルト)

Javadoc:failOnError

ただし、マルチプロジェクトを採用している場合、failOnErrorをtrueに設定すると、すべてのサブプロジェクトでのチェックができないことがあります。

例えば、サブプロジェクトA, B, Cがあり、A, Bでjavadocの構文にエラーが有った場合、Aのチェックでエラーが発生した時点で処理が終了し、Bがチェックされない。ということが起こります。

root/
 ├ A/ // エラー発生
 ├ B/ // エラーを含むがチェックされない
 └ C/

こういう場合はfailOnErrorのフラグをfalseに設定することで、とりあえず一旦すべてのサブプロジェクトでのチェックを行うようにします。

grepで該当箇所を検索する

grepコマンドを使用してjavadocコマンドの出力結果を検索します。

警告もエラーも取得する場合は以下のようになります。(warning: error:の部分は日本語が設定されている場合は警告: エラー:となります)

./gradlew javadoc 2>&1 | grep -e warning: -e error:

以下のように出力されるかと思います。

/home/runner/work/github-actions-sandbox/github-actions-sandbox/src/main/java/com/example/sandbox/SampleController.java:11: error: @param name not found
/home/runner/work/github-actions-sandbox/github-actions-sandbox/src/main/java/com/example/sandbox/SampleController.java:13: warning: no @param for out
/home/runner/work/github-actions-sandbox/github-actions-sandbox/src/main/java/com/example/sandbox/SampleController.java:13: warning: no @return
/home/runner/work/github-actions-sandbox/github-actions-sandbox/src/main/java/com/example/sandbox/SampleController.java:22: warning: no @return

さらに、エラー箇所も表示したい場合は更にオプションを付けます。

./gradlew javadoc 2>&1 | grep -A 2 -e warning: -e error:

2行追加されて以下のような結果になるかと思います。

/home/runner/work/github-actions-sandbox/github-actions-sandbox/src/main/java/com/example/sandbox/SampleController.java:11: error: @param name not found
     * @param j iii 
              ^
/home/runner/work/github-actions-sandbox/github-actions-sandbox/src/main/java/com/example/sandbox/SampleController.java:13: warning: no @param for out
    public String get(String in, String out) {
                  ^
/home/runner/work/github-actions-sandbox/github-actions-sandbox/src/main/java/com/example/sandbox/SampleController.java:13: warning: no @return
    public String get(String in, String out) {
                  ^
/home/runner/work/github-actions-sandbox/github-actions-sandbox/src/main/java/com/example/sandbox/SampleController.java:22: warning: no @return
    public String out() {
                  ^

Javadoc以外のメッセージを除外する

上記までだとwarning:とerror:を含む全ての文字列を検索するので、除外したい条件を追加します。

今回はdeprecationを除外するようにします。

./gradlew javadoc 2>&1 | grep -v 'warning: \[deprecation\]' | grep -A 2 -e warning: -e error:

grep -vとすることでマッチした行以外の部分を取得します。

終了コードを調整する

grepコマンドは検索文字列が見つかった場合は終了コード0で処理を終了し、見つからなかった場合は1で終了します。

今回は該当する警告・エラー行が見つかった場合にエラーで終了したいので、終了コードを逆転させます。

! ./gradlew javadoc 2>&1 | grep -v 'warning: \[deprecation\]' | grep -A 2 -e warning: -e error: ; exit $?

最初に!を付けることで終了コードを逆転させ、exit $?で逆転させた終了コードで処理を終えるようにします。

Github Actionsに組み込む

最終的に以下のような形になりました

name: Javadoc Check

on: [push, pull_request]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Set up JDK 1.8
      uses: actions/setup-java@v1
      with:
        java-version: 1.8
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
    - name: Check Javadoc
      # warning: [deprecation] 以外で発生しているwarningとerrorを取得し、ヒットした場合は終了コード1で終了
      run: "! ./gradlew javadoc 2>&1 | grep -v 'warning: \\[deprecation\\]' | grep -A 2 -e warning: -e error: ; exit $?"

YAMLで設定を記述する場合は:が使えないので、値の両端を""で閉じる必要がある("warning :"みたいにその箇所だけ閉じてもエラーになる)のと

エスケープ文字を含む場合はバックスラッシュが2つ必要という部分で地味にハマりました。(1つはGithub Actions上で判定され、もう一つはLinux上で管理されるからと思われる)

最後に

Github Actions上で以下のようになれば成功です!

Run ! ./gradlew clean javadoc 2>&1 | grep -v deprecation | grep -A 2 -e warning: -e error: ; exit $?
/home/runner/work/github-actions-sandbox/github-actions-sandbox/src/main/java/com/example/sandbox/SampleController.java:11: error: @param name not found
     * @param j iii 
              ^
/home/runner/work/github-actions-sandbox/github-actions-sandbox/src/main/java/com/example/sandbox/SampleController.java:13: warning: no @param for out
    public String get(String in, String out) {
                  ^
/home/runner/work/github-actions-sandbox/github-actions-sandbox/src/main/java/com/example/sandbox/SampleController.java:13: warning: no @return
    public String get(String in, String out) {
                  ^
/home/runner/work/github-actions-sandbox/github-actions-sandbox/src/main/java/com/example/sandbox/SampleController.java:22: warning: no @return
    public String out() {
                  ^
Error: Process completed with exit code 1.

では、良いCIライフを!

参考

検証に利用したリポジトリ

Javadoc:failOnError