⚰️

Jenkinsを勉強する - Pipelineを使ってみる

2023/02/25に公開

はじめに

前回は ユーザー管理 をやりました。

今回は Jenkins 2.0 で標準プラグインとなった Pipeline を使いたいと思います。
https://www.jenkins.io/doc/book/pipeline/

Jenkinsのジョブは通常1つずつ実行しますが、パイプラインを使うことで ジョブAが終わったらジョブBを実行する ということが出来るようになります。
Groovyという言語で定義されたファイルを元に実行されるのでコードベースで管理が可能です。

Hello World

スクリプトのサンプルに Hello World があるので、パイプラインがどんな機能なのかを体験します。

ジョブはパイプラインを指定して作成します。



スクリプトに設定されいる「try sample Pipeline」を「Hello Wolrd」に変えます。
すると、スクリプトの内容が変わるので保存します。


ビルドを実行すると、以下のように表示が変わります。

コンソール出力を確認すると、パイプラインの内容が分かります。

以上、「Hello World」でした。

構文を理解するとしよう

Pipeline Syntaxを見ることで理解を深めれます。

書き方が2種類あるようで、Pipeline2.5以降はDeclarative Pipelineが推奨になったようです。

Sections

1つ以上のディレクティブまたはステップが含まれます

セクション 説明 指定出来る箇所
agent どの環境(ノード)で実行するか pipeline, stage
post 後処理にstepを追加できる pipeline, stage
stages stageを書くための箱 pipeline
steps ビルドやデプロイなどの処理をここに指定 stage

Directives

pipelineブロック直下やセクション内に指定するやつ

ディレクティブ 説明 指定出来る箇所
environment 環境変数を指定できる pipeline, stage
options pipelineのオプションが使える pipeline, stage(制限つき)
parameters ジョブ設定で指定できるやつ(1回だけ) pipeline
triggers cronなどが使える(1回だけ) pipeline
stage 箱の中のステージ(1個以上) stage
tools toolをインストールしてPATHに配置する
tool→maven, jdk, gradle
pipeline, stage
input ユーザーの入力を受け付ける stage(多分)
when 条件に応じてステージを実行するかどうかを決定する stage

自分なりに書いてみる

ということで、何を書けば良いのか、何が使えるのかを大まかに理解したところで実際に書いて実行してみます。

以下に自分用サンプルを置いておきます。
内容としては、ジョブやbashの実行、並列処理、Slackへの通知をやっています。

自分用サンプル
jenkinsfile
pipeline {
    // エージェントの指定
    agent any
    // 環境変数(グローバル)
    environment {
        ENV_01 = "1"
        ENV_02 = "2"
    }
    // パラメータ設定(1回のみ)
    parameters {
        booleanParam(name: 'touch_job', defaultValue: true, description: '実行か否か')
        booleanParam(name: 'echo_job', defaultValue: true, description: '実行か否か')

    }
    options {
        // パイプラインの実行による出力に時刻も出力してくれる 
        timestamps() 
    }
    stages {
        stage('touch job') {
            // stageを実行するか入力待ちにする
            input {
                /*
                  message: 好きな文言に変更が可能(Required)
                  ok: 実行を許可するときの文言(default: procced)
                  ※拒否する方の文言はパラメータがないため設定できません
                */
                message "Should we continue?"
                ok "OK"
            }
            // 処理の中身を書く
            steps {
                // ジョブを実行する
                build job: 'sample_touch', parameters: [
                    string(name: "file_name", value: "from_pipeline")
                    /*
                      以下の書き方でもOK
                      [$class: 'StringParameterValue', name: "file_name", value: "from_pipeline"]
                    */ 
                    
                ]
            }
        }
        stage('echo bash job') {
            /*
              条件に応じてステージを実行するかどうかを決定します
              以下の場合は、パラメータ:echo_job が true なら実行されます
            */
            when {
                expression {
                    return "${params.echo_job}".contains('true')
                }
            }
            // 環境変数(ローカル)
            environment {
                ENV_01 = "3"
                /*
                  JenkinsのCredentialsに登録しておく
                  idに設定した値で取得が可能
                */
                USER_INFO = credentials('user_info')
            }
            steps {
                echo "${ENV_01} ${ENV_02}"
                // credentialsの値はマスキングされて出力されません
                echo "${USER_INFO_USR} ${USER_INFO_PSW}"
            }
            // stageブロック内でpostを使う
            post{
                always{
                    echo "post step job1(always)"
                }
                success{
                    slackSend color: 'good', message: "'echo bash job' success."
                    echo "post step job1(successful)"
                }
                failure{
                    echo "post step job1(failed)"
                }
            }
        } 
        stage('parallel') {
            //並列処理させたい場合は、'parallel' で stage を囲む
            parallel {
                stage('echo job1') {
                    steps {
                        build job: 'sample_echo', 
                        parameters: [
                            string(name: "string_param", value: "pipeline")
                        ]
                    }
                }
                stage('echo job2') {
                    steps {
                        build job: 'sample_echo'
                    }
                }
            }
            // parallelのstageブロック内でpostを使う
            post{
                always{
                    echo "post parallel after(always)"
                }
                success{
                    echo "post parallel after(successful)"
                }
                failure{
                    echo "post parallel after(failed)"
                }
            }
        }
    }
    // pipelineブロック内でpostを使う場合
    post{
        always{
            echo "post stages after(always)"
        }
        success{
            echo "post stages after(successful)"
        }
        failure{
            echo "post stages after(failed)"
        }
    }
}

PipelineでSlackに通知する

JenkinsにはSlackへの通知を簡単にするプラグイン(Slack Notification Plugin)があります。
ただし、Pipelineの設定にSlackへ通知するための設定がないので、各ジョブ側で設定する必要があります。
またジョブではなく、スクリプト(groovy)で制御したい場合は slackSend というコマンドが使えるためそれを使いましょう。

以下は自分用のメモとして残しておきます。

Slackの設定

  1. app directoryに「Jenkins CI」をインストールする
  2. 対象のチャンネルを指定する

上記まで行うと、セットアップ手順が表示されます。
その中に、以下の情報が記載されているためメモっておきましょう。

  • チームサブドメイン
  • インテグレーション用トークン認証情報 ID

Jenkinsの設定

セットアップ手順を簡略化したのが以下です。

  1. プラグイン(Slack Notification Plugin)をインストールする
  2. Credentialsにトークンを登録する
    種類 スコープ Secret ID 説明
    Secret text グローバル 発行したトークン 任意 任意

システムの設定

プラグインをインストールした後にシステムの設定にSlackが追加されています。
ここでデフォルトの値を指定することが可能です。

設定しない場合は、ジョブやPipelineで使うスクリプト(Groovy)にWorkSpaceやチャンネル等を指定する必要があります。

ジョブ側の設定

「ビルド後の処理で設定」>「Slack Notifications」

  1. 通知させたい条件を選択する
  2. 設定を入力する
    Workspace Credential Channel/member id
    Workspace名
    (メモしたやつ)
    先ほど登録したCredentials 対象のチャンネル
    (省略した場合はデフォルトのチャンネル)
  3. Test Connection を実行する(設定の最後にある)
    成功すれば、Slackへ通知が届きます

おわりに

Pipelineについて簡単に説明しました。
ジョブAを実行した後にジョブBを実行するといった感じの場合に使えそうなツールですね。
並列処理が行えるので、順番に依存しないジョブであれば時間の短縮にもなりそうです。

Dockerで構築したJenkinsだけでやっているので、もう2個ぐらいコンテナを立ててコントローラーとエージェントやりたいなーと思います。
できるのか知らんけど。

Discussion