こんにちは!現場の最前線で毎日コードとパイプラインに向き合っている先輩エンジニアです。
皆さんは、Jenkinsでのビルドが失敗したときに飛んでくる、あの無機質な標準メール通知にうんざりしたことはありませんか?
「どのジョブが落ちたのか一目でわからない」「SlackやTeamsで見たいのに、わざわざメールボックスを開かなきゃいけない」「そもそもメールサーバーのメンテが面倒…」
今回は、そんなレガシーな通知の悩みを一刀両断する「Jenkinsの通知システムをPythonとAWS SNSでモダンにリプレイスする手法」を解説します。
これをマスターすれば、通知の柔軟性が劇的に向上し、チームのチャットツール(SlackやTeams)へリッチなアラートを飛ばせるようになりますよ。毎日の開発体験がグッと快適になるので、ぜひ最後までついてきてくださいね!
—
なぜJenkins標準のメール通知から脱却すべきなのか?
Jenkinsには標準で「Mailer」プラグインが入っており、設定画面でSMTPサーバーの情報を入れれば簡単にメールを送ることができます。しかし、現場の実務では以下のような強い制限にぶつかります。
1. 表現力の限界: プレーンテキストか、せいぜい簡単なHTMLしか送れず、エラーログの重要な部分(スタックトレースなど)をピンポイントでハイライトするのが難しい。
2. ルーティングの硬直性: 「このジョブの失敗はインフラチームのSlackへ、別のジョブは開発チームのTeamsへ」といった動的な宛先変更が非常にやりづらい。
3. コストと管理: 社内SMTPサーバーの管理コストや、クラウド移行時のセキュリティ設定(ポート25番のブロックなど)の壁。
これらを解決するのが、「Jenkins ➔ Pythonスクリプト ➔ AWS SNS(または直接Webhooks)」というモダンなルーティングアーキテクチャです。ビルド結果という「イベント」をPythonで一度受け止め、リッチに料理してから最適なチャネルへ爆速で届ける仕組みを作ります。
—
全体像:今回構築するアーキテクチャ
今回のハンズオンでは、以下のステップで環境を構築します。
1. AWS SNS(Simple Notification Service)のトピックを作成し、エンドポイント(Slackやメールなど)を準備。
2. Jenkinsのビルド後処理から呼び出すPython通知スクリプトを作成。
3. JenkinsのPipeline(Jenkinsfile)に組み込み、「成功」「失敗」に応じた動的な通知を実装。
それでは、初心者の方でも迷わないよう、一つひとつ丁寧に手を動かしていきましょう!
—
ステップ1:AWS SNSのトピック作成と基礎準備
まずは、通知のハブとなるAWS SNSを設定します。(※AWSアカウントをお持ちでない場合は、ローカルのPythonスクリプトから直接Slackへ送る形に読み替えてもOKです!)
1. AWSマネジメントコンソールから SNS (Simple Notification Service) を開きます。
2. 「トピック」>「トピックの作成」をクリックします。
- タイプ: 標準 (Standard)
- 名前: `jenkins-build-notifications`
3. 作成されたトピックの 「ARN」(例: `arn:aws:sns:us-east-1:123456789012:jenkins-build-notifications`)を控えておきます。
4. 必要に応じて「サブスクリプションの作成」から、TeamsのWebhookやSlackへ転送するLambda、あるいは個人のメールアドレスなどを紐づけておきます。
—
ステップ2:魔法のPython通知スクリプトを作成する
次に、Jenkinsから受け取ったビルド情報を綺麗に整形し、AWS SNSへブロードキャストするPythonスクリプトを作成します。
このスクリプトは、Boto3(AWS SDK for Python)を使用するため、事前に `pip install boto3` が必要です。Jenkinsのマスターノード(または実行エージェント)に配置しておきましょう。
`notify_sns.py`
!/usr/bin/env python3
import sys
import os
import argparse
import boto3
from botocore.exceptions import BotoCoreError, ClientError
def send_sns_notification(subject, message, topic_arn):
“””
AWS SNS経由で通知を送信する関数
“””
# 認証情報は環境変数 (AWS_ACCESS_KEY_ID等) またはIAMロールから自動取得されます
sns_client = boto3.client(‘sns’, region_name=os.getenv(‘AWS_REGION’, ‘ap-northeast-1’))
try:
response = sns_client.publish(
TopicArn=topic_arn,
Subject=subject,
Message=message
)
print(f”Successfully sent notification. MessageId: {response[‘MessageId’]}”)
except (BotoCoreError, ClientError) as e:
print(f”Error sending notification to SNS: {e}”, file=sys.stderr)
sys.exit(1)
def main():
parser = argparse.ArgumentParser(description=”Jenkins Notification Dispatcher via AWS SNS”)
parser.add_argument(‘–status’, required=True, choices=[‘SUCCESS’, ‘FAILURE’, ‘UNSTABLE’], help=’Build status’)
parser.add_argument(‘–job-name’, required=True, help=’Jenkins Job Name’)
parser.add_argument(‘–build-number’, required=True, help=’Jenkins Build Number’)
parser.add_argument(‘–build-url’, required=True, help=’URL to the Jenkins build’)
args = parser.parse_args()
# SNSトピックのARNを環境変数から取得
topic_arn = os.getenv(‘SNS_TOPIC_ARN’)
if not topic_arn:
print(“Error: SNS_TOPIC_ARN environment variable is not set.”, file=sys.stderr)
sys.exit(1)
# ステータスに応じた絵文字とメッセージのカスタマイズ(ここが柔軟性のミソ!)
if args.status == ‘SUCCESS’:
emoji = “✅”
subject = f”[SUCCESS] {args.job_name} #{args.build_number}”
elif args.status == ‘FAILURE’:
emoji = “🔥”
subject = f”[FAILURE ALERT] {args.job_name} #{args.build_number}”
else:
emoji = “⚠️”
subject = f”[UNSTABLE] {args.job_name} #{args.build_number}”
message = (
f”{emoji} Jenkins Build Update\n”
f”———————————-\n”
f”• Job: {args.job_name}\n”
f”• Build: #{args.build_number}\n”
f”• Status: {args.status}\n”
f”• Direct Link: {args.build_url}\n”
f”———————————-”
)
send_sns_notification(subject, message, topic_arn)
if __name__ == ‘__main__’:
main()
このスクリプトの優れているポイント
- 表現力の高さ: 単なる文字の羅列ではなく、絵文字(✅ や 🔥)を使って、チャット画面で視覚的に一発でステータスがわかるようにしています。
- 拡張性: 将来的に「エラーログの末尾10行をメッセージに含める」といったカスタマイズも、Pythonなら数行追加するだけで簡単に実現できます。
—
ステップ3:Jenkins Pipeline (Jenkinsfile) への組み込み
いよいよ仕上げです。Declarative Pipeline(あるいはScripted Pipeline)の `post` セクションを使い、ビルドの結果に応じて先ほどのPythonスクリプトをキックします。
実際のプロジェクトでそのまま使える `Jenkinsfile` のサンプルをどうぞ。
`Jenkinsfile`
pipeline {
agent any
environment {
// ステップ1で作成したAWS SNSのトピックARN
SNS_TOPIC_ARN = ‘arn:aws:sns:ap-northeast-1:123456789012:jenkins-build-notifications’
// AWSのリージョン
AWS_REGION = ‘ap-northeast-1’
}
stages {
stage(‘Build & Test’) {
steps {
echo ‘Building the amazing application…’
// 意図的に失敗させたい場合は sh ‘exit 1’ などに変更してテストしてください
sh ‘echo “Build passed successfully!”‘
}
}
}
post {
success {
script {
// Pythonスクリプトを呼び出して成功通知を送る
sh “””
python3 /path/to/notify_sns.py \
–status SUCCESS \
–job-name “${env.JOB_NAME}” \
–build-number “${env.BUILD_NUMBER}” \
–build-url “${env.BUILD_URL}”
“””
}
}
failure {
script {
// Pythonスクリプトを呼び出して失敗通知を送る
sh “””
python3 /path/to/notify_sns.py \
–status FAILURE \
–job-name “${env.JOB_NAME}” \
–build-number “${env.BUILD_NUMBER}” \
–build-url “${env.BUILD_URL}”
“””
}
}
}
}
💡 先輩エンジニアからのワンポイント・アドバイス
Jenkinsを実行しているエージェント(コンテナやEC2インスタンスなど)に、AWSの認証情報(IAMロール、あるいはJenkinsのクレデンシャル機能経由での環境変数注入)が正しく渡されていることを確認してください。Boto3は環境変数 `AWS_ACCESS_KEY_ID` と `AWS_SECRET_ACCESS_KEY`、またはEC2のインスタンスプロファイルを自動で検知してくれます。
—
動作確認:いざ、パイプラインを実行!
1. 上記の `Jenkinsfile` をリポジトリにコミットし、Jenkinsでマルチ分支やパイプラインジョブとして登録します。
2. 「ビルドの実行」をポチッと押してみましょう。
3. コンソール出力に `Successfully sent notification. MessageId: …` と表示されたら成功です!
4. 設定したAWS SNSのエンドポイント(Slackのチャンネルやメールボックス)に、リッチで分かりやすい通知が飛んできていることを確認してください。
—
まとめ:通知の自由を手に入れ、チームの心理的安全性を高めよう
今回は、Jenkins標準のメール通知の限界を突破し、PythonとAWS SNSを組み合わせた柔軟かつ拡張性の高い通知システムの構築手法を解説しました。
この仕組みを導入するメリットは、単に「通知が綺麗になる」だけではありません。
- 障害発生時にチーム全員が瞬時に状況を把握できる。
- 通知内容をビジネスロジックに合わせて自由自在にハックできる。
- レガシーなメールサーバーへの依存を断ち切れる。
これをマスターすれば、毎日のCI/CD運用のストレスが劇的に軽くなりますよ。ぜひ、あなたのプロジェクトのパイプラインにも取り入れてみてくださいね。
それでは、ハッピー・エンジニアリング!