Jenkins2.0のPipelineを触ってみたら便利だった

Jenkins2.0でてた

f:id:hsbrysk:20160428172413p:plain

Jenkins2.0がでてた。
https://jenkins.io/2.0/

ざっくりと概要を見ると、主な変更点は次の3つらしい。

  1. Built-in support for delivery pipelines.
  2. Improved usability.
  3. Fully backwards compatible.

2に関しては、単純に見た目が良くなったよってこと。嬉しい。
3に関しては、後方互換性あるよってこと。幸せ。アップデートしない理由は理由ありませんということ。

1が気になる。

Jenkinsに感じてた不満点

Jenkinsって基本的にUIで設定をしていくから、面倒だなって思ってた。
ちょっと変更したいだけなのに、わざわざポチポチと...。
そもそもUI自体もそんなに良くはなかった。(jenkins1.6あたりからだいぶマシになったけど)

あと、同じような設定のジョブが乱立していくこと。
例えばgit-flow的な開発をしていると、masterとdevelop branchにpushがあったときにビルド&テストを実行するようにすると思うんだけど、そうするとそれぞれのbranchごとにジョブを作る必要があった。
PRきたときにもビルド&テストを実行するから、一つのrepositoryにつき3つも作る必要があって、なんとかならんものかと悩んでいた。

Jenkinsから他のCI toolに移行すれば楽なんだけど、会社とかだと色々な事情があってそうもいかない。
(人数多いとライセンス量とかも高くなるし...)

Pipelineが解決してくれそうな予感

1の"Built-in support for delivery pipelines"ってやつはどうやらこういった不満点を解決してくれるみたい。

Built-inって書いてある通りに、pipeline自体はpluginとして1.xのときから提供されていたみたい。
2.0ではそれがビルトインで提供されるようになったということ。知らなかった。

実際にどうやるかというと、 JenkinsfileというものにDSL(Groovyで)を記述していくことで、ジョブの振る舞いを定義できるらしい。
そのJenkinsfileはsource code repoにおいておけば良いらしい。
Jenkinsfile自体がversion管理されるし良い。

さらに詳しく見ていると、Githubのusername or organaizationをJenkinsに登録しておくと、Jenkinsfileが置いてあるrepositoryを見つけてきてpushやPRに対してJenkinsfileに記述してある処理をしてくれるようだ。

travisっぽい雰囲気。好き。

よっしゃ試すぞ!
Fully backwards compatibleらしいけどさすがにいきなりupdateするの怖いから、まっさらなjenkinsを作る。

Jenkins2.0をセットアップ

jdkをインストール、war downloadしてきて動かすだけなので、省略。
きっとあなたのすぐそばにJenkinsおじさん(= Jenkinsを運用してくれている人)がいるから安心していい。

(前からあったか忘れてしまったが)はじめてJenkinsのweb siteにaccessしたときに、お勧めのpluginを入れるかどうか聞いてくるので、お勧めされた通りに入れた。

こんな画面でどんどんplugin入ってきた。

f:id:hsbrysk:20160428172629p:plain

あと、追加でMaven pluginも入れた。

JenkinsにGithubのusernameを登録する

新規ジョブ作成のpageから登録する。 ちょっとUIが変わってて、新規ジョブ作成の画面がこんなふうになっている。

f:id:hsbrysk:20160428174617p:plain

"Github Organaization"を選択して、Githubのusername/organaizationを登録すればいい。

細かい設定をする

Project Sources

f:id:hsbrysk:20160428172855p:plain

Scan credentialsにハマった。
以前のGithub関連のpluginだと、accessTokenが使えたんだけど、それができなかった。
仕方ないのでGithubのusername/passwordでcredentialsを追加した。 Scan credentialsを登録しなくても、checkoutはできる。
ただ、commit statusの変更とかができないので、登録することをお勧めする。

Checkout credentialsはSame as scan credentialsで良いと思う。
anonymouseでも問題ない。

デフォだと、username/organaization配下のJenkinsfileが置いてあるrepositoryのbranchが全て対象になるようだけど、Repository name patternや、include/exclude branchesで調節できる。

もちろん個別のrepository単位でも登録することは可能。

ビルド・トリガ

f:id:hsbrysk:20160428172948p:plain

ひとまず"Periodically if not otherwise run"で1min intervalで動かしてみる。

1minだとJenkinsを虐待しすぎな気がするけど、ひとまず強気に行く。
この辺、以前はGithubからweb hookもらってたりしてたんだけど、Pipelineを使用したときもできるのかは不明。

登録完了

でも、Jenkinsfileがあるrepositoryがないので、emptyだよと言われる。

f:id:hsbrysk:20160428173306p:plain

Jenkinsfileを書いてみる

よっしゃJenkinsfile書くぞ!
ひとまず手探りにこんなのを書いてみた。

基本的には、今までUIで設定していたものをcodeに落とし込んでいけば良い。

#!groovy

node {
    step([$class: 'GitHubSetCommitStatusBuilder'])

    stage 'Checkout'
    checkout scm

    stage 'Build and test'
    env.PATH = "${tool 'maven3.3.9'}/bin:${env.PATH}"

    try {
        echo "Build and test ${env.BRANCH_NAME}"
        sh 'mvn clean test'
        currentBuild.result = 'SUCCESS'
    } catch (err) {
        currentBuild.result = 'FAILURE'
    }

    stage 'Notify'
    step([$class: 'GitHubCommitNotifier', resultOnFailure: 'FAILURE'])
    
    // And notify Hipchat, LINE bot or Slack...etc
}

行っていることは次の通り。

  • GitHubSetCommitStatusBuilderを実行する
  • repositoryからcheckoutする
  • mavenでtest実行する
  • GitHubCommitNotifierを実行する

env.BRANCH_NAMEで現在のbranchが取得できるので、もしもdevelop branchだったらdevelop環境にdeployする処理を記述しても良い。

その辺はDSLで自由に書けるみたい。

Jenkinsfileをrepoにpushする

Jenkinsfileがpushされると、Jenkinsがscanするときに発見してrepositoryが出現するようになる。

f:id:hsbrysk:20160428174726p:plain

repositoryをclickすると、各branchやPRも勝手に出現する。
例えば、masterとdevelop branchがあるrepositoryならこんな感じ。

f:id:hsbrysk:20160428174929p:plain

各branchにpushしてみる

各branchにpushしたりすると、ちゃんとJenkinsfileの内容が実行された。

PR出してみる

同一repository上でPRだしたとき

remote branchをpushしたタイミングで、このようにjenkinsのほうにも登録される。
例えば、tmp2っていうbranch nameでPR出すとこうなる。

f:id:hsbrysk:20160428175017p:plain

PRのbranchに対してテストを実行した結果が成功だったときは"All checks have passed"と表示される。
このあたりはGithub pull request builderとかと一緒。

f:id:hsbrysk:20160428173920p:plain

もしも失敗したときは、"All checks have failed"と表示される。

f:id:hsbrysk:20160428173956p:plain

Github pull request builderにあった「test this please」とcommentに書くとtestを実行してくれ るような機能とか、結果をcommentに書くやつも頑張れば出来る気はする。

forkしたところからPRだしたとき

fork先からPRだしたときは、"Pull requests"のタブに登録されるようだ。

f:id:hsbrysk:20160428175117p:plain

PRがcloseされると、ここから自動的に削除された。

テストの成功時と、失敗時の振る舞いは同一repositoryからのPRと同じ。

Jenkinsfileを書く上で参考になるやつ

公式document

公式document以外で参考になったもの

所感 / まとめ

色々と設定が簡単になった。嬉しい。
これで1回username/organaizationを登録してしまえば、それ以降は全てJenkinsfileで管理できるので、良い。
repository追加するたびにポチポチする地獄から解放される。

ジョブの設定もversion管理されて良い。
さよならJobConfigHistory plugin。

Jenkinsのジョブ設定が秘伝のタレ化してしまうリスクもなくなる気がする。
しかし、Jenkinsfileが秘伝のタレ化する未来がちょっとだけ見えた。