Jenkins Workflow Pluginを使ってみました

![buildpipeline.png](https://qiita-image-store.s3.amazonaws.com/0/63454/1958908d-3a37-9f44-6e7c-48936e79a40f.png)


先日の[Jenkins User Conference 2015](http://build-shokunin.org/juc2015/)でWorkflow Pluginの情報を入手しましたので
簡単な導入から良く使われるワークフローをテストコードで確認してみました。

#導入

Workflow Pluginは**Workflow Aggregator**と言うプラグインを入れる必要があります。

![workflowplugin.png](https://qiita-image-store.s3.amazonaws.com/0/63454/1ec388f8-f40c-b803-44ba-4088bf115d7e.png)

こちらを入れると新規ジョブ作成で以下のWorkflowスタイルのジョブが作成出来るようになります。

![job create.png](https://qiita-image-store.s3.amazonaws.com/0/63454/540e523c-52cb-50f3-ebb1-920115866246.png)

Workflowジョブには見慣れないGroovy CPS DLSのスクリプトを書く所が出てきます。
ワークフローはここに記載していきます。

![dsl.png](https://qiita-image-store.s3.amazonaws.com/0/63454/00f37921-582e-b0d2-2616-cb6127685db9.png)

#挙動確認

思ったよりも必要なpluginが未対応?のようなのでガチ利用は諦めて既存のジョブ同士を繋いでワークフローを作成する利用に限定します。

![test-jobs.png](https://qiita-image-store.s3.amazonaws.com/0/63454/107dfe24-71a1-f438-583c-c0eb666b3f90.png)

挙動確認の為に以下のテスト用のジョブを生成しました。

* `test-workflow`がworkflowジョブ本体です。
* `test-pass1 / test-pass2`は必ず成功するだけのジョブです
* `test-fail`は必ず失敗するだけのジョブです。
* `test-notify`は通知(chatwork等)を想定した成功（エラー）通知ジョブです

##1.groovyファイルを読み込んで実行

Jenkinsのtest-workflowジョブ内のGroovy CPS DLS内のScriptに以下の記述を行います

```groovy:dls
def flow
node('master') {
    git url: 'https://hogehoge@bitbucket.org/hogehoge/workflow-test.git'
    flow = load 'groovy/flow.groovy'
    flow.builds()
}
```
やっている事はmasterノード固定でbitbucketからgroovy/flow.groovyと言うファイルを更新してbuilds()と言う関数を実行しているだけです。
Jenkins上で記載するのはこれだけで実体はバージョン管理されたflow.groovyに記述していきます。

##2.ジョブが失敗した場合に後続のジョブに流れない様に

一番基本的な利用方法を確認するために以下の様なスクリプトを作成しました。
builds()は実際のビルドシーケンスを記述しています。run()はbuilds()から呼び出される関数です。

```groovy:flow.groovy
// flow.groovyファイル 必ず失敗するパターンの確認用
def builds() {
	run 'test-pass2'
	run 'test-fail'
	run 'test-pass1'
}

def run(name) {
	try {
		build name
	} catch (e) {
		echo "job error : ${name}"
		build 'test-notify'
		throw e
	}
}
return this;
```
このテストシーケンスではtest-pass2の後にtest-failが失敗し
test-notifyが呼び出されて後続ジョブのtest-pass1が**呼び出されない**事を確認します。

![logs.png](https://qiita-image-store.s3.amazonaws.com/0/63454/6d557b19-6b03-f883-b4e7-964ed450113c.png)

実行時のJenkinsのコンソール出力です。
test-pass2は正常に完了しtest-failで失敗し echo と test-notifyを実行後に workflow自体が停止しています。

と言うわけで意図した通りにJenkinsで良く利用される以下の2つの動作が確認できました。

*  成功した時だけ後続ジョブを実行（build -> test -> deployなど)
*  失敗した時だけ特別なジョブを実行（通知など）

またWorkflowスタイルのジョブには Running Stepと言う項目が追加されます。

![running step.png](https://qiita-image-store.s3.amazonaws.com/0/63454/0d831b4a-84b3-ac26-4989-c191d8b9014b.png)

こちらを利用すると先ほどのログを以下の様な形式で確認する事が出来ます。

![step.png](https://qiita-image-store.s3.amazonaws.com/0/63454/21ee362b-b623-4b70-a3c4-5befe3ffb010.png)

エラー箇所がとても判りやすいのが良いですね！

##3.並列実行を行う

複数のジョブを並行に実行してマシンリソースを同時に利用したいケースは多々あると思います。
その場合は以下の様なparallelに**ブランチ**と言う物を複数記述して実現します

`parallel( ブランチ名 : { 実行処理 } , ブランチ名 : { 実行処理 } ... )`

```groovy:flow.groovy
// flow.groovyファイル 並列実行の確認
def builds() {
	parallel(pass2: {
		run 'test-pass2'
	}, pass1: {
		run 'test-pass1'
	}, fail: {
		run 'test-fail'
	})
}
```
上記のflow.groovyの場合はジョブ実行後に以下の様にビルドキューが3つ同時に走ります。

![buildque.png](https://qiita-image-store.s3.amazonaws.com/0/63454/ccf5e85f-7d01-c378-635f-ba1db7f5c5d5.png)

今回はジョブ単位なのでtest-pass1をSlave-Aで実行しtest-pass2をSlave-Bで実行する事も可能です。（この設定は今まで通り各ジョブに設定する）

![step2.png](https://qiita-image-store.s3.amazonaws.com/0/63454/1da353b9-7ff9-1fc7-923d-2b4d14b303bd.png)

こちらが並列実行時Running Stepですが3つのブランチが動作している事が判ります。
failブランチの中でtest-failが失敗後に同一ブランチ内できちんとecho / Test-notifyが実行されている事が確認出来ます。

#本命 checkpointは？

個人的大本命のcheckpointです。

```groovy:flow.groovy
// flow.groovyファイル checkpointを置く
def builds() {
	checkpoint('build')
	run 'test-pass2'
	checkpoint('test')
	run 'test-pass1'
	checkpoint('deploy')
	run 'test-fail'
}
```

test-failが失敗した場合に本来はtest-pass2 -> test-pass1を再度実行するのがJenkinsでフローを作成した時の面倒な所でした。test-pass1が超スローテストなジョブだった日には頭痛で吐きます。

しかしcheckpointを追加しておくとWorkflow Pluginのおかげで失敗した最後のcheckpointから
再開（上記の場合はdeployから）出来る機能となります。

と心をワクワクさせながら実行してみましたが、どうもNoSuchMethodErrorが帰ってきます。
https://github.com/jenkinsci/workflow-plugin-pipeline-demo/blob/master/flow.groovy のサンプルコードを見てると・・・・

***'Checkpoint feature available in Jenkins Enterprise by CloudBees.'***

と言うわけでひと通りのテストが終わった後にこの1行に気づき少しだけ気絶しています。

#まとめ

後続のタスクを呼び出す形でワークフローを作成していたプロダクトであれば、かなり簡単にWorkflowプラグインに入れ替えられる事が判りました。

特にワークフロー上の色々な要件の為に各ジョブに様々な小細工をしていた方は多いと思いますのでWorkflowプラグインを利用してスッキリさせるのは良さそうです。

ただ拡張e-mailプラグインだのMulti系のプラグインだのがまだ直接呼べない?ようなのでジョブ呼び出しでは無く1つのジョブで完結する方式への移行は色々と時間がかかりそうです。

あとはBuild Pipelineの Workflow版が早く出てほしいですね。（見える化　大事）

ちなみに初めてGroovyでコードを書いてみたのですが参考資料の公式のflow.groovyを見ただけで違和感無くさっくりと書くことが出来ました。素直な言語ですね。

パラメーター付きでジョブを呼ぶ方法とリトライを調査＆テストが終われば、社内のプロダクトを少しづつ移行しはじめる予定です。