mike-neckのブログ

Java or Groovy or Swift or Golang

今更だけど、Gradleをちゃんと勉強しよう - Task同士の協調

f:id:mike_neck:20150818084108g:plain

今度のJava女子部の勉強会でGradleの講師をさせていただくことになりました。

javajo.doorkeeper.jp

それほど高度な内容は扱わないのですが、入門レベルの復習をされたい方はご参加いただくとよいかもしれません。


で、その勉強会の中でGradleのタスク同士が強調するようなサンプルを作っていた所、謎いタスクが出来上がりました。

f:id:mike_neck:20150910121301p:plain

ベースとなっているタスクは単なるじゃんけんです。ユーザーがrps(Rock-Paper-Scissors)の値を入力して、Gradle側もrps(Rock-Paper-Scissors)の値を決定して比べているだけです。

まあ、それだけだったら、面白くもなんともないのですが、そのタスクの結果を受けて、Gradleが負けた(ユーザーが勝った)時に、JVM系モダンビルドツールの他の四天王(sbt、Leiningen、Maven)がお決まりの四天王ネタを言ってくれるタスクを用意します。

なお、ユーザーが負けたり、あいこだったりする場合は、他の四天王の面々は無言です。

f:id:mike_neck:20150910122453p:plain


仕様と実装

簡単にタスクの仕様を書くとこんな感じです。

  • rpsタスク
    • ユーザーがrpsというプロパティを設定して起動した場合、その値からじゃんけんの値を取り出す(ない場合や、特定できない場合はグーになる)
    • cpu側はランダムでrpsの値を決定する
    • それらを比較結果(WINDRAWLOSE)をresultというフィールドに設定する
  • jvmタスク
    • rpsタスクに依存する
    • rpsタスクが実行され、rpsタスクのresultの値がLOSEの場合にのみ実行される
    • 四天王ネタを表示する

rpsタスクのベースになるタスクのクラスはこんな感じです。

class RpsCompTask extends DefaultTask {
  CompResult result
  @TaskAction
  void comp() {
    // ユーザーの手とCPUの手を決定 -> 省略
    // 比較結果をresultに保存する
    result = cpu.comp(user)
    // 結果を表示する -> 省略
  }
}

タスク実行制御

jvmタスクの方の実行制御ですが、これはTaskonlyIfメソッドを用いて制御します。

onlyIfに渡されるClosuretrueを返す時にタスクは実行され、falseを返すときにタスクはスキップされます。

task rps(type: RpsCompTask)

task jvm(dependsOn: 'rps') {
  group = 'JVM系モダンビルドツール最強決定戦'
  description = 'JVM系モダンビルドツール四天王が何か言いたそうにこちらを見ている'
  onlyIf {
    // rpsタスクが実行されて、その結果がLOSEの場合のみ実行
    tasks.rps.didWork && tasks.rps.result == CompResult.LOSE
  }
  doLast {
    logger.lifecycle "sbt      : Gradleが負けたようだな…"
    logger.lifecycle "Leiningen: ククク…奴はJVM系モダンビルドツール四天王の中でも最弱"
    logger.lifecycle "Maven    : ユーザーごときに負けるとはJVM系モダンビルドツールの面汚しよ…"
  }
}

このような形で依存タスクの実行結果に基いて次のタスクの実行制御が可能になります。

応用

例えば、Dockerファイルなどをまとめてパッケージングするタスクは、JaCoCoのテストカバレージで分岐、行とも70%に満たない場合には行わないという形にするなどの応用ができるでしょう。


amazon.co.jp