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

[インデックス 11580] ファイルの概要

このコミットは、Go言語の継続的インテグレーション(CI)システムであるGo Dashboardの一部であるmisc/dashboard/app/build/handler.goファイルに対する変更です。このファイルは、Goプロジェクトのビルドタスク("todo")の生成ロジックを扱っています。具体的には、様々なビルドワーカー(builder)に対して、Go本体やサブリポジトリのビルドを指示する役割を担っています。

コミット

dashboard: don't send failing Go commits as todos for subrepos

R=golang-dev, dsymonds CC=golang-dev https://golang.org/cl/5608044

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/aa716e36a6c0656730eeab753eaba9d07aab72e0

元コミット内容

dashboard: don't send failing Go commits as todos for subrepos

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/5608044

変更の背景

Go Dashboardは、Go言語本体だけでなく、それに依存する多数のサブリポジトリ(例: golang.org/x/配下のライブラリ群)のビルドとテストも継続的に実行しています。これまでの挙動では、Go本体の特定のコミットがビルドに失敗した場合でも、その失敗したGoコミットをベースとしてサブリポジトリのビルドタスク("todo")が生成されてしまう問題がありました。

このような状況では、サブリポジトリのビルドはGo本体のビルド失敗に起因して必ず失敗するため、無駄なビルド処理が実行されることになります。これは、ビルドリソースの無駄遣いであるだけでなく、ダッシュボード上に多数の失敗したビルドタスクが表示され、本当に問題のあるサブリポジトリの変更による失敗と区別がつきにくくなるという問題を引き起こしていました。

このコミットは、このような非効率性と混乱を解消するために導入されました。Go本体のコミットが特定のビルドワーカーで既に失敗している場合、そのコミットを基にしたサブリポジトリのビルドタスクは生成しないようにすることで、リソースの節約とダッシュボードの情報の明確化を図っています。

前提知識の解説

この変更を理解するためには、以下の概念を把握しておく必要があります。

  • Go Dashboard: Go言語プロジェクトの公式な継続的インテグレーション(CI)システムです。Go本体のコミットや、golang.org/x/配下にあるような関連するサブリポジトリのビルド、テスト、リリースプロセスを自動化し、その結果をウェブインターフェースで可視化します。これにより、Go言語の安定性と品質が維持されています。
  • Subrepositories (Subrepos): Goエコシステムにおいて、Go本体とは別のリポジトリで管理されているが、Go本体に強く依存しているプロジェクトやライブラリ群を指します。例えば、Goの標準ライブラリには含まれないが、Goチームによって公式にメンテナンスされているツールやパッケージ(例: go.toolsnet/contextなど)がこれに該当します。これらのサブリポジトリは、Go本体の変更によって影響を受ける可能性があるため、Go本体のコミットと連携してビルド・テストされる必要があります。
  • ビルドの「todo」: Go Dashboardの文脈における「todo」とは、特定のビルドワーカー(builder)に対して発行される、ビルドやテストの実行指示(タスク)を意味します。ダッシュボードは、新しいコミットがプッシュされた際や、特定の条件が満たされた際に、これらの「todo」を生成し、ビルドワーカーに割り当てます。
  • Google App Engine: misc/dashboard/app/というパスからわかるように、Go DashboardのアプリケーションはGoogle App Engine上で動作しています。appengine.ContextはそのApp Engineアプリケーションのコンテキストを表すオブジェクトで、データストアへのアクセスやログ出力など、App Engineのサービスを利用する際に必要となります。

技術的詳細

この変更は、misc/dashboard/app/build/handler.goファイル内のbuildTodo関数にロジックを追加することで実現されています。buildTodo関数は、特定のビルドワーカー(builder引数)とGoのコミットハッシュ(goHash引数)に基づいて、サブリポジトリのビルドタスクを生成するかどうかを決定します。

変更前は、buildTodo関数はGo本体のコミットが正常にビルドされたかどうかに関わらず、サブリポジトリのビルドタスクの生成を試みていました。

変更後のロジックでは、サブリポジトリのビルドタスクを生成する前に、以下のチェックが追加されました。

  1. 現在のGoコミットの取得: tag.Commit(c)を呼び出して、現在のGoコミット(goHashに対応するコミット)の情報を取得します。ここで取得されるcomオブジェクトは、そのコミットに関するメタデータやビルド結果を保持していると考えられます。
  2. Goコミットのビルド結果の確認: 取得したcomオブジェクトに対してcom.Result(builder, "")を呼び出します。
    • Resultメソッドは、指定されたbuilder(ビルドワーカー)とパッケージパス(ここではGo本体のビルド結果を見るため空文字列"")に対するビルド結果を返します。
    • 返された結果オブジェクトがnilでない(つまり、ビルド結果が存在する)かつ、!r.OKである(つまり、ビルドが成功していない、失敗している)場合に、Go本体のビルドが失敗していると判断します。
  3. タスク生成の抑制: もしGo本体のビルドが失敗していると判断された場合、return nil, nilを実行します。これにより、buildTodo関数はビルドタスクを生成せずに終了し、無駄なサブリポジトリのビルドが回避されます。

この変更により、Go Dashboardはより効率的に動作し、ビルド結果の表示もより正確になります。

コアとなるコードの変更箇所

--- a/misc/dashboard/app/build/handler.go
+++ b/misc/dashboard/app/build/handler.go
@@ -215,10 +215,22 @@ func buildTodo(c appengine.Context, builder, packagePath, goHash string) (interf
 	// see if there are any subrepo commits that need to be built at tip.
 	// If so, ask the builder to build a go tree at the tip commit.
 	// TODO(adg): do the same for "weekly" and "release" tags.
+\n
 	tag, err := GetTag(c, "tip")
 	if err != nil {
 		return nil, err
 	}
+\n
+\t// Check that this Go commit builds OK for this builder.
+\t// If not, don't re-build as the subrepos will never get built anyway.
+\tcom, err := tag.Commit(c)
+\tif err != nil {
+\t\treturn nil, err
+\t}\
+\tif r := com.Result(builder, ""); r != nil && !r.OK {
+\t\treturn nil, nil
+\t}\
+\n
 	pkgs, err := Packages(c, "subrepo")
 	if err != nil {
 		return nil, err
@@ -233,6 +245,7 @@ func buildTodo(c appengine.Context, builder, packagePath, goHash string) (interf
 			return tag.Commit(c)
 		}
 	}\n+\n 	return nil, nil
 }

コアとなるコードの解説

追加されたコードブロックは以下の部分です。

	// Check that this Go commit builds OK for this builder.
	// If not, don't re-build as the subrepos will never get built anyway.
	com, err := tag.Commit(c)
	if err != nil {
		return nil, err
	}
	if r := com.Result(builder, ""); r != nil && !r.OK {
		return nil, nil
	}
  1. // Check that this Go commit builds OK for this builder. // If not, don't re-build as the subrepos will never get built anyway. このコメントは、追加されるロジックの目的を明確に説明しています。Go本体のコミットがこのビルドワーカーで正常にビルドされるかを確認し、もし失敗している場合は、サブリポジトリのビルドを再試行しないという意図が示されています。これは、サブリポジトリのビルドがGo本体のビルドに依存しているため、Go本体が失敗していればサブリポジトリも成功する見込みがないという前提に基づいています。

  2. com, err := tag.Commit(c) tagオブジェクト(おそらくGetTag(c, "tip")で取得された、現在のGoのtip、つまり最新のコミットに関する情報を持つオブジェクト)のCommitメソッドを呼び出し、現在のappengine.Context cを渡して、Go本体のコミット情報を取得しています。このcom変数は、取得したコミットの詳細(ハッシュ、作者、日付、そしてビルド結果など)を保持するオブジェクトであると推測されます。エラーが発生した場合は、即座にnil, errを返して処理を中断します。

  3. if r := com.Result(builder, ""); r != nil && !r.OK { この行が変更の核心部分です。

    • r := com.Result(builder, ""): comオブジェクトのResultメソッドを呼び出しています。
      • 第一引数builderは、現在処理しているビルドワーカーの名前です。
      • 第二引数""(空文字列)は、特定のパッケージパスを指定しないことを意味します。これは、Go本体全体のビルド結果を参照していることを示唆しています。
      • この呼び出しは、指定されたbuilderにおけるGo本体のビルド結果を返します。その結果はrという変数に代入されます。
    • r != nil: Resultメソッドがnil以外の値を返した場合、それはそのbuilderに対するビルド結果が存在することを示します。
    • !r.OK: rオブジェクトのOKフィールドがfalseである場合、それはそのビルドが成功しなかった(つまり、失敗した)ことを意味します。
    • このif文全体は、「もし、このGoコミットがこのビルドワーカーでビルド結果を持っており、かつそのビルドが成功していなかった場合」という条件をチェックしています。
  4. return nil, nil 上記のif条件が真(Go本体のビルドが失敗している)の場合、この行が実行されます。buildTodo関数はnil, nilを返します。これは、新しいビルドタスク(todo)を生成しないことを意味します。これにより、Go本体のビルド失敗に起因する無駄なサブリポジトリのビルドタスクの生成が抑制されます。

関連リンク

参考にした情報源リンク

  • Go Dashboardのソースコード(misc/dashboardディレクトリ): Goリポジトリ内のこのディレクトリは、Go Dashboardのアプリケーションコードを含んでいます。
  • Go言語の公式ドキュメント: Go言語のビルドシステムやパッケージ管理に関する一般的な情報。
  • Google App Engineのドキュメント: Go DashboardがApp Engine上で動作しているため、appengine.Contextなどの理解に役立ちます。The user wants me to output the generated explanation to standard output. I have already constructed the entire Markdown content. I will now print it.# [インデックス 11580] ファイルの概要

このコミットは、Go言語の継続的インテグレーション(CI)システムであるGo Dashboardの一部であるmisc/dashboard/app/build/handler.goファイルに対する変更です。このファイルは、Goプロジェクトのビルドタスク("todo")の生成ロジックを扱っています。具体的には、様々なビルドワーカー(builder)に対して、Go本体やサブリポジトリのビルドを指示する役割を担っています。

コミット

dashboard: don't send failing Go commits as todos for subrepos

R=golang-dev, dsymonds CC=golang-dev https://golang.org/cl/5608044

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/aa716e36a6c0656730eeab753eaba9d07aab72e0

元コミット内容

dashboard: don't send failing Go commits as todos for subrepos

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/5608044

変更の背景

Go Dashboardは、Go言語本体だけでなく、それに依存する多数のサブリポジトリ(例: golang.org/x/配下のライブラリ群)のビルドとテストも継続的に実行しています。これまでの挙動では、Go本体の特定のコミットがビルドに失敗した場合でも、その失敗したGoコミットをベースとしてサブリポジトリのビルドタスク("todo")が生成されてしまう問題がありました。

このような状況では、サブリポジリのビルドはGo本体のビルド失敗に起因して必ず失敗するため、無駄なビルド処理が実行されることになります。これは、ビルドリソースの無駄遣いであるだけでなく、ダッシュボード上に多数の失敗したビルドタスクが表示され、本当に問題のあるサブリポジトリの変更による失敗と区別がつきにくくなるという問題を引き起こしていました。

このコミットは、このような非効率性と混乱を解消するために導入されました。Go本体のコミットが特定のビルドワーカーで既に失敗している場合、そのコミットを基にしたサブリポジトリのビルドタスクは生成しないようにすることで、リソースの節約とダッシュボードの情報の明確化を図っています。

前提知識の解説

この変更を理解するためには、以下の概念を把握しておく必要があります。

  • Go Dashboard: Go言語プロジェクトの公式な継続的インテグレーション(CI)システムです。Go本体のコミットや、golang.org/x/配下にあるような関連するサブリポジトリのビルド、テスト、リリースプロセスを自動化し、その結果をウェブインターフェースで可視化します。これにより、Go言語の安定性と品質が維持されています。
  • Subrepositories (Subrepos): Goエコシステムにおいて、Go本体とは別のリポジトリで管理されているが、Go本体に強く依存しているプロジェクトやライブラリ群を指します。例えば、Goの標準ライブラリには含まれないが、Goチームによって公式にメンテナンスされているツールやパッケージ(例: go.toolsnet/contextなど)がこれに該当します。これらのサブリポジトリは、Go本体の変更によって影響を受ける可能性があるため、Go本体のコミットと連携してビルド・テストされる必要があります。
  • ビルドの「todo」: Go Dashboardの文脈における「todo」とは、特定のビルドワーカー(builder)に対して発行される、ビルドやテストの実行指示(タスク)を意味します。ダッシュボードは、新しいコミットがプッシュされた際や、特定の条件が満たされた際に、これらの「todo」を生成し、ビルドワーカーに割り当てます。
  • Google App Engine: misc/dashboard/app/というパスからわかるように、Go DashboardのアプリケーションはGoogle App Engine上で動作しています。appengine.ContextはそのApp Engineアプリケーションのコンテキストを表すオブジェクトで、データストアへのアクセスやログ出力など、App Engineのサービスを利用する際に必要となります。

技術的詳細

この変更は、misc/dashboard/app/build/handler.goファイル内のbuildTodo関数にロジックを追加することで実現されています。buildTodo関数は、特定のビルドワーカー(builder引数)とGoのコミットハッシュ(goHash引数)に基づいて、サブリポジトリのビルドタスクを生成するかどうかを決定します。

変更前は、buildTodo関数はGo本体のコミットが正常にビルドされたかどうかに関わらず、サブリポジトリのビルドタスクの生成を試みていました。

変更後のロジックでは、サブリポジリのビルドタスクを生成する前に、以下のチェックが追加されました。

  1. 現在のGoコミットの取得: tag.Commit(c)を呼び出して、現在のGoコミット(goHashに対応するコミット)の情報を取得します。ここで取得されるcomオブジェクトは、そのコミットに関するメタデータやビルド結果を保持していると考えられます。
  2. Goコミットのビルド結果の確認: 取得したcomオブジェクトに対してcom.Result(builder, "")を呼び出します。
    • Resultメソッドは、指定されたbuilder(ビルドワーカー)とパッケージパス(ここではGo本体のビルド結果を見るため空文字列"")に対するビルド結果を返します。
    • 返された結果オブジェクトがnilでない(つまり、ビルド結果が存在する)かつ、!r.OKである(つまり、ビルドが成功していない、失敗している)場合に、Go本体のビルドが失敗していると判断します。
  3. タスク生成の抑制: もしGo本体のビルドが失敗していると判断された場合、return nil, nilを実行します。これにより、buildTodo関数はビルドタスクを生成せずに終了し、無駄なサブリポジトリのビルドが回避されます。

この変更により、Go Dashboardはより効率的に動作し、ビルド結果の表示もより正確になります。

コアとなるコードの変更箇所

--- a/misc/dashboard/app/build/handler.go
+++ b/misc/dashboard/app/build/handler.go
@@ -215,10 +215,22 @@ func buildTodo(c appengine.Context, builder, packagePath, goHash string) (interf
 	// see if there are any subrepo commits that need to be built at tip.
 	// If so, ask the builder to build a go tree at the tip commit.
 	// TODO(adg): do the same for "weekly" and "release" tags.
+\n
 	tag, err := GetTag(c, "tip")
 	if err != nil {
 		return nil, err
 	}
+\n
+\t// Check that this Go commit builds OK for this builder.
+\t// If not, don't re-build as the subrepos will never get built anyway.
+\tcom, err := tag.Commit(c)
+\tif err != nil {
+\t\treturn nil, err
+\t}\
+\tif r := com.Result(builder, ""); r != nil && !r.OK {
+\t\treturn nil, nil
+\t}\
+\n
 	pkgs, err := Packages(c, "subrepo")
 	if err != nil {
 		return nil, err
@@ -233,6 +245,7 @@ func buildTodo(c appengine.Context, builder, packagePath, goHash string) (interf
 			return tag.Commit(c)
 		}
 	}\n+\n 	return nil, nil
 }

コアとなるコードの解説

追加されたコードブロックは以下の部分です。

	// Check that this Go commit builds OK for this builder.
	// If not, don't re-build as the subrepos will never get built anyway.
	com, err := tag.Commit(c)
	if err != nil {
		return nil, err
	}
	if r := com.Result(builder, ""); r != nil && !r.OK {
		return nil, nil
	}
  1. // Check that this Go commit builds OK for this builder. // If not, don't re-build as the subrepos will never get built anyway. このコメントは、追加されるロジックの目的を明確に説明しています。Go本体のコミットがこのビルドワーカーで正常にビルドされるかを確認し、もし失敗している場合は、サブリポジトリのビルドを再試行しないという意図が示されています。これは、サブリポジリのビルドがGo本体のビルドに依存しているため、Go本体が失敗していればサブリポジリも成功する見込みがないという前提に基づいています。

  2. com, err := tag.Commit(c) tagオブジェクト(おそらくGetTag(c, "tip")で取得された、現在のGoのtip、つまり最新のコミットに関する情報を持つオブジェクト)のCommitメソッドを呼び出し、現在のappengine.Context cを渡して、Go本体のコミット情報を取得しています。このcom変数は、取得したコミットの詳細(ハッシュ、作者、日付、そしてビルド結果など)を保持するオブジェクトであると推測されます。エラーが発生した場合は、即座にnil, errを返して処理を中断します。

  3. if r := com.Result(builder, ""); r != nil && !r.OK { この行が変更の核心部分です。

    • r := com.Result(builder, ""): comオブジェクトのResultメソッドを呼び出しています。
      • 第一引数builderは、現在処理しているビルドワーカーの名前です。
      • 第二引数""(空文字列)は、特定のパッケージパスを指定しないことを意味します。これは、Go本体全体のビルド結果を参照していることを示唆しています。
      • この呼び出しは、指定されたbuilderにおけるGo本体のビルド結果を返します。その結果はrという変数に代入されます。
    • r != nil: Resultメソッドがnil以外の値を返した場合、それはそのbuilderに対するビルド結果が存在することを示します。
    • !r.OK: rオブジェクトのOKフィールドがfalseである場合、それはそのビルドが成功しなかった(つまり、失敗した)ことを意味します。
    • このif文全体は、「もし、このGoコミットがこのビルドワーカーでビルド結果を持っており、かつそのビルドが成功していなかった場合」という条件をチェックしています。
  4. return nil, nil 上記のif条件が真(Go本体のビルドが失敗している)の場合、この行が実行されます。buildTodo関数はnil, nilを返します。これは、新しいビルドタスク(todo)を生成しないことを意味します。これにより、Go本体のビルド失敗に起因する無駄なサブリポジトリのビルドタスクの生成が抑制されます。

関連リンク

参考にした情報源リンク

  • Go Dashboardのソースコード(misc/dashboardディレクトリ): Goリポジトリ内のこのディレクトリは、Go Dashboardのアプリケーションコードを含んでいます。
  • Go言語の公式ドキュメント: Go言語のビルドシステムやパッケージ管理に関する一般的な情報。
  • Google App Engineのドキュメント: Go DashboardがApp Engine上で動作しているため、appengine.Contextなどの理解に役立ちます。