JenkinsのJNLPスレーブを簡単に gradlew 一発で立てたい

## Jenkinsスレーブの立ち上げは無策でやると面倒くさい

Jenkinsではビルドする際、Jenkinsスレーブを立てることになるのですが、下記の理由により面倒です。

* スレーブの登録が面倒 
  ![image.png](https://qiita-image-store.s3.amazonaws.com/0/9619/b1101519-cc83-5605-26a3-b15ba22bab48.png)
    * というか、Jenkinsに設定をあまり持たせたくない。
* Jenkinsからスレーブをつなぎに行く方式（SSHとか）だと、Firewall設定が厄介。
    * クラウド上にたっているJenkinsは実質ムリ。
* WindowsとLinux、macOSやらで違う手順・プロトコルが必要になってくる。

## 面倒くささを克服する

そういうことで、下記方針でJenkinsスレーブ立てをやっていくことになります。

* スレーブの登録が面倒
    * → [Swarm Plugin](https://wiki.jenkins.io/display/JENKINS/Swarm+Plugin) を使います。
        * このプラグインを使えば、スレーブ側からJenkins上に直接自分自身のスレーブ登録をオンデマンドかつ自動で行うことができます。
        * 設定画面上は "Self-Organizing Swarm Plug-in Modules" という名前になっているので注意。
        * 実際動かす際は Swarm Plugin の[クライアントJAR](https://repo.jenkins-ci.org/releases/org/jenkins-ci/plugins/swarm-client/)をダウンロードして下記のように引数付きで起動することになります。
        
          ```console
          $ java -jar swarm-client.jar \
              -master "http://JenkinsのURL" \
              -name "スレーブの名前のプレフィックス" \
              -uname "JenkinsにログインするID" \
              -password "上記IDのパスワード" \
              -fsroot "スレーブのワークスペースルートパス" \
              -executors "エグゼキュータの数" \
              -deleteExistingClients \
              -label "スレーブノードのラベル1 ラベル2 ラベル3 ..." \
              -mode "exclusive"

          # あらかじめJenkinsのJNLPポートをあけておくこと / あらかじめ Swarm Plugin をインストールしておくこと
          ```
* Jenkinsからスレーブをつなぎに行く方式（SSHとか）だと、Firewall設定が厄介。
    * → JNLPプロトコルを利用する。
        * 特定のポートにたっているJNLPポートにスレーブ側からシェイクハンドして以後TCP接続をするという方式です。
        * Swarm Pluginを使う時点でこれしか選択肢は無いです。
* WindowsとLinux、macOSやらで違う手順・プロトコルが必要になってくる。
    * → JNLPは特にSSH非依存なので大丈夫。どの環境からでもいけます。

## でもSwarm PluginのJARを置いたりするのが面倒くさい → Gradle化すればいい

上記のやり方でやるとしても、 [Swarm Plugin のクライアントJAR](https://repo.jenkins-ci.org/releases/org/jenkins-ci/plugins/swarm-client/) をダウンロード・設置するのが非常に面倒です。クライアントJARのバージョンアップもやってられません。

そういうことで、 Gradle ビルドスクリプトを使ってスレーブのJARのダウンロードと立ち上げすべてをやってもらいます。

```gradle:build.gradle
repositories { mavenCentral(); maven { url "https://repo.jenkins-ci.org/releases/" } }
configurations { tool }
dependencies { tool "org.jenkins-ci.plugins:swarm-client:3.12" }

task start(type: JavaExec) {
    classpath = configurations.tool
    main = "hudson.plugins.swarm.Client"
    args([
        "-master", "http://JenkinsのURL",
        "-name", "スレーブの名前のプレフィックス",
        "-username", "JenkinsにログインするID",
        "-password", "上記IDのパスワード",
        "-fsroot", "スレーブのワークスペースルートパス ",
        "-executors", "エグゼキュータの数",
        "-deleteExistingClients",
        "-labels", ["スレーブノードのラベル1","ラベル2","ラベル3","..."].join(" "),
        "-mode", "exclusive", // 排他モード
    ])
}
defaultTasks "start"
```

上記ファイルを用意して、下記コマンドを流せばスレーブが繋がります。

```console
$ gradle
```

とはいえ、こうなるとGradleのインストールも面倒なので、[Gradle wrapper](http://gradle.monochromeroad.com/docs/userguide/gradle_wrapper.html)も用意すればGradleのインストールも不要になります。

```console
# JDKのインストールはさすがに必要
$ ./gradlew
```

## スレーブを立ち上げ・維持するのが面倒

こうなると、スレーブを立ち上げ・維持するのが面倒になってきます。

Jenkinsスレーブを立ち上げるホストOSのデーモンサービス的な機能を使ってプロセスを維持させましょう。

* macOS: [launchd](http://www.launchd.info/)
* 最近のLinux: [systemd](http://www.freedesktop.org/wiki/Software/systemd/)。systemdでデーモンのユニットを作る方法で調べましょう。
* Windows: タスクスケジューラとか使えばできる。（詳しくない）

macOSなど、要するに証明書やらで特定ユーザの環境込みのXcodeでビルドしたいのだと思いますが、誰かのユーザプロセスとして立ち上げるようにデーモンを構成することをおすすめします。（場合によってはスレーブを立ち上げるためだけに、電源ONの後、ユーザログインという手順が必要になるでしょうね。）

## ここまでやってきたことはこのリポジトリにあります

https://github.com/knjname/JenkinsSwarmPluginLauncherScript

そのうちLinuxデーモンの登録用スクリプト足すかも…