Jenkinsプラグインを作ってみる(1) - セットアップとサンプルコード - 


Jenkinsプラグインを開発しはじめたものの、あまり資料がないのでまとめてみる。
まずは開発をはじめるための最初のステップとして、セットアップとサンプルコードの説明から。

## そもそもプラグインって何ができるの？
```
Jenkinsでは拡張ポイントを定義しています。
それはビルドシステムのある側面をモデル化したインターフェースもしくは抽象クラスです。これらのインターフェースでは実装する必要があるものを定めており、Jenkinsではプラグインがこの実装にコントリビュートすることを許可しています。

https://wiki.jenkins-ci.org/display/JA/Plugin+tutorial
```


上記の内容だと分かりづらいですね。

例えば、以下の様なことが出来るようになる。

 - Jobの実行終了時にSlackに実行結果を投稿する
 - 成果物を外部のストレージに保存する

## 環境
 - Mac
  - OSX 10.10.2
 - Java
  - java version "1.8.0_31"
  - インストールしていなければ、[参考資料](http://qiita.com/ryo0301/items/3c9a02e03b4e9a41f576)を元にインストールしておく。

## 環境セットアップ
### 各種インストール
#### Maven3

```
brew install maven
```

##### 設定
以下の場所にファイル(settings.xml)を置く。

 - ~/.m2/settings.xml


```xml:settings.xml
<settings>
  <pluginGroups>
    <pluginGroup>org.jenkins-ci.tools</pluginGroup>
  </pluginGroups>

  <profiles>
    <!-- Give access to Jenkins plugins -->
    <profile>
      <id>jenkins</id>
      <activation>
        <activeByDefault>true</activeByDefault> <!-- change this to false, if you don't like to have it on per default -->
      </activation>
      <repositories>
        <repository>
          <id>repo.jenkins-ci.org</id>
          <url>http://repo.jenkins-ci.org/public/</url>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>repo.jenkins-ci.org</id>
          <url>http://repo.jenkins-ci.org/public/</url>
        </pluginRepository>
      </pluginRepositories>
    </profile>
  </profiles>
</settings>
```

#### Eclipse
 - ダウンロード
  - https://eclipse.org/downloads/

#### Jenkins

```
brew install jenkins
```

起動

 - launchctl load ~/Library/LaunchAgents/homebrew.mxcl.jenkins.plist
 - jenkins

どちらでもOK。
※Eclipseからも出来るので、今から起動させておく必要はない。

## サンプルプラグインの作成

```
mvn -cpu hpi:create
```

以下の2種類を入力
 - Enter the groupId of your plugin [org.jenkins-ci.plugins]:
 - Enter the artifactId of your plugin (normally without '-plugin' suffix):

### Eclipseの設定
#### プロジェクトファイル作成
作成されたディレクトリで以下のコマンドをうつ。

```
mvn -DdownloadSources=true -DdownloadJavadocs=true -DoutputDirectory=target/eclipse-classes eclipse:eclipse
```

作成されたらEclipseからimportすればOK。

#### Maven Buildの設定
Eclipseの「Debug Configurations」から「Maven Build」を新規に作成し以下のように設定する。

|名前  |値|
|:----|:------|
|Goals|hpi:run|
|Parameter Name|MAVEN_OPTS|
|Value|-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n|


上記設定をやっておき、EclipseからDebugで起動させるだけでOK。
あとは、http://localhost:8080/jenkins にアクセスするだけ。

### ディレクトリ構成
 - src/main/java
   - ロジック(Javaソースコード)
 - src/main/resources
   - UI(jellyファイル)


### サンプルコードの説明
#### ロジック(Javaソースコード)
このサンプルコードで利用している拡張ポイントはBuilder。
この拡張ポイントをextendsすることにより、「ビルド手順」に新規の機能を追加することができる。

```java
public class HelloWorldBuilder extends Builder
```


サンプルコードをインストールすると以下の様な感じになる。

![スクリーンショット 2015-04-04 14.19.27.png](https://qiita-image-store.s3.amazonaws.com/0/37642/f4da13ab-427f-7723-1f70-d36c2b83a1b3.png "スクリーンショット 2015-04-04 14.19.27.png")

![スクリーンショット 2015-04-04 14.19.38.png](https://qiita-image-store.s3.amazonaws.com/0/37642/2d482e61-0eb1-74d4-0694-c75632fcb612.png "スクリーンショット 2015-04-04 14.19.38.png")


performを@Overrideすることにより、Jenkinsのjobの実行時におこなう処理を追加すること出来る。
サンプルコードでは以下のように書いている。

```java
    @Override
    public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) {
        if (getDescriptor().getUseFrench())
            listener.getLogger().println("Bonjour, "+name+"!");
        else
            listener.getLogger().println("Hello, "+name+"!");
        return true;
    }
```

これにより、入力された値を実行終了時のConsole Outputとして出力している(getUseFrench()周りについては割愛)。

![スクリーンショット 2015-04-04 14.20.34.png](https://qiita-image-store.s3.amazonaws.com/0/37642/15c57da6-5268-1b27-429a-6704cdc2920f.png "スクリーンショット 2015-04-04 14.20.34.png")



ここでは常 ```return true``` になっているが、ここを条件によりfalseにすることによりビルドを失敗させることも出来る。



##### 拡張ポイント

 - ビルド手順の追加であれば、[Builder](http://javadoc.jenkins-ci.org/hudson/tasks/Builder.html)
 - ビルド後の処理であれば、[Recorder](http://javadoc.jenkins-ci.org/hudson/tasks/Recorder.html)

というふうに拡張ポイントを利用していく。
他の拡張ポイントについては、[ここ](https://wiki.jenkins-ci.org/display/JENKINS/Extension+points)を参考にすると良い。



#### UI(jellyファイル)
UIに関しては、「config.jelly」に記述されている。
jellyだけでなくgroovyも利用することが出来る。


サンプルコードは単純で以下のように書かれている。

```xml:config.jelly
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">

    <f:entry title="Name" field="name">
    <f:textbox />
  </f:entry>
</j:jelly>
```

jellyで書いていることと対応するコードは以下のようなclass内に書かれている必要がある。

```
        @Extension
    public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
    .....
}
```


##### Selectを使いたい場合
まず、config.jelly側では以下のように記述する。

```:xml:config.jelly
<f:entry field="goalType" title="Choose Goal Type">
   <f:select />
</f:entry>
```

そして、コード側では以下のように記述する。

```
		public ListBoxModel doFillGoalTypeItems() {
            ListBoxModel items = new ListBoxModel();
            for (BuildGoal goal : getBuildGoals()) {
                items.add(goal.getDisplayName(), goal.getId());
            }
            return items;
        }
```

見るとわかるけど、ルールが決まっているだけでさくっと書くことが出来る。
他に、どのように書くかは[ここ](https://wiki.jenkins-ci.org/display/JENKINS/Jelly+form+controls)を参考にすると良い。


## 終わりに
Jenkinsプラグインは思っているよりも簡単に作ることが出来る。
なので、自分が欲しいプラグインが無かったら作ってしまえば良いと思う！


## 参考資料
 - JAVA周り
   - http://qiita.com/ryo0301/items/3c9a02e03b4e9a41f576
 - Jenkinsプラグイン チュートリアル
   - https://wiki.jenkins-ci.org/display/JA/Plugin+tutorial
 - Jelly form controls
   - https://wiki.jenkins-ci.org/display/JENKINS/Jelly+form+controls
 - Extension points
   - https://wiki.jenkins-ci.org/display/JENKINS/Extension+points