Jenkins の Multibranch Pipieline を試した
前回、Jenkins でジョブをスクリプト形式で書ける Declarative Pipeline という記法を試した。
今回は、このスクリプトファイルを複数のブランチに適用しやすくするための Multibranch Pipeline というモノを試してみる。
Multibranch Pipeline とは
通常の Pipeline でブランチごとにジョブを実行したい場合、Pipeline スクリプトファイル内でトリガーの契機となったブランチを判定したりする必要があった。この時、ワークスペースは全部ランチで共有されており、ブランチごとに異なる依存ライブラリを扱ったりしている時に不都合が出やすかった。
マルチブランチ・パイプラインは、Git リポジトリと自動連携して複数ブランチを個別に管理してくれる仕組みだ。スクリプトファイル内でブランチを選択してチェックアウトする必要はなく、Git リポジトリへの Push を検知して自動的に対象ブランチ向けのジョブを実行してくれるのだ。
Multibranch Pipeline を作ってみる
まずは Jenkins 管理画面のメニューから「新規ジョブ作成」を選び、「Multibranch Pipeline」を作る。
設定画面での設定項目は以下のとおり。
- Branch Sources
- 「Add source」ボタンより「Git」を選び、対象のリポジトリを設定する。GitHub との連携時は「GitHub」より設定する。
- 「高度な設定」ボタンを押すと、「対象ブランチ」「対象外ブランチ」を指定できる。ワイルドカードが使用できるので、「
feat/
で始まるブランチは Jenkinsfile が存在してもジョブを実行させたくない」場合は、「対象外ブランチ」に「feat/*
」と設定すればよい。
- Build Configuration
- リポジトリ中の Jenkinsfile のパスを指定する。大抵はルートディレクトリに「Jenkinsfile」という名前でスクリプトファイルを置くと思うので、そのままで良い。
- あとはお好みで「不要アイテムの扱い」など。
ここまで設定できたら、対象のリポジトリのルートディレクトリに Jenkinsfile
を作り、以下のように実装してみよう。
pipeline {
agent any
stages {
stage('npm install') {
steps {
nodejs(configId: '★', nodeJSInstallationName: 'my nodejs') {
bat 'npm install'
}
}
}
stage('UT 実行') {
steps {
nodejs(configId: '★', nodeJSInstallationName: 'my nodejs') {
bat 'npm test'
}
}
}
}
}
内容は前回の記事で作った「npm install
後に npm test
を実行する」というジョブのスクリプトとほぼ同じ。違うのは、「Git チェックアウト」の stage
がなくなったこと。ブランチのチェックアウトはジョブが勝手にやってくれるので、Jenkinsfile での指定は不要なのだ。
このファイルを git add
・git commit
して、git push
してみよう。Git リポジトリとの連携ができていれば、Jenkins のジョブが自動的に実行されるはずだ。
試しに、別の名前のブランチを新たに作って git push
してみよう。先程のブランチのジョブとは別のワークスペースができ、当該ブランチに対するジョブとして実行される。ブランチ別にサブジョブとして管理されるので、Jenkins の管理画面としても見やすい。例えば「master ブランチはテストをクリアしているが、feat/test1
ブランチはテストが失敗している」といった見極めも容易だ。
特定ブランチのみ異なる Jenkinsfile を実行させる
特定のブランチのみ、同リポジトリ内の Jenkinsfile ではなく、別リポジトリで管理している Jenkinsfile を実行する方法。
実はサブジョブも一つの Pipeline ジョブとして扱うことができ、ブランチごとに個別の設定が可能なのだ。
マルチブランチ・パイプラインの「Branches」から任意のブランチを選択し、「設定の参照」に移動する。すると通常の Pipeline ジョブとほぼ同等の設定画面が現れるはずだ。
ココで最下部にある「Pipeline」のプルダウンにて、「Pipeline from multibranch configuration」から「Pipeline script」を選べばその場にスクリプトが書けるし、「Pipeline script from SCM」を選択して別リポジトリを選択すれば、異なる Jenkinsfile を実行できる。
例えば「develop ブランチまでは UT を実行したいが、master ブランチではイチイチ UT を回す必要はない。master ブランチへの Push 時はリリース作業を行う別のスクリプトを実行させたい」といった場合に利用できるかと思う。
ただし、Multibranch Pipeline の設定に沿わないブランチが出てくるのはあまり管理しやすい状態ではないので、多用は控えたい。
特定のブランチのみ実行する stage
を書く
次は、1つの Jenkinsfile 内で、ブランチを判別して特定のブランチのみ処理を行わせる方法。
when
・branch
というシンタックスを使って、以下のように書けば良い。
pipeline {
agent any
stages {
stage('master ブランチのみ処理する') {
when {
branch 'master'
}
steps {
echo 'master ブランチのみ実行します'
}
}
stage('feat/ 始まりのブランチのみ処理する') {
when {
branch 'feat/*'
}
steps {
echo 'feat/ 始まりのブランチのみ実行します'
}
}
}
}
このようなスクリプトにすると、master ブランチで実行された場合は「master ブランチのみ処理する」の stage
のみ実行され、「feat/ 始まりのブランチのみ処理する」stage
はスキップされる。
branch 'feat/*'
のようにワイルドカードも使える。Jenkins 管理画面における「対象ブランチ」「対象外ブランチ」の書き方と同じだ。
not { when { branch
という構造にすると、当該ブランチ以外なら実行する、という stage
も書ける。
こちらもあまり多用すると、1つの Jenkinsfile に条件分岐が多く登場し、こんがらがるので、最低限に留めたい。
Multibranch Pipeline のジョブの後に別のジョブを実行する
Multibranch Pipeline のジョブの後に、別のジョブを実行するためには、次のように設定する。
後続のジョブの設定にて、「Build Triggers」→「他プロジェクトの後にビルド」を選択し、対象プロジェクトを「【マルチブランチ・パイプライン名】/【ブランチ名】」と指定する。例えば「my-multi/master
」といった形だ。
単に「my-multi
」とマルチブランチ・パイプラインの名前を指定するだけではダメで、入力補完でもこの時点までは入力エラー扱いになるので指定できないかのように見えるが、スラッシュ /
まで入力すると候補が登場する。
コレで、「Multibranch Pipeline を使って全ブランチで UT を実行するが、master ブランチのみはその後に別のリリースジョブを実行する」といった設定が可能になる。
おわり
なかなか Jenkins も奥が深い…。ジョブの構成やスクリプトファイルの管理方法に色々悩むが、あんまり綺麗に構造化しきろうとは思わない方が良いのかも。