🤖

Jenkinsでのデプロイ完了を実行者宛メンションつきでslack通知するようにした

2024/07/22に公開

はじめに

こんにちは。
SKIYAKIのエンジニアの家(@ie_webengineer)です。

今回やったこと

  1. slackのincoming-webhookを使えるようにする
  2. jenkinsデプロイ完了後に実行するjobの作成
  3. jenkinsユーザー名をslackのメンバーIDに変換する
  4. 変換したメンバーIDを元にメンションつきデプロイ完了メッセージをincoming-webhookでslackへ投稿する

やろうと思ったきっかけ

デプロイする際、jenkinsを使っているのですが、デプロイ完了後自分宛に通知がないと
他作業を途中始めてしまった時にデプロイが完了したことにすぐ気づけない問題がありました。

元々別のプロダクトで今回やったことを他のエンジニアが作ってたこともあり、
Bitfanではそれができていなかったため、勉強がてら自分でやってみました。
※コードをパクって実装してませんw

また、jenkinsにはslack通知するためのプラグインがありますが、
それはjob実行者への通知は少々難しい部分があったためシェルスクリプトで実現した経緯になります。
もちろん何のjobが完了したかはプラグイン使う方が楽なので合わせ技にしました。

・jenkinsのslack通知のプラグイン
https://plugins.jenkins.io/slack/

今回ハマってしまったこと

jenkinsで実行した後、GAS(Google Apps Script)に通知内容を渡してやれば
多少メンテがしやすくコードも書きやすく簡単だと思って取り掛かったのですが、

外部からGASを実行する場合、アクセストークンが必要で
有効期限が無制限にはできないためjenkinsのjobから実行すると数分経つと、
有効期限切れで401エラーになってしまいました。

また、実行可能APIを選択して作ることもできますが、有料になってしまいそうだったため諦めました。

・参考情報
https://qiita.com/Cheap-Engineer/items/f849b9b1c2a4da9e25c1

実装内容

slackのincoming-webhookを使えるようにする

以下記事の新方式で実施すれば簡単にできます。
https://zenn.dev/hotaka_noda/articles/4a6f0ccee73a18

jenkinsユーザー名をslackのメンバーIDに変換する

これが一番悩みどころだったのですが、以下の案が良いかなと考えました。

①jenkinsユーザーのメールアドレスからslackユーザー情報を取得する
②デプロイした最新コミット情報から取得したコミッターメールアドレスからslackユーザー情報を取得する
③slackのユーザーグループ情報からメンバーIDを抜き出し、ベタ書きでjenkinsユーザー名をslackメンバーIDに置き換える

①か②が良かったのですが、無理に頑張る必要もないので
①はjenkinsユーザーのメールアドレスを取得するには管理者権限が必要っぽかったので(自分が管理者ならできそう)諦めました...w
②は純粋にできそうだしテックブログネタ的ではありますが、jenkinsユーザー名だけで事足りそうだったためやめました。

結果的に③で対応しました。

jenkinsユーザー名から変換したメンバーIDを元にメンションつきデプロイ完了メッセージをslackへ投稿する

slackのメンバーID変換は他jobでも利用することになるので共通処理化するためにファイルに閉じた方が良いです。

jenkinsUserId="jenkinsのユーザーID"
apiToken="jenkinsのAPIトークン"
jobUrl="jenkinsのjobのurl"
curl -X GET --user $jenkinsUserId:$apiToken $jobUrl/api/json > jobs.json
url=$(cat jobs.json | jq -r ".builds[0].url")
curl -X GET --user $jenkinsUserId:$apiToken "${url}api/json" > detail.json
# job実行履歴情報からjenkinsのユーザー名取得
userName=$(cat detail.json | jq -r ".actions[0].causes[0].userName")

# jenkinsユーザー名をslackのメンバーIDに変換
case "$userName" in
  "skiyaki-user-name1")
    slackMemberId="メンバーID1"
    ;;
  "skiyaki-user-name2")
    slackMemberId="メンバーID2"
    ;;
esac

変換したメンバーIDを元にメンションつきデプロイ完了メッセージをincoming-webhookでslackへ投稿する

repositoryNameやenvなどはjobはごとに変えていけば良いのでベタ書きにしました。

repositoryName="bitfan_account"
env="staging"
message="<@$slackMemberId>\n$repositoryName $env へのデプロイが完了しました。"

# Slackメッセージを送信  
curl -X POST -H 'Content-type: application/json' --data "{ 'text':'$message' }" https://hooks.slack.com/services/**************

結果

最後にデプロイを実行をしたユーザー宛にメンション通知することができました。

まとめ

地味に助かる運用改善が自分には結構楽しい分野だったりするため
身近な作業でこうなれば良いのにとかがあったら都度対応していきたいと思います。

SKIYAKI Tech Blog

Discussion