Rubyとかのスクリプト言語ではなく、Javaとかのコンパイルが必要な言語で困ったこと。
困った内容
Jenkinsでコンパイルを行っていて、コンパイル失敗の時に、失敗したファイルを特定して、そのファイルをコミットした人宛に向けてメールが飛ばせない!
前提条件
1. 「コミット頻度<コンパイル時間」となるような大きな(肥大化した)プロジェクト
→不等号が逆向きならば、コンパイル失敗=コミット者になるため、同じ状況になっても困らないはず
2. mavenでコンパイル実施(antの人はごめんなさい)
解決する必要があること
今回困った内容を解決するには、以下の2つが必要なはず
エラーとなったファイル名を抽出したい
以前に、Consoleに表示した[ERROR]文面を抜き取る方法について記事を書きました。
JenkinsでMavenのERRORのみを記載したメールを飛ばそう - ブロッコリーのブログ
ただ、今回はその文字列からさらにファイル名を抽出したい。
ということで、ログをファイル出力して、そのファイルの中身を別プログラムで操作する方法を考えました。
その際に「コマンド 2> ファイル名」とかの方法も考えましたが、そうするとmavenプロジェクトのビルドの恩恵が受けられなくなってしまう…。
コマンドライン(mavenオプションとかも入力する必要があるため、設定内容が分かりにくい)
mavenプロジェクト
※実際は%WORKSPACE%とかの環境変数を使えばもっと短くできるし、コマンドをファイル化して、そのファイル自身もバージョン管理した方が良いのかもしれません。
mavenコンパイルのログをファイルに残したい
そんな時にはmavenオプション!
今回の場合は
-q -l <ファイルパス>
-q オプションは、「エラーログのみ出力」
-l <ファイルパス> は、「<ファイルパス>にログを出力」
ということで、これを使えば
「ログをファイル出力して、そのファイルの中身を別プログラムで操作する」
が達成できる!
コンパイルが失敗した時だけ実行したい
これは今回に限ったことではないですが、よく陥る問題。
Jenkinsは成功したJobに対して後ろに渡す仕組みになっています。
しかし、失敗時だけというのはなかなかできない。
そういう悩みを解決するのが
「Trigger parameterized build on other projects」プラグイン
これを使えば、失敗時のみ下流のJobを動かすことができます。
今回の解決方法
下の画像の通り。
ポイントは2つ。
1. -q -l オプションで得られたログファイルのパスを下流のJobへ
渡していること(赤囲み部分)
2. Trigger when build is をFailedにしていること(青囲み部分)
この2つのポイントを行えば、下流のJob(この画像では01_view_log_file)に
エラーログの入ったファイルを渡すことができます。
あとは、その下流Jobの中で、渡されたファイルの中身を解析すれば
やりたいことができるはず。
注意点
それぞれで環境変数の表記方法が異なります。
- コマンドライン…%WORKSPACE%
- 引数の設定…%WORKSPACE%
- mavenオプション…$WORKSPACE
- Trigger parameterized build on other projectsプラグイン…${WORKSPACE}
自分の場合はこんな感じ。
1. コンパイル実行
2. 失敗した場合は、そのエラーログを渡して別のJobへ
3. エラーログの中身を見て、以下の方法からエラー発生ファイルを抽出
3-1. "[ERROR] "で始まる行を検索
3-2. ".java"の文字列部分まで抽出
4. コミットログからエラー発生ファイルを最近コミットした人物を特定
5. その人物のメールアドレスにメールを飛ばす
まとめ
1. -q -l でエラーログを保存する
2. 「Trigger parameterized build on other projects」プラグインで
失敗時の操作を行う
さいごに
それにしても、この方法だと面倒っす。
誰かもっと良い方法あったら教えて下さい!