Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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に圧縮されて保存されており、読み出す際にこのパッケージで解凍されます。

技術的詳細

このコミットは、主に以下のコンポーネントにわたる変更を加えて、ビルド失敗時のメール通知機能を実現しています。

  1. app.yaml の変更:

    • アプリケーションIDが godashboard から go-build に変更されました。これはアプリケーションの識別子をより明確にするための変更です。
    • バージョンが go から 1 に変更されました。
    • 新しいURLハンドラ /(_ah/queue/go/delay) が追加されました。これはApp Engineのタスクキュー(特に delay パッケージが使用する内部キュー)からのリクエストを処理するためのもので、非同期のメール送信タスクがこのエンドポイントを通じて実行されます。
  2. 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() メソッドを使用するようにリファクタリングされ、ログの取得と表示が簡素化されました。
  3. misc/dashboard/app/build/notify.go の新規追加:

    • このファイルは、ビルド失敗通知機能の核心をなすものです。
    • mailFromfailMailTo ( golang-dev@googlegroups.com ) の定数が定義されています。
    • notifyOnFailure 関数が定義されています。この関数は、現在のコミットまたはその次のコミットがビルドを壊しているかどうかを判断します。
      • Datastoreをクエリして、現在のコミットのビルドステータスと、その前後のコミットのステータスを確認します。
      • もしビルドが壊れており、かつまだ通知が送信されていない場合 (!broken.FailNotificationSent)、sendFailMailLater.Call(c, broken, builder) を呼び出します。これは appengine/delay パッケージを使用して、 sendFailMail 関数を非同期タスクとしてタスクキューに追加します。これにより、メール送信処理がメインのリクエストハンドラをブロックせず、Datastoreトランザクションが成功した場合にのみメールが送信されることが保証されます。
      • 通知が送信された後、broken.FailNotificationSenttrue に設定し、Datastoreにコミットエンティティを更新します。
    • firstMatch はDatastoreクエリの結果から最初の一致を取得するためのヘルパー関数です。
    • sendFailMailLaterdelay.Func のインスタンスで、sendFailMail 関数をラップしています。
    • sendFailMailTmplbuild/notify.txt から読み込まれるメールテンプレートです。
    • init() 関数内で gob.Register(&Commit{}) が呼び出されています。これは、appengine/delay パッケージが Commit オブジェクトをタスクキュー間でシリアライズ/デシリアライズするために gob エンコーディングを使用するため、Commit 型を登録する必要があるためです。
    • sendFailMail 関数は、実際にメールを送信するロジックを含んでいます。
      • Datastoreから関連するビルド結果 (Result) とログ (Log) を取得します。
      • sendFailMailTmpl を使用してメールの本文をレンダリングします。テンプレートには、ビルダー名、コミット情報、ビルド結果、ログ、ホスト名などの情報が渡されます。
      • appengine/mail.Message 構造体を作成し、送信者、受信者、件名、本文を設定します。
      • mail.Send(c, msg) を呼び出してメールを送信します。
  4. misc/dashboard/app/build/notify.txt の新規追加:

    • このファイルは、ビルド失敗通知メールの本文のテンプレートです。
    • Goの text/template 構文を使用して、コミットの短いハッシュ、ビルダー名、ビルドログへのリンク、コミットの説明、そしてビルドログの末尾100行を表示するようにフォーマットされています。
  5. misc/dashboard/app/build/test.go の変更:

    • ビルド失敗通知機能のテストケースが追加されました。特に、「繰り返し失敗してもメールを再送しない」というシナリオ(FailNotificationSent フラグの動作確認)がテストされています。
  6. 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.gonotifyOnFailure 関数は、ビルド結果がDatastoreに保存された後に呼び出されます。この関数は、現在のコミットのビルドステータスと、その親コミットまたは子コミットのステータスを比較することで、「ビルドを壊したコミット」を特定しようとします。

具体的には、以下のシナリオを考慮します。

  1. 現在のコミットがOKの場合: その次のコミットがビルドを壊しているかどうかを確認します。もし次のコミットが壊れていれば、そのコミットが原因であると判断します。
  2. 現在のコミットが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に関する情報源となります。

参考にした情報源リンク