パイプラインビルドジョブを定義するJenkinsfile
内のJenkinsの既存の Mailer プラグインを活用したいと思います。次の単純な失敗スクリプトを考えると、私はすべてのビルドで電子メールを期待しています。
#!groovy
stage 'Test'
node {
try {
sh 'exit 1'
} finally {
step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: '[email protected]', sendToIndividuals: true])
}
}
ビルドからの出力は次のとおりです。
Started by user xxxxx
[Pipeline] stage (Test)
Entering stage Test
Proceeding
[Pipeline] node
Running on master in /var/lib/jenkins/jobs/rpk-test/workspace
[Pipeline] {
[Pipeline] sh
[workspace] Running Shell script
+ exit 1
[Pipeline] step
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
ERROR: script returned exit code 1
Finished: FAILURE
ご覧のように、障害の直後にパイプラインstep
を実行することを記録しますが、電子メールは生成されません。
mailer
を活用する他のフリースタイルジョブの電子メールは正常に機能し、パイプラインジョブを介して呼び出します。
これは、Jenkins 2.2およびメーラー1.17で実行されています。
失敗したビルド電子メールを呼び出す別のメカニズムはありますか?mail
ステップのすべてのオーバーヘッドは必要ありませんが、障害と回復に関する通知のみが必要です。
Pipelineでsh
はすぐにcurrentBuild.result
をFAILURE
に設定しませんが、初期値はnull
です。したがって、メーラーのようなビルドステータスに依存するビルド手順は、一見正しくないように見える場合があります。
デバッグ出力を追加することで確認できます:
stage 'Test'
node {
try {
sh 'exit 1'
} finally {
println currentBuild.result // this prints null
step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: '[email protected]', sendToIndividuals: true])
}
}
このパイプライン全体がJenkinsが提供する例外ハンドラーでラップされているため、Jenkinsは最後にビルドを失敗としてマークします。
したがって、メーラーを利用する場合は、ビルドステータスを適切に維持する必要があります。例えば:
stage 'Test'
node {
try {
sh 'exit 1'
currentBuild.result = 'SUCCESS'
} catch (any) {
currentBuild.result = 'FAILURE'
throw any //rethrow exception to prevent the build from proceeding
} finally {
step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: '[email protected]', sendToIndividuals: true])
}
}
例外を再スローする必要がない場合は、catchError
を使用できます。これはPipelineビルトインであり、スコープ内の例外をキャッチし、コンソールに出力してビルドステータスを設定します。例:
stage 'Test'
node {
catchError {
sh 'exit 1'
}
step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: '[email protected]', sendToIndividuals: true])
}
Izzekilの優れた回答に加えて、コミットの作成者に基づいて電子メールの受信者を選択できます。 email-ext を使用してこれを行うことができます( パイプラインの例 に基づいて):
step([$class: 'Mailer',
notifyEveryUnstableBuild: true,
recipients: emailextrecipients([[$class: 'CulpritsRecipientProvider'],
[$class: 'RequesterRecipientProvider']])])
最近のemail-ext(2.50+)を使用している場合、それをパイプラインで使用できます。
emailext(body: '${DEFAULT_CONTENT}', mimeType: 'text/html',
replyTo: '$DEFAULT_REPLYTO', subject: '${DEFAULT_SUBJECT}',
to: emailextrecipients([[$class: 'CulpritsRecipientProvider'],
[$class: 'RequesterRecipientProvider']]))
宣言的なJenkinsfileを使用していない場合、Jenkinsがコミッターを見つけられるようにcheckout scm
を配置する必要があります。 JENKINS-46431 を参照してください。
まだ古いバージョンのemail-extを使用している場合は、 JENKINS-25267 を押します。独自のHTMLメールを送信できます。
def emailNotification() {
def to = emailextrecipients([[$class: 'CulpritsRecipientProvider'],
[$class: 'DevelopersRecipientProvider'],
[$class: 'RequesterRecipientProvider']])
String currentResult = currentBuild.result
String previousResult = currentBuild.getPreviousBuild().result
def causes = currentBuild.rawBuild.getCauses()
// E.g. 'started by user', 'triggered by scm change'
def cause = null
if (!causes.isEmpty()) {
cause = causes[0].getShortDescription()
}
// Ensure we don't keep a list of causes, or we get
// "Java.io.NotSerializableException: hudson.model.Cause$UserIdCause"
// see http://stackoverflow.com/a/37897833/509706
causes = null
String subject = "$env.JOB_NAME $env.BUILD_NUMBER: $currentResult"
String body = """
<p>Build $env.BUILD_NUMBER ran on $env.NODE_NAME and terminated with $currentResult.
</p>
<p>Build trigger: $cause</p>
<p>See: <a href="$env.BUILD_URL">$env.BUILD_URL</a></p>
"""
String log = currentBuild.rawBuild.getLog(40).join('\n')
if (currentBuild != 'SUCCESS') {
body = body + """
<h2>Last lines of output</h2>
<pre>$log</pre>
"""
}
if (to != null && !to.isEmpty()) {
// Email on any failures, and on first success.
if (currentResult != 'SUCCESS' || currentResult != previousResult) {
mail to: to, subject: subject, body: body, mimeType: "text/html"
}
echo 'Sent email notification'
}
}
Jenkinsパイプラインでメール通知を送信するより良い方法は、try catchを使用する代わりに、 jenkins docs で説明されているパイプラインのpostセクションを使用することです。
pipeline {
agent any
stages {
stage('whatever') {
steps {
...
}
}
}
post {
always {
step([$class: 'Mailer',
notifyEveryUnstableBuild: true,
recipients: "[email protected]",
sendToIndividuals: true])
}
}
}
}
}