ほとんど情報がなかったので調べながら書いたメモ。基本的に、公式情報が最もまとまっている。

また、古い情報らしいけど、現状こちらにしか書かれていない項目もある。

基本

現状のJenkinsfileは2通り書き方があって、pipelineがルートになっている場合はDeclarative Pipelineという。この場合は、Groovyスクリプトを直接書くことができず、Groovyを書きたければscriptディレクティブを使う必要がある。この記事では主にこちらを扱う。

pipelineから始まらない場合、Scripted Pipelineといって、この場合は直接Groovyスクリプトも書けるし、node()stage()などの、Pipeline Stepsメソッドも書くことができる。便利そうにみえるけど自由度が高すぎて職人コードになりがち。

Declarative Pipelineの書き方

Jenkinsfileは特定の条件ごとにディレクティブを書いて実装する。ディレクティブの出現順は以下の順番になっている。例えばstagesのすぐ下にagentを書くことはできない。

pipeline {
    // 1行コメント
    /*
     * 複数行コメント
     */
    agent { ... }
    environment { ... }
    options {
        buildDiscarder(...)
        disableConcurrentBuilds(...)
        skipDefaultCheckout(...)
        timeout(...)
        retry(...)
        timestamps()
    }
    parameters {
        string(...)
        booleanParam(...)
        choice(...)
    }
    tools {
        maven '...'
        jdk '...'
        gradle '...'
    }
    triggers {
        cron(...)
        pollSCM(...)
    }
    stages {
        stage {
            agent { ... }
            environment { ... }
            tools { ... }
            when { ... }
            steps {
                //Pipeline Steps Reference参照
                echo 'help'
                sh 'ls'
                script {
                    // 任意のGroovyスクリプト
                }
            }
        }
    }
    steps {
        //Pipeline Steps Reference参照
    }
    post {
        always { ... }
        success { ... }
        failure { ... }
        ...
    }
}

stepsだけの場合は、直接stepsの中に書くものを記述できる。

echo 'help'
sh 'ls'

node()のようにstepsディレクティブの中で子ブロックが現れる場合、そのブロックの中はstepsディレクティブと同じものが書ける。

steps {
    node('slave1'){
        sh 'ls'
        dir('output'){
            sh 'ls'
        }
    }
}

個別の事例

stageの書き方

stage()を使うと、進捗を分けて表示することができるが、インターネットでは2種類の書き方がある。stage単体で書かれているものは古く、推奨されない。

stage 'first'
sh 'ls'

stage 'second'
sh 'pwd'

今はブロックを取るようになっていて、こちらが推奨される。

stage('first'){
    sh 'ls'
}
stage('second'){
    sh 'pwd'
}

ビルドするノードを制限する

agentディレクティブでラベルを指定する。

agent {
    label 'slave1'
}

または、stepsディレクティブでnodeブロックを使う。

steps {
    node('slave1'){
    }
}

環境変数をセットする

environmentディレクティブが使える場合はその中で書く。ここでは、定数またはcredentials()しか使えない。

environment {
    GOPATH = '/home/jenkins/go'
}

または、stepsディレクティブの中でwithEnvブロックを使う。withEnvの中でだけ環境変数が有効になる。

steps {
    withEnv(["GOPATH=${env.WORKSPACE}"]) {
    }
}

Groovyを使ってもっと細かく制御したい場合。stepsディレクティブに直接Groovyは書けないのでscriptディレクティブを使う。

steps {
    script {
        // ここからGroovy
        env.GOPATH = env.WORKSPACE
    }
}

ツールをインストールする

Jenkinsの管理メニューにGlobal Tools Configuration があり、そこで事前にMavenやGoコンパイラなどのバージョンと名前を定義しておくと、toolsディレクティブで、自動でインストールすることができる。

pipeline {
    tools {
        go 'go1.10'
    }
}

Pipeline Syntaxで自動生成したコードはtool name: 'go1.9', type: 'go'のように出力されるが、このままDeclarative Pipelineとして記述するとエラーになる。$type '$name'のように置き換えて書く必要がある。

パラメータ付きビルドにする

parametersに何か書くと、パラメータ付きビルドとして扱われる。params.nameで参照する。

pipeline {
    parameters {
        string(name: 'TARGET', defaultValue: 'Tests', description: '説明')
        choice(name: 'STAGE', choices: 'staging\nproduction', description: '説明')
    }
    stages {
        stage('build'){
            sh "./make.bash ${params.TARGET}"
        }
    }
}

GitHub Organization Folder Plugin環境でスレーブを使ってビルドする

基本的には何もしなくてもプラグインがcloneするが、デフォルトでは(おそらく)Jenkinsマスターのワークスペースへcloneされる。このため、ビルドノードがマスター以外の場合、ビルドするソースコードがスレーブのワークスペースにない状態となる。

stepsディレクティブでcheckoutを使うとslaveのワークスペースへcloneが行われる。

steps {
    checkout scm
}

または最初から、agentディレクティブでラベルを指定しておくと、対象となったスレーブでcloneされる。

pipeline {
    agent {
        label 'slave1'
    }
    steps {
        sh 'ls'
    }
}

特定のディレクトリへcloneする

dir()を使うとカレントディレクトリを変更できるので、移動した後でcheckout scmを実行すればいい。移動するディレクトリが存在しない場合は自動的に作成される。

stage('chekout'){
    steps {
        dir("src/v2"){
            checkout scm
        }
    }
}

GitHub Organization Folder Pluginでcheckoutの動作を変更する

How to Customize Checkout for Pipeline Multibranchによると、checkout scmは、

checkout([
    $class: 'GitSCM',
    branches: scm.branches,
    extensions: scm.extensions,
    userRemoteConfigs: scm.userRemoteConfigs
])

の省略形らしい。Shallow cloneとかcloneするディレクトリを変更する場合は、scm.extensionsに配列でオプションを追加する。

checkout([
    $class: 'GitSCM',
    branches: scm.branches,
    extensions: scm.extensions + [
        [
            $class: 'RelativeTargetDirectory',
            relativeTargetDir: "src/v2"
        ]
    ],
    userRemoteConfigs: scm.userRemoteConfigs
])

checkoutの前にワークスペースをクリアする

checkout scmの前にdeleteDirを使う。

stage('clean'){
    steps {
        deleteDir()
    }
}
stage('checkout'){
    steps {
        checkout scm
    }
}

Scripts not permitted to use methodエラーで動作しない

Jenkinsfileのコードを実行した時、

RejectedAccessException: Scripts not permitted to use method (メソッド名)

というエラーで停止する場合がある。これは、外部のコードを無条件に実行すると危険なので、Script Security Pluginによってsandbox実行されているため、らしい。

外部のコードを制限するための機能なので、Jenkinsfileで回避できるものではない。エラーが発生した後であれば、Jenkinsの管理画面にエラーとなったメソッドの許可を求めるログが出ているので、そこでApprovalボタンを押せば次からはエラーを回避できる。このファイルは$JENKINS_HOME/scriptApproval.xmlに置かれているので、これをコピーしてもいい。

成果物を保存する

postセクションでArchive Artifact Pluginを使えばよい。

pipeline {
    post {
        success {
            archiveArtifacts artifacts: bin/*, fingerprint: true
        }
    }
}

成果物の保存数を制限する

いろいろ書き方はあるが、おそらくoptionsディレクティブを使うのが簡単。

pipeline {
    options {
        buildDiscarder(logRotator(numToKeepStr: '5', artifactNumToKeepStr: '5'))
    }
}

並列ビルドする

stepsparallelを使う。

steps {
    parallel(
        linux: {
            sh './make.bash -t linux_amd64'
        },
        windows: {
            sh './make.bash -t windows_amd64'
        }
    )
}

この例では、./make.bash -t linux_amd64./make.bash -t windows_amd64が並列実行される。

他のジョブをビルドする

buildを使う。

引数のパラメータはJenkinsを置いているフォルダまでのパスを渡す。相対パスの場合は呼び出し元ジョブのディレクトリがカレントになり、絶対パスの場合は$JENKINS_HOME/jobsがルートになる。

steps {
    build '../jobName1'
}

マルチブランチ構成のプロジェクトを呼び出す場合は、内部の階層がブランチごとに切られているので、ブランチ名も必要。

steps {
    build '../jobName1/master'
}

GitHub Organization Folderが管理しているジョブはマルチブランチに近くて、Organizationの下にジョブが作られるので、次のようになる。

steps {
    build '/organizationName/jobs/jobName/master'
}

Jenkinsが管理しているCredentialでssh接続したい

ssh-agentプラグインをインストールするとsshagentブロックが利用可能になる。このブロックの中に記述したコマンドは、Jenkinsが管理している秘密鍵が追加されたssh-agentが動作してる状態で実行される。なのでJenkinsのアカウントでgit pushしたい場合は、以下のように書く。

steps {
    // jenkins_credential_id_strという名前のCredentialを読み込む
    sshagent(['jenkins_credential_id_str']){
        sh 'git push'
    }
}
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.