Usual Software Engineer

よくあるソフトウェアエンジニアのブログ

Jenkins 2.0 アップデートで本当に知りたいこと

Jenkins 2.0 がリリースされて話題になってからだいぶ時間が経ちましたが、 昨年末に業務で Jenkins 2.0 へのアップデート作業を行ったので、今更ながらよく触るようになりました。

2年前くらいのJava 勉強会?でまともに Jenkins 2.0 の紹介を見てから良いなとは思ってたのですが、 とはいえ紛れもなく Jenkins おじさんなので、クラウドの CI サービスを使うようになってからはなかなか触りたくないもの、という印象が拭えないですよね。 もちろんモダンなデザインになる BlueOcean とビルドパイプラインは目玉なので魅力的なのはわかるのですが。

そんなわけで今回は、そんなよく話される目玉機能の話ではなく、 アップデートする時に本当に知りたいこと をまとめてみようと思います。 個人的な目線のまとめですが、すでに CI サービスや別のプロダクトを使ってる人向けではなく、 元々 Jenkins を使っていてでもなかなか 2.0 にアップデートする気にもなれない人向けに参考になれば幸いです。

5つポイントを挙げます。

既存のジョブは正常に動くの?

アップデートの時に一番気をつけないといけないのは、既存のジョブや設定などが壊れないか、という点ですよね。 Jenkins 1.6 ぐらいから 2.7 ぐらいにアップデートしてみましたが、 基本的に既存のジョブも問題なく動く ことが確認できました。 ただし、ジョブの設定などでプラグイン依存な部分あるので、それらは Jenkins 本体やプラグインのアップデート時に不意に消えてしまうことがあります。 おそらく、 Jenkins 本体アップデート後にプラグインが古いバージョンのままでジョブの設定をいじって保存してしまうなどの操作が影響すると思われます。 この際、プラグインもごっそりアップデートしてから設定をいじるのが良さそうです。

ちなみにパイプラインのジョブとして作り直さなくても、既存のジョブのまま BlueOcean でモダンなUIでジョブ実行と結果確認ができます。 それだけでも Jenkins おじさんが若返ってテンションが上がりますね。

f:id:innossh:20180131205428p:plain

プラグイン増えすぎてない?

Jenkins 2.0 にアップデートしてみると気づくと思いますが、 インストールされているプラグインの種類多すぎwww ってなります。 全体的に プラグインベースで機能を拡張 していこうという方針があるのか、既存のプラグインが複数のプラグインに分割されていたり、 別のプラグインに機能が移行されていたりします。 つまり依存関係が強いプラグインが多いので、アップデートの時に気をつけましょう。 自作プラグインの場合も1つのプラグインの機能はミニマムになるように開発するのが良い感じがします。

f:id:innossh:20180131205440p:plain

新しい形式でジョブを定義した方が良い?

せっかくだから 2.0 に合った新しい形式でジョブを定義してみたいですよね。 何ができるのかというと、

  • GitHub リポジトリと連携させることで、ブランチやプルリクエストごとにジョブを自動生成/実行できる
  • Jenkinsfile にジョブの内容を定義することでジョブをコードで管理できる

この2点が大きいと思います。というかアップデートしたらやるべきですね。 以前までジョブの xml をバージョン管理していた人などは、 Jenkinsfile で可読性も上がって GitHub 連携で自動でジョブ生成してハッピーになると思います。

pipeline ジョブのサンプルが少ない?

さっそく Jenkinsfile を書こうと取り掛かるわけですが、現在は Declarative Pipeline という形式が推奨されていて これがまたネット上を探し回ってもサンプルがかなり少なさそうです。だんだんと増えていくとは思いますが。 ドキュメントも正直わかりやすいものではないので、試行錯誤して頑張るしかないかもしれません。 あるプラグインの使いたい機能が Declarative Pipeline だと記述できない 、みたいなパターンもあるので結構苦しみます。 とりあえずサンプルを貼っておきますね。

pipeline {
    // ビルド実行時のパラメータを定義できる
    parameters {
        // セレクトボックスのパラメータも定義できる
        choice(
            name: 'TARGET_NODE',
            choices: 'agent-jp\nagent-us',
            description: 'Choose the target slave node (Required)')
        string(
            name: 'TARGET_HOST',
            description: 'Input the target host (Required)')
    }

    // ビルドトリガーを定義できる
    triggers {
        // 標準装備の cron だけでなく Parameterized Scheduler Plugin も使える
        parameterizedCron('''
H 2 * * * %TARGET_NODE=agent-jp;TARGET_HOST=server-01-jp
H 2 * * * %TARGET_NODE=agent-us;TARGET_HOST=server-01-us
''')
    }

    // ビルド実行場所の node を定義する
    // 変数を参照する場合はダブルクォーテーションを使う
    agent { label "${params.TARGET_NODE}" }

    // 環境変数を定義できる
    environment {
        FOO_ROOT = "${HOME}/.foo"
        PATH = "${PATH}:${FOO_ROOT}/bin"
        CREDENTIAL_ID = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
    }

    stages {
        // ビルドのステージを定義する
        stage('Initialize') {
            // 1行1行がビルドのステップとなる
            steps {
                sh "echo FOO_ROOT:${FOO_ROOT}"
                sh 'env'
            }
        }
        stage('Build') {
            steps {
                // SSH Agent Plugin も使える
                sshagent (credentials: ["${CREDENTIAL_ID}"]) {
                    // Pipeline ジョブを作成した時に指定した SCM がチェックアウトされている
                    //checkout scm
                    // カレントディレクトリはそのチェックアウトしたリポジトリのルート
                    // dir で相対パス指定でカレントディレクトリの移動ができる
                    dir(path: 'some/dir') {
                        sh "ssh -F ssh_config ${params.TARGET_HOST} hostname"
                    }
                }
            }
        }
    }

    post {
        always {
            // ビルド実行後に必ず実行。 JUnit テストの実行結果のレポートなど
            //junit 'some/dir/reports/**/*.xml'
        }

        failure {
            // ビルド失敗時に実行。 Slack への通知など
            // BlueOcean Display URL Plugin を使うと通知のリンク先が BlueOcean のURLにできる
            slackSend color: 'danger',
                    message: "${env.JOB_NAME} - <${env.RUN_DISPLAY_URL}|#${env.BUILD_NUMBER}> Failure (${params.TARGET_HOST})"
        }
    }
}

モダンな表示になるのはジョブの画面だけ?

BlueOcean でイケイケになると、モダンな表示にならない管理画面などが悲しい感じになってきます。 今のところその管理画面などはモダンにならないので、 Simple Theme Pluginjenkins-material-theme を設定してマテリアルデザインなモダン UI にしている人が多い気がします。

うちの場合は設定してみたらアイコンなどがガラッと変わって迷子になったので、これはリアル Jenkins おじさん達の評判も良くないだろう(笑)と思い、やめておきました。

代わりに、開発環境用と本番環境用で Jenkins のヘッダの色を変えたい要件があったのでそこのみいじることにしました。 User Content に CSS などを配置すればいいわけですが、それも面倒な人のために CSSGitHub にあげておきました。何の変哲もない、ヘッダの色を変えるだけの CSS ですww

github.com

例えば赤色にしたかったら、これ https://cdn.rawgit.com/innossh/jenkins-simple-theme/v0.0.1/header-red.cssURL of theme CSS に設定するだけです。

https://github.com/innossh/jenkins-simple-theme/raw/master/doc/Screenshot-red.png

おあとがよろしいようで。

まとめ

  • 既存のジョブも正常に動く
  • プラグインの依存関係が増えているので気をつける
  • Jenkinsfile でジョブをコード管理する
  • Declarative Pipeline の書き方は試行錯誤が必要
  • BlueOcean でジョブ画面をモダンに、他の画面は Simple Theme Plugin で