【Jenkins】Declarative Pipeline入門



新卒の@Toriyabotです。
情報系の学部出身ではないのですがエンジニアとして入社し、最近では弊社のCI環境の改善を行なっています。
その過程でJenkinsのPipeline機能の導入を行なったのですが、これについて簡単に紹介したいと思います。

# Pipelineとは
Jenkinsはビルドやテスト、インスペクション、デプロイ(まとめてビルドと総称)などを自動化して「継続的インテグレーション(CI)」をサポートするツールですが、この自動化された一連の流れを定義するために導入されたのが[Pipeline](https://jenkins.io/doc/book/pipeline/)です。
ジョブの新規作成画面から選ぶことができます。
![スクリーンショット 2017-12-14 21.26.48.png](https://qiita-image-store.s3.amazonaws.com/0/66517/eef73fad-9a88-0e5d-4013-b9eff6f30cec.png)


## ビルドスクリプトの一連の流れをJenkinsfileに記述する
Pipelineでは"ビルド"の流れをJenkinsfileと呼ばれるgroovyベースのDSLで記述します。
groovyのコードとして書くことで、今まで設定できなかった項目も自由に記述できますし、何よりも複雑になりがちな一連のビルドの流れをJenkinsfileとしてバージョン管理できることが大きな利点だと思います。
## Scripted PipelineとDeclarative Pipeline
ちなみにPipeline Plugin 2.5までは文法として**Scripted Pipeline**という書き方が使われていましたが、2.5以降は**Declarative Pipeline**という書き方が推奨されるようになりました(部分的にScripted Pipelineを混ぜることもできます)。
情報を検索するときにはScripted/Declarativeの違いに注意する必要があります。

## サンプルコード
以下に示すサンプルもDeclarative Pipelineのスタイルで書かれています。
コメントを多めにしたので何をしているかはわかりやすいのではないかなと思います。

```groovy:Jenkinsfile
#!groovy
pipeline { // Declarative pipelineであることを宣言する
  agent any // どこで実行するか等の情報(どのノードか、どういうdocker imageかとかを指定する)
  stages {  // Stageを列挙する
    stage('チェックアウト') { 
      steps { // stageは必ずstepsをもつ
        // Slack通知
        // グローバルな環境変数がenvに入っている
        slackSend color: "good", message: "${env.JOB_NAME} - #${env.BUILD_NUMBER} Started! (<${env.BUILD_URL}|Open>)"
        // Githubのprivateリポジトリを使う時は認証情報の記述が必要
        checkout([$class: 'GitSCM', 
          branches: [[name: '*/master']],
          doGenerateSubmoduleConfigurations: false,
          extensions: [], 
          submoduleCfg: [], 
          userRemoteConfigs: [[credentialsId: 'idだよ', url: 'git@hogehoge']]
        ])
      }
    }
    stage('環境設定') {
      steps {
        sh './prepare_env.sh'
      }
    }
    stage('テスト') { 
      parallel { // parallelはstageの直下に書く
        stage('フロントテスト') {
          steps {
            sh './front_test.sh'
          }
        }
        stage('サーバサイドテスト') {
          steps {
            sh './server_test.sh'
          }
        }
      }
    }
  }
  post { // ビルド終了後の処理はここに書く
    always { // ビルド終了後、必ず行う処理
      junit "junit_output.xml" // 出力されたテスト結果ファイルを読み込む
    }
    success { // 成功した場合
      postBuildSlackSend("good", "SUCCESS")
    }
    failure { // 失敗した場合(どこかのステップでエラーを吐いた場合)
      postBuildSlackSend("danger", "FAILURE")
    }
    aborted { // 中断した場合
      postBuildSlackSend("warning", "ABORTED")
    }
    // changed, unstableもあるよ！
  }
}

// 自身で定義した関数の例
def postBuildSlackSend(bar_color, result) { 
  slackSend color: bar_color, message:"${env.JOB_NAME} - #${env.BUILD_NUMBER} ${result} after ${currentBuild.durationString.split(" and")[0]} (<${env.BUILD_URL}|Open>)"
}
```

# コード記述のためのサポート: コードジェネレータが使える！
さて、このコードをいざ自分で書くとなるとgroovy知らないし困ったな、みたいな気持ちになりますが、そういう人でもすぐに使えるようにコードスニペットを自動で生成してくれる機能がJenkinsにはついています。

ジョブの「設定」画面から「Pipeline Syntax」というリンクを開きます。
![スクリーンショット 2017-12-13 22.32.22.png](https://qiita-image-store.s3.amazonaws.com/0/212905/6283569b-15af-9861-0b1f-733f417a325b.png)
「Snippet Generator」が開きます。これはcheckout処理を行うコードを生成しようとしているところです。
こういった必要事項を入力するだけでコードを生成する機能が、結構な数、用意されているので意外とすぐ、使えるJenkinsfileが出来上がるのではないでしょうか。
![スクリーンショット 2017-12-13 22.32.52.png](https://qiita-image-store.s3.amazonaws.com/0/212905/2197fc23-a8d4-33a1-7e89-bd566c616de7.png)

# 結果の可視化: Stage View
Jenkinsの推奨プラグインである、Stage View Pluginを使うとPipelineを可視化することができます。
各Stageでの所要時間のところからログ（の末尾部分）を出すこともでき、結果の要約を簡単に確認することもできます。
どこのステップに時間がかかっているか一目瞭然なので、CIの高速化を目指す場合などに大変便利です。
![スクリーンショット 2017-12-13 11.41.24.png](https://qiita-image-store.s3.amazonaws.com/0/212905/b8ef3de8-4b02-cbd5-76ea-c78759429cc6.png)

# まとめ
Pipelineを使うとビルドの流れをコードとして管理できるだけでなく、サクッと並列処理が書けたり複数マシンをまたがるような処理もシンプルに書けたりという利点があります。他にもビルドの途中でJenkinsが終了しても、Pipelineで作成したジョブだったらJenkinsが途中で終了してしまっても、Jenkinsを起動し直せばジョブを継続できるようになっています。

# 所感
実際にパイプラインのジョブを運用してみて、限られた計算資源しかない中、並列処理を行いビルドの実行時間を短くできたのはよかったです。またGUIで行う大量の設定をコードに落とし込んでバージョン管理できるようになったのは安心感がありました。Stage Viewも現代的なUIで良いですね。

皆さんもPipelineで快適なJenkins生活を送りましょう！