プロジェクトを運用していると複数のバージョンに複数のJenkinsfileが存在するということはないでしょうか?
私が所属するプロジェクトでも、Jenkinsfileが複数あるのですが、処理自体は共通化できるようなものがほとんどです。
同じような処理ばかりになると、メンテナンスがやりにくくなるので、共有化できないか調べてみました。
すると、共有ライブラリというものをJenkinsに設定できるようで、試してみました。
ディレクトリ構成
共有ライブラリのソースコードをSCMで管理し、Jenkinsに設定することでSCMからソースをチェックアウトして使用することが可能です。
共有ライブラリのディレクトリ構成は以下のようなイメージです。
(root) +- src # Groovy source files | +- org | +- foo | +- Bar.groovy # for org.foo.Bar class +- vars | +- foo.groovy # for global 'foo' variable +- resources # resource files (external libraries only) | +- org | +- foo | +- bar.json # static helper data for org.foo.Bar
重要なのは、src、vars、resourcesフォルダになります。
ディレクトリ | 概要 |
---|---|
src | パイプライン実行時にクラスパスに設定される。クラスを実装する場合、srcフォルダに配置する必要があります |
vars | パイプラインで変数として扱うことができる。vars/log.groovyというファイルにdef test(message)という関数を定義した場合に、log.test "メッセージ" というような使い方が可能です。 |
resources | groovyファイルではないファイル(jsonファイルなど)を配置する。libraryResourceを使ってロードします。 |
srcフォルダの共有ライブラリを使ったパターン
Utilltiesクラスを定義して、クラスをJenkinsfileから呼び出すパターンを実装してみました。
オブジェクトを生成する際に、パラメータを渡しておけばオブジェクトでデータを保持でき、メソッド内でも使用可能です。
src/org/foo/Utillities.groovy
package org.foo class Utilities implements Serializable { def steps def version Utilities(steps, version) { this.steps = steps this.version = version } def checkout() { this.steps.stage("checkout") { this.steps.sh "ls -l" } } def compile() { this.steps.stage("compile") { this.steps.echo "compile " + version } } def deploy() { this.steps.stage("deploy") { this.steps.echo "deploy" } } def test() { this.steps.stage("test") { this.steps.echo "test" } } }
Jenkinsfile
@Library('my-shared-library') import org.file.Utilities def util = new Utilities(this, "1.0"); node() { util.checkout() util.compile() util.deploy() util.test() }
varsフォルダにおいた共有ライブラリを使ったパターン
クラスとは異なり、関数だけ定義することになります。
こちらはこちらでシンプルではあります。
srcフォルダでは、import文を使ってましたが、varsフォルダのスクリプトを使用する場合は、_ を使います。
var/utilites.groovy
def checkout() { stage("checkout") { echo "checkout" } } def compile() { stage("compile") { echo "compile" } } def deploy() { stage("deploy") { echo "deploy" } }
@Library('my-shared-library') _ node() { utilites.checkout() utilites.compile() utilites.deploy() }
最後に
共有ライブラリを初めて試しましたが、スムーズには設定できませんでした。
特に、Jenkinsfileから共有ライブラリの関数やクラスを呼び出すのに手間取ったので、共有ライブラリを作成する際は、簡単なプログラムを共有ライブラリ化して試してみるのをオススメします。
また、共有ライブラリ化することで、Jenkinsfileの定義も小さくなり、クローンコードも無くなり、保守がやりやすくなるので設定の手間よりメリットの方が大きいと思います。
時間を見つけて、プロジェクトのJenkinsfileを共有ライブラリ化しようと思います。