色々なjenkins pluginがあって色々なやり方があるので混乱してやや苦労した。
あたり前の話かもしれないが、gitlab-pluginを使って連携させた時に、呼び出し元のPUSHの情報等は環境変数に入っている。
それに気づかずにどうすればよいのかを相当悩んだ。公式ドキュメントを読むの大事。。
今回使うjenkinsのpluginは
- gitlab-plugin(1.5.4)
- slack-plugin(2.3)
- pipeline-utility-steps-plugin(2.0.2)
やりたいこと
シーケンスを起こすと次のようになる。
gitlabからJenkinsProjectへのhook
ブランチ名で規約を作って、そのブランチをPUSHした時に限りJenkinsが動作して欲しい。
Jenkinsでの設定
ここではpipelineプロジェクトを選択しているが、ビルドトリガの存在するプロジェクトなら何でもよい。
赤で塗りつぶした部分がgitlabがリクエストするJenkinsのURLなので控えておく。Jenkinsはプライベートアドレスでhttpで動作している。
Secret tokenも適宜Generateして控えておく。
feature/build_hoge
などという名前のブランチがPUSHされた場合に動作する設定だ
gitlabからのwebhookを許容するにはもしかしたらグローバルセキュリティの設定 > CSRF対策
のチェックを外す必要があるかもしれない。(自分の環境ではチェックを外す必要があった。)
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での動作を記述している。
JenkinsからSlackへのメッセージ送信
Declarative Pipelineの書式はここを参照のこと。
Dockerと組み合わせると幸せになれる。
slack-pluginを使うと手軽にslack通知できるようになる。slackのワークスペースにJenkinsアプリをインストールするのとJenkinsでのslack-plugin設定が必要だがここでは説明しない。
slack通知の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はこちら