gitlabからjenkinsを利用する(意図したブランチをJenkinsプロジェクトでビルドしたい)

色々なjenkins pluginがあって色々なやり方があるので混乱してやや苦労した。

あたり前の話かもしれないが、gitlab-pluginを使って連携させた時に、呼び出し元のPUSHの情報等は環境変数に入っている。

それに気づかずにどうすればよいのかを相当悩んだ。公式ドキュメントを読むの大事。。

今回使うjenkinsのpluginは

- gitlab-plugin(1.5.4)
  - https://github.com/jenkinsci/gitlab-plugin#defined-variables
- slack-plugin(2.3)
  - https://wiki.jenkins.io/display/JENKINS/Slack+Plugin
- pipeline-utility-steps-plugin(2.0.2)
  - https://github.com/jenkinsci/pipeline-utility-steps-plugin

# やりたいこと
シーケンスを起こすと次のようになる。

![gitlab-jenkins.png](https://qiita-image-store.s3.amazonaws.com/0/105926/bf387f15-8cf0-3139-5d06-c96a30c8913a.png)

# gitlabからJenkinsProjectへのhook

ブランチ名で規約を作って、そのブランチをPUSHした時に限りJenkinsが動作して欲しい。

## Jenkinsでの設定

ここではpipelineプロジェクトを選択しているが、ビルドトリガの存在するプロジェクトなら何でもよい。

赤で塗りつぶした部分がgitlabがリクエストするJenkinsのURLなので控えておく。Jenkinsはプライベートアドレスでhttpで動作している。

Secret tokenも適宜Generateして控えておく。

`feature/build_hoge`などという名前のブランチがPUSHされた場合に動作する設定だ

gitlabからのwebhookを許容するにはもしかしたら`グローバルセキュリティの設定 > CSRF対策`のチェックを外す必要があるかもしれない。(自分の環境ではチェックを外す必要があった。)

![01.png](https://qiita-image-store.s3.amazonaws.com/0/105926/ddbbafb8-9f0e-2e97-9113-ae3c2dc55e7a.png)

## gitlabでの設定

プロジェクトの設定からwebhookを追加する。

URLとSecretTokenには先程控えたものを設定する。TriggerはPush eventのみを設定している。

SSL Verification(Enable SSL verification)にはチェックを入れたままだ。

`Add Webhook`を押して設定を追加する。

Testして疎通がとれればOK。403エラーの場合はJenkinsのCSRF対策を解除することで解決されるかもしれない。

Testボタンからのテスト実行はmasterブランチが環境変数に加えられるようで、先のJenkins側の設定だとプロジェクトは実行されない。

かわりに`Jenkinsの管理 > システムログ`で確認できる。

# Jenkinsの設定

ブランチの指定はgitlab-pluginによって設定された環境変数を利用している。

gitlabからはPUSH毎にwebhookがJenkinsにリクエストされるが、gitlab-pluginの設定で`feature/build.*`という命名規約にそったブランチのPUSHしか対象にしない。

また、`Declarative Pipeline`を利用しているので、gitlabプロジェクトのどのファイルを読み込むかという設定のみで住んでいる。

ここではJenkinsfileにJenkinsでの動作を記述している。

![02.png](https://qiita-image-store.s3.amazonaws.com/0/105926/ce3a7f7a-e5f8-e507-3db5-7381dc4c8081.png)

# JenkinsからSlackへのメッセージ送信

Declarative Pipelineの書式は[ここ](https://jenkins.io/doc/book/pipeline/syntax/)を参照のこと。

Dockerと組み合わせると幸せになれる。

slack-pluginを使うと手軽にslack通知できるようになる。slackのワークスペースにJenkinsアプリをインストールするのとJenkinsでのslack-plugin設定が必要だがここでは説明しない。

slack通知の[attachments](https://api.slack.com/docs/message-attachments)を利用するにはJSONを利用しなければならないが、あまりスマートでないやり方でしか自分は書けなかった。

`readJSON`や`readFile`を使うにはpipeline-utility-steps-pluginを使う必要がある。

また、Decralative Pipelineにはそれらを直接記述できないので、scriptブロックで囲い、pipeline scriptの書式で記述する必要がある。

```
pipeline {
//  agent {
//    dockerfile {
//      args "-it --user root"
//    }
//  }
  stages() {
    stage('my stage') {
      steps() {
        slackSend "ビルド開始 - ${env.JOB_NAME} ビルド#${env.BUILD_NUMBER} (<${env.BUILD_URL}|Open>)"
        echo "execute something!!"

        script {
          def attachments = './attachments.json'
          def json_data = readJSON(file: './default_slack_attachments.json')
          def _text = readFile("./result.txt")


          //slackSendの引数のattachmentsに与えるJSON文字列をあまりスマートでないやり方で生成する
          //  1. json_dataを書き出す
          //     文字列onlyと変数展開した文字列を連結するとGroovyはStringとして認識してくれる
          json_data[0]['title'] = "ビルド終了" + " - ${env.JOB_NAME} " + "ビルド#${env.BUILD_NUMBER} 結果は添付しています" + " (<${env.BUILD_URL}|Open>)"
          json_data[0]['text'] = _text
          writeJSON(file: "${attachments}", json: json_data)

          //  2. json stringとして読み込む
          def attachments_string = readFile("${attachments}")
          echo "${attachments_string}"
          slackSend channel: "#jenkins", attachments: "${attachments_string}"
        }
      }
      post {
        success {
          archiveArtifacts artifacts: 'result.txt', fingerprint: true
          deleteDir()
        }
        failure {
          slackSend "ビルド失敗 - ${env.JOB_NAME} ビルド#${env.BUILD_NUMBER}"
          deleteDir()
        }
      }
    }
  }
}
```

Happy CI & CD!

originは[こちら](https://abcb2.github.io/blog/2018/04/05/gitlab-jenkins)