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現在)で、バグが多くドキュメントも整備されていないため、 運用に使えるのはもう少し後かな・・・という感覚。

EC2(Amazon Linux AMI)へのPostgreSQLのインストールと設定

PostgreSQLの設定にだいぶ手間取ったので、 次からすぐに設定できるようにメモ。

インストール

yumにはPostgresSQLが準備されてないので、rpmからとってくる。 今回インストールしたのはPostgresSQL-9.6.

wget https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-6-x86_64/pgdg-ami201503-96-9.6-2.noarch.rpm
sudo rpm -ivh pgdg-ami201503-96-9.6-2.noarch.rpm
sudo yum install -y postgresql96 postgresql96-server postgresql96-libs postgresql96-contrib
sudo /etc/init.d/postgresql-9.6 initdb
sudo /etc/init.d/postgresql-9.6 start

公式にDL用のコマンドジェネレータがあるので、違うバージョンをダウンロードしたいときはこちらから。 PostgreSQL: Linux downloads (Red Hat family)

常に起動したいときは以下もたたいておく。

chkconfig postgresql-9.6 on

ここまでで、以下のコマンドでpsql(PostgreSQL)に接続できるようになる。

sudo -u postgres -i psql

パスワード設定とアプリケーション用ユーザの設定

PostgresSQLは最初「Unixユーザ名」と「PostgresSQLのユーザ」が一致しないとログインできない Peer認証というのになっている。

Postgresユーザでアプリが起動するとは限らないし、sudoとかしたくない。 新しいユーザを作り、sudoしないでshellからpsqlにログイン&アプリケーションからつなげるようにしていく。

最初はpostgresユーザしかいないのでpostgresユーザで入る

sudo -u postgres -i psql

パスワードの設定とアプリケーション用ユーザの作成

-- パスワードの設定
\password
-- ここでパスワードをきかれるので設定する

-- ユーザを作る
CREATE ROLE ユーザ名 LOGIN CREATEDB PASSWORD 'ここにパスワード';

-- ↑のユーザが管理したいdbを作る
CREATE DATABASE データベース名 OWNER ユーザ名;

ユーザを作ったら、psqlの設定を-Uで選択するユーザをUnixユーザ名と関係なく指定できるよう 以下の設定を変更する。

amazon linuxの場合は以下のパスに設定ファイルがあるが、 OSが違う場合は違うところにあるので注意。

sudo emacs /var/lib/pgsql/9.6/data/pg_hba.conf

以下のように変更

# local   all             all                                    peer
local   all             all                                    md5

# localhostからのアクセスをパスワード認証にしたい場合はこちらも変更
# host    all             all             127.0.0.1/32            ident
host    all             all             127.0.0.1/32            md5

これでパスワード認証ができるように。 詳しい設定方法は以下を見ればわかる。 https://www.postgresql.org/docs/9.6/static/auth-pg-hba-conf.html

設定が完了したらpsqlをリスタートする。

sudo /etc/init.d/postgresql-9.6 restart
# reloadでも大丈夫そう
# sudo /etc/init.d/postgresql-9.6 reload

# 以下でログイン可能に
psql -U ユーザ名 -d データベース名 -h localhost;

PostgresSQLのconnection URI

以上の設定で postgresql://ユーザ名:パスワード@localhost:5432/データベース名 でアクセスできる。

おまけ