[インデックス 10924] ファイルの概要
このコミットは、Go言語のビルドダッシュボードシステムに、ビルド失敗時にメール通知を送信する機能を追加するものです。これにより、Goプロジェクトのビルドが壊れた際に、開発者が迅速にその状況を把握し、対応できるようになります。
コミット
commit 03fbf29927a2e47939c5b1a8b879f049a01a7cdc
Author: Andrew Gerrand <adg@golang.org>
Date: Wed Dec 21 13:16:47 2011 +1100
dashboard: send mail on build failure
R=rsc, adg
CC=golang-dev
https://golang.org/cl/5490081
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/03fbf29927a2e47939c5b1a8b879f049a01a7cdc
元コミット内容
dashboard: send mail on build failure
変更の背景
Go言語のプロジェクトでは、継続的なインテグレーションとテストのためにビルドダッシュボードが運用されています。しかし、これまでのシステムでは、ビルドが失敗した場合に開発者への自動的な通知メカニズムがありませんでした。ビルドの破損は、プロジェクトの健全性に直接影響し、他の開発者の作業を妨げる可能性があります。そのため、ビルドが失敗した際に、関係者(特に golang-dev メーリングリスト)に即座に通知することで、問題の早期発見と解決を促し、開発ワークフローの効率を向上させる必要がありました。このコミットは、この重要な通知機能を追加することで、ビルドシステムの監視体制を強化することを目的としています。
前提知識の解説
このコミットの変更内容を理解するためには、以下の技術要素に関する基本的な知識が必要です。
- Go Dashboard (Goビルドダッシュボード): Go言語プロジェクトの公式ビルドシステムであり、様々なオペレーティングシステムやアーキテクチャ上でGoのコードを継続的にビルドし、テストを実行するウェブアプリケーションです。ビルド結果はウェブインターフェースを通じて確認できます。
- Google App Engine (GAE): Googleが提供するPaaS(Platform as a Service)であり、ウェブアプリケーションやモバイルバックエンドを構築・ホストするためのプラットフォームです。このGoビルドダッシュボードはApp Engine上で動作しており、Datastore、Mail、DelayなどのApp Engine固有のサービスAPIを利用しています。
- App Engine Datastore: App Engineアプリケーションが利用できるNoSQLドキュメントデータベースです。このシステムでは、ビルドのコミット情報 (
Commitエンティティ) やビルドログ (Logエンティティ) などがDatastoreに永続化されています。 appengine/mailパッケージ: Go言語のApp Engine SDKに含まれるパッケージで、App Engineアプリケーションからメールを送信するためのAPIを提供します。appengine/delayパッケージ: Go言語のApp Engine SDKに含まれるパッケージで、関数を非同期に実行するためのAPIを提供します。これは、時間がかかる処理や、トランザクションのコミット後にのみ実行したい処理(例:メール送信)をバックグラウンドで安全に実行するために使用されます。delay.Funcを使用して、指定した関数をタスクキューに追加し、後で実行させることができます。- Go言語の
text/templateパッケージ: Goの標準ライブラリの一部で、テキストベースの出力を生成するためのテンプレートエンジンを提供します。このコミットでは、メールの本文を動的に生成するために使用されています。 gzipパッケージ: Goの標準ライブラリの一部で、GZIP形式の圧縮・解凍機能を提供します。ビルドログはDatastoreに圧縮されて保存されており、読み出す際にこのパッケージで解凍されます。
技術的詳細
このコミットは、主に以下のコンポーネントにわたる変更を加えて、ビルド失敗時のメール通知機能を実現しています。
-
app.yamlの変更:- アプリケーションIDが
godashboardからgo-buildに変更されました。これはアプリケーションの識別子をより明確にするための変更です。 - バージョンが
goから1に変更されました。 - 新しいURLハンドラ
/(_ah/queue/go/delay)が追加されました。これはApp Engineのタスクキュー(特にdelayパッケージが使用する内部キュー)からのリクエストを処理するためのもので、非同期のメール送信タスクがこのエンドポイントを通じて実行されます。
- アプリケーションIDが
-
misc/dashboard/app/build/build.goの変更:Commit構造体にFailNotificationSent boolフィールドが追加されました。これは、特定のコミットに対するビルド失敗通知が既に送信されたかどうかを追跡し、重複してメールが送信されるのを防ぐためのフラグです。Commit構造体にOK(builder, goHash string) (ok, present bool)メソッドが追加されました。これは、特定のビルダーとGoハッシュに対するコミットのビルドステータス(成功/失敗)を簡潔に確認するためのヘルパーメソッドです。Log構造体にText() ([]byte, os.Error)メソッドが追加されました。このメソッドは、圧縮されたビルドログ (CompressedLogフィールド) を解凍し、プレーンテキストとして返します。これにより、ログの読み出しがより簡単になりました。resultHandler関数(ビルド結果がApp Engineに送信された際に呼び出されるハンドラ)の最後にnotifyOnFailure(c, com, res.Builder)の呼び出しが追加されました。これにより、新しいビルド結果がDatastoreに保存された直後に、ビルド失敗の可能性をチェックし、必要に応じて通知プロセスを開始するようになりました。logHandler関数がLog.Text()メソッドを使用するようにリファクタリングされ、ログの取得と表示が簡素化されました。
-
misc/dashboard/app/build/notify.goの新規追加:- このファイルは、ビルド失敗通知機能の核心をなすものです。
mailFromとfailMailTo(golang-dev@googlegroups.com) の定数が定義されています。notifyOnFailure関数が定義されています。この関数は、現在のコミットまたはその次のコミットがビルドを壊しているかどうかを判断します。- Datastoreをクエリして、現在のコミットのビルドステータスと、その前後のコミットのステータスを確認します。
- もしビルドが壊れており、かつまだ通知が送信されていない場合 (
!broken.FailNotificationSent)、sendFailMailLater.Call(c, broken, builder)を呼び出します。これはappengine/delayパッケージを使用して、sendFailMail関数を非同期タスクとしてタスクキューに追加します。これにより、メール送信処理がメインのリクエストハンドラをブロックせず、Datastoreトランザクションが成功した場合にのみメールが送信されることが保証されます。 - 通知が送信された後、
broken.FailNotificationSentをtrueに設定し、Datastoreにコミットエンティティを更新します。
firstMatchはDatastoreクエリの結果から最初の一致を取得するためのヘルパー関数です。sendFailMailLaterはdelay.Funcのインスタンスで、sendFailMail関数をラップしています。sendFailMailTmplはbuild/notify.txtから読み込まれるメールテンプレートです。init()関数内でgob.Register(&Commit{})が呼び出されています。これは、appengine/delayパッケージがCommitオブジェクトをタスクキュー間でシリアライズ/デシリアライズするためにgobエンコーディングを使用するため、Commit型を登録する必要があるためです。sendFailMail関数は、実際にメールを送信するロジックを含んでいます。- Datastoreから関連するビルド結果 (
Result) とログ (Log) を取得します。 sendFailMailTmplを使用してメールの本文をレンダリングします。テンプレートには、ビルダー名、コミット情報、ビルド結果、ログ、ホスト名などの情報が渡されます。appengine/mail.Message構造体を作成し、送信者、受信者、件名、本文を設定します。mail.Send(c, msg)を呼び出してメールを送信します。
- Datastoreから関連するビルド結果 (
-
misc/dashboard/app/build/notify.txtの新規追加:- このファイルは、ビルド失敗通知メールの本文のテンプレートです。
- Goの
text/template構文を使用して、コミットの短いハッシュ、ビルダー名、ビルドログへのリンク、コミットの説明、そしてビルドログの末尾100行を表示するようにフォーマットされています。
-
misc/dashboard/app/build/test.goの変更:- ビルド失敗通知機能のテストケースが追加されました。特に、「繰り返し失敗してもメールを再送しない」というシナリオ(
FailNotificationSentフラグの動作確認)がテストされています。
- ビルド失敗通知機能のテストケースが追加されました。特に、「繰り返し失敗してもメールを再送しない」というシナリオ(
-
misc/dashboard/app/build/ui.goの変更:- テンプレート関数 (
builderTitle,shortDesc,shortHash,shortUser,repoURL) の登録方法がリファクタリングされ、tmplFuncsというマップにまとめられました。 - 新しいテンプレート関数
tail(n int, s string) stringが追加されました。これは文字列の末尾n行を返すもので、notify.txtでビルドログの末尾を表示するために使用されます。
- テンプレート関数 (
これらの変更により、Goビルドダッシュボードは、ビルドが失敗した際に自動的にメール通知を送信する堅牢なシステムを獲得しました。appengine/delay の使用は、通知の信頼性とシステムの応答性を高める上で重要な役割を果たしています。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は以下のファイルに集中しています。
misc/dashboard/app/app.yaml: App Engineアプリケーションの設定ファイル。タスクキューのハンドラが追加されました。misc/dashboard/app/build/build.go: ビルド結果の処理ロジックが含まれるファイル。Commit構造体の変更、新しいメソッドの追加、そしてnotifyOnFailureの呼び出しが追加されました。misc/dashboard/app/build/notify.go: 新規追加されたファイル。ビルド失敗通知の主要なロジック(ビルド状態の判定、メール送信のトリガー、非同期タスクの管理)が実装されています。misc/dashboard/app/build/notify.txt: 新規追加されたファイル。ビルド失敗通知メールの本文のテンプレートです。misc/dashboard/app/build/test.go: テストファイル。通知機能のテストケースが追加されました。misc/dashboard/app/build/ui.go: UI関連のヘルパー関数が含まれるファイル。テンプレート関数のリファクタリングとtail関数の追加が行われました。
コアとなるコードの解説
このコミットの最も重要な部分は、misc/dashboard/app/build/notify.go ファイルに実装されたロジックです。
notify.go の notifyOnFailure 関数は、ビルド結果がDatastoreに保存された後に呼び出されます。この関数は、現在のコミットのビルドステータスと、その親コミットまたは子コミットのステータスを比較することで、「ビルドを壊したコミット」を特定しようとします。
具体的には、以下のシナリオを考慮します。
- 現在のコミットがOKの場合: その次のコミットがビルドを壊しているかどうかを確認します。もし次のコミットが壊れていれば、そのコミットが原因であると判断します。
- 現在のコミットがNGの場合: その前のコミットがOKだったかどうかを確認します。もし前のコミットがOKで、現在のコミットがNGであれば、現在のコミットがビルドを壊したと判断します。
「ビルドを壊したコミット」が特定され、かつそのコミットに対する通知がまだ送信されていない場合 (!broken.FailNotificationSent)、appengine/delay パッケージの sendFailMailLater.Call() を使用して、sendFailMail 関数を非同期タスクとしてタスクキューに追加します。
sendFailMail 関数は、タスクキューによって実行されると、Datastoreから必要なビルド結果とログ情報を取得し、notify.txt テンプレートを使用してメールの本文を生成します。最終的に、appengine/mail.Send() を呼び出して、golang-dev@googlegroups.com にビルド失敗通知メールを送信します。
Commit 構造体に追加された FailNotificationSent フラグは、同じコミットが複数回ビルド失敗を引き起こした場合でも、通知が一度しか送信されないようにするために重要です。これにより、メーリングリストへのスパムを防ぎます。
また、misc/dashboard/app/build/ui.go に追加された tail 関数は、メールテンプレート (notify.txt) でビルドログの末尾を表示するために利用され、通知メールの有用性を高めています。
これらの変更は、Goビルドダッシュボードの運用において、ビルドの健全性を維持し、問題発生時の対応を迅速化するための重要な改善です。
関連リンク
- Go言語公式ウェブサイト: https://golang.org/
- Google Cloud App Engine ドキュメント: https://cloud.google.com/appengine/docs
- Go App Engine SDK ドキュメント (当時のバージョン): 現在はGoの標準ライブラリに統合されている部分が多いですが、当時のApp Engine固有のAPIに関する情報源となります。
参考にした情報源リンク
- Go App Engine Mail API:
- https://cloud.google.com/appengine/docs/standard/go/mail/sending-mail (現在のドキュメントですが、当時のAPIの概念を理解するのに役立ちます)
- Go App Engine Delay Package:
- https://cloud.google.com/appengine/docs/standard/go/taskqueue/push/delay (現在のドキュメントですが、当時のAPIの概念を理解するのに役立ちます)
- Go
text/templatePackage: - Go App Engine Datastore:
- https://cloud.google.com/appengine/docs/standard/go/datastore (現在のドキュメントですが、当時のAPIの概念を理解するのに役立ちます)
- Go
gzipPackage: