Jenkinsのpipelineのスクリプトの書き方まとめ

Jenkins2.0以降Pipelineが標準機能となり、 ビルド同士の関係もスクリプトで管理しやすくなった。

PipelineのスクリプトはGroovy(JavaVM上で動く動的プログラミング言語)で書く必要があり、 GroovyにもJavaにも明るくない人にとってはちょっとハードルが高いのだが、柔軟性があるので慣れてしまえばとても便利。

最近すこしpipelineのスクリプトを書くことがあったので、忘れないうちにまとめておく。

サンプルスクリプト

pipelineについてまずざっくりとした雰囲気をつかみたい方はJenkins公式pipeline紹介ページを読もう。

今回説明するのをだいたい詰め込んだ自分のサンプルスクリプトを最初にはっておく。

def repository = "git@{....}.git"
def github_credential = '{credentialsのid}'

pipeline {

    agent {
        // どのノードを使うかの宣言
        label '{masterとか}'
    }

    environment {
        // credentialsに登録している鍵を取ってきて環境変数に入れる
        XXX_PASSWORD = credentials('XXX_PASSWORD')
    }

    stages {
        stage('cleanup') {
            steps {
                deleteDir() // Clean up workspace
                sh "mkdir log/"
            }
        }

        stage('clone') {
            steps {
                git([branch       : {....}},
                     credentialsId: github_credential,
                     url          : repository])
            }
        }

        stage('parallel jobs') {
            // task1とtask2を並列実行
            parallel {
                stage('task1') {
                    // TEST_BUILDというパラメータがtrueだった時のみ実行
                    when {
                        expression {
                            env.TEST_BUILD == 'true'
                        }
                    }
                    steps {
                        sh '{....}'
                    }
                }
                stage('task2') {
                    steps {
                        sh '{....}'
                    }
                }
            }
        }


    post {
        always {
            script {
                if (env.TEST_BUILD == 'false') {
                    // スクリプト書きたいときはこんな感じ
                }
            }
        }
        success {
            // 成功したときの処理
            echo 'success :)'
        }

        failure {
            // 失敗したときの処理
            sh '{....}'
        }
    }
}

二種類の書き方

Jenkinsfileの書き方はDeclarative PipelineScripted Pipelineの2つの書き方がある。

検索したりサンプルを読んだりする場合に、 違う方の書き方しているものをコピペしたりすると動かないので注意。

JenkinsはDeclarative Pipelineの方の書き方を推奨しているのでそのほうが良いと思う。サンプルもそっちで書いている、

Declarative Pipeline

Declarative Pipelineでは必ず最初に pipeline {}が来る。 pipelineの下には、以下に説明するselections directives stepsが来る

Selections

Selectionsは1つ以上のDirectivesやstepsを子要素に持つ。

要素 何の子要素か
agent どこの環境/slaveで実行するか pipeline, stage
post タスク終了時の成功・失敗したときの処理。 pipeline, stage
stages pipeline以下にstageを書く時に親要素として必要 pipeline
steps stage以下にstepsを使う時に親要素として必要 stage

Directives

stageやpipeline直下に来る要素。 説明は特に自分がよく使うもののみ。

要素
environment 同レベルの環境に環境変数を設定する
options
parameters
triggers pollingするタイミングとか設定できる
stage タスクの単位
tools
when 同レベルにあるstepsを実行する条件

steps

echoをはじめgitslackなどPipeline Steps Referenceにある全てのコマンドが書ける(対応したプラグインが必要)。

また、stepsの中でifとかdefとかforとかのスクリプトを書きたいときはscript要素の中に入れる必要がある。

Scripted Pipeline

Scripted PipelineDeclarative Pipeline ちょっとテストしたいときとかにこちらを書いている。 あまり自分は書かないのでこちらの書き方をしたい方はドキュメントを読んで下さい(´・ω・`)

stageの並列実行

stageを並列で実行したいときはstages以下でparalell {}要素を宣言し、 その中にstageを複数宣言することでそれらを並列実行してくれる

最後に

groovyじゃなくてyamlみたいにかけたら簡単なんだけどなぁ。 まだあんまり使いこなせてないので、認識が間違ってる所あればおしえてくださいm( )m

jenkinsにsnippet generator(下図)っていうのがあって最初は簡単にかけるのだけど、これにはsteps, directives, selectionsが全部入っていて適当に書くと動かないので注意。 steps, directives, selectionsの関係を理解して書く必要がある。 f:id:cocodrips:20171023204501p:plain

余談

最近TreasureData製のワークフローエンジン「Digdag」をしばらく触ってみたのだけど、 あちらはyamlで書けるので書くのがとても簡単だった。あとGUI一切触らずに全部スクリプト出かけるのは良い。 しかしDigdagはまだバージョンが0.9(2017/10現在)で、バグが多くドキュメントも整備されていないため、 運用に使えるのはもう少し後かな・・・という感覚。