Jenkins Shared Libraryで快適 Jenkins 生活？

#Jenkins Shared Library で快適 Jenkins 生活？

この記事は ACCESS Advent Calendar 2018、第 15 日目の記事です。
今日も元気にCIぶん回す@bols_blueです。

## Jenkins Shared Librariesとは
Jenkins 2.0 になって新たに Jenkins　Pipeline が使えるようになり、レポジトリに Jenkinsfile をおくだけでビルドの設定ができるようになりました。
り GitHub Organization Plugin と組み合わせればいちいち Jenkins の画面を開かなくてもレポジトリの検出、ジョブの作成、プルリクエスト毎のビルドジョブの作成、ビルドの設定・実行をやってくれるので便利になったと思います。

しかし、メンテナンスの問題は依然として存在していて、運用が長くなれば同じような Jenkinsfile が増えていきます。
ここで

- プラグインの修正で動作が変わった
- 過去の自分の作った Jenkinsfile が自分で見ても微妙…

といったような事になると全部のレポジトリの Jenkinsfile を直して回ると行った **Jenkins 修行僧によるお遍路**が発生してしまいます。

~~「お遍路はもう嫌だ！！！」~~ と叫ぶ羽目になる前に使っとくと良いと思います。
まぁ、私は手遅れでこれから Shared Library 置き換えるお遍路の旅が始まるぜよ…

Jenkins の Declarative Pipeline で Shared Library を使ってみようとおもいます。

## Shared Library を書いてみる

### 公式のサンプルからディレクトリ構成の解説

ソースコードの構成は下記の様な構成にできます。
**できます**というのもかんたんなステップを作るだけであればvarsだけで十分です。

```
+- src                     # Groovy ソース
|   +- org
|       +- foo
|           +- Bar.groovy  # for org.foo.Bar class
+- vars
|   +- foo.groovy          # 'foo' のステップ
|   +- foo.txt             # 'foo' のステップのヘルプ
+- resources               # resource files (external libraries only)
|   +- org
|       +- foo
|           +- bar.json    # リソースファイル

```

公式のサンプルコードをそのままやっても芸がないの＋jenkinsの中でshellである程度実装している人向けにちょっと修正してリソースの中にあるシェルスクリプトを読み出して実行するサンプルを作ります

### リソースの中にあるシェルスクリプトを読み出して実行するサンプル

ディレクトリ構成は以下のようになっています。

```
├── resources
│   └── jp
│       └── lnc
│           └── jenkins
│               └── libs
│                   └── my_shell.sh
└── vars
    └── runMyShell.groovy

```

**vars以下のファイルはファイル名の先頭は小文字**です。
必須ではないですが正しく認識されないケースがあるので気をつけてください。


```groovy:runMyShell.groovy
def call() { 
   def myShell = libraryResource 'jp/lnc/jenkins/libs/my_shell.sh' 
   return sh(myShell) 
} 
```

```shell:my_shell.sh
ls
ls -la
```

以上です。
簡単ですね。

## Shared Library のセットアップ
Shared Library はプラグインと違って公式の配布に頼らなくてもgitやsvnなどのSCMから直接配布することができます。

利用するライブラリにJenkinsからアクセスが可能であればJenkinsの設定画面から追加することができます。
以下のような設定画面から設定できます。
公開してあるレポジトリを利用する場合は図中の2つの項目を設定すればセットアップは完了です。
![Jenkijns-Pipeline-Library.png](https://qiita-image-store.s3.amazonaws.com/0/8707/59601c06-7927-84d2-fe66-c71572ecbebc.png)

各設定項目は以下のようになっています。

| 設定項目名 | 設定内容 | 画像での表示 | 
|:--|:--|:--|
| Name | ライブラリ名です。＠Libraryでインポートする識別子です。 | bols-blue-org |
| Default version | ＠Library でバージョンを指定しない場合に使われるブランチ、またはタグを指定します。 | master |
| Load implicitly | オンにすると ＠Library　で明示的にインポートしなくても呼び出しが可能になります | OFF |
| Allow default version to be overridden | ＠Library で読み込む場合にバージョンの指定を許可するか。オフの場合、常にDefault versionで指定したバージョンが使われます | ON |
| Include ＠Library changes in job recent changes | ONにするとライブラリ内の変更がビルドのチェンジセットに含まれます。 | ON |
| Retrieval method | ライブラリを取得するためのSCMの設定です | git |

これでセットアップは完了なので Jenkinsfile を書いていきます
まずは全体です

```groovy:Jenkinsfile
@Library('bols-blue-org') _

pipeline {
    agent {
        docker { image 'node:7-alpine' }
    }
    stages {
        stage('Test') {
            steps {
                runMyShell()
            }
        }
    }
}
```

下記のコードでライブラリをロードしています。
このときbols-blue-org@vx.x.xなどという形でタグやブランチを指定できます。

```groovy
@Library('bols-blue-org') _
```

この記事とはあまり関係ないですがdocker image上で実行します。

```groovy
    agent {
        docker { image 'node:7-alpine' }
    }
```

ステージとステップの定義を行いstepsでrunMyShellのカスタムステップを実行します。

```groovy:
    stages {
        stage('Test') {
            steps {
                runMyShell()
            }
        }
    }
```

**引数がない場合は呼び出し時に()をつけないとエラーになります**ので気をつけましょう。

以上の設定で実行してみましょう。

![Screenshot from 2018-12-15 16-50-29.png](https://qiita-image-store.s3.amazonaws.com/0/8707/296ff119-88bd-93ad-7fed-801105a4ae91.png)

できました。
これで色んな所に点在してしまったshellやJenkinsfileを一元管理できますね。



## 終わりに

bitbucketやgitlabがSCMとCI環境を含んだ環境を提供し始めて段々とCIサーバー単品で構築、運用の場が減っていくのかなと感じる昨今ですがJenkinsの記事です。

参考
[公式のパイプラインの概要（英語）](https://jenkins.io/doc/book/pipeline/)
[公式のshared-librariesのドキュメント（英語）](https://jenkins.io/doc/book/pipeline/shared-libraries/)
[公式のDeclarative Pipelineのシンタックス（英語）]
(https://jenkins.io/doc/book/pipeline/syntax/)
[公式の他のプラグインから提供されるステップのドキュメント（英語）]
(https://jenkins.io/doc/pipeline/steps/)

[もう少し実用的な例（通知をパイプラインからshared-librariesに置き換える）]
(https://jenkins.io/blog/2017/02/15/declarative-notifications/)

[Jenkins2のPipline参考リンク集]
(https://qiita.com/Jenkins_BBA/items/bc60a8b98b4665a75755)