Go Wiki: Watchflakes

Watchflakesは、build.golang.orgダッシュボード上の見かけ上のテストフレークをトリアージするプログラムです。

見かけ上のテストフレークとは、次の条件を満たす失敗のことです。

Watchflakesは、すべての見かけ上のテストフレークをTest Flakesプロジェクトのissueに投稿します。

Test Flakesプロジェクトのすべてのissueの説明は、そのissueに関連する失敗のパターンで始まります。たとえば、#55260の説明のmarkdownは次のように始まります。

```
#!watchflakes
post <- pkg == "cmd/go" && test == "" && `unexpected files left in tmpdir`
```

Watchflakesは、すべての見かけ上のテストフレークをissueのパターンと照合します。

新しく作成されたissueのパターンは、しばしば広すぎるため、実際の失敗により具体的に絞り込むように編集する必要があります。失敗を最も小さい番号の一致するissueに送信することで、新しい失敗の広範なデフォルトパターンを作成しても、以前のissueから失敗を「盗む」ことはなく、同じテストで既に個別に追跡されている無関係な失敗で新しいissueをスパムすることもありません。

Watchflakesは、新しく作成されたissueをTest Flakesプロジェクトに配置し、NeedsInvestigationラベルを追加します。これらのissueは、ステータス(Active、Doneではない)なしで開始されます。ステータスがないissueは、通常、失敗に関する重要な情報をキャプチャするようにパターンを修正する必要がある人が検査する必要があります。チェックされたissueは、Activeに移動できます。GitHubは、issueがクローズされると、自動的にActiveからDoneに移動します。

Watchflakesは、新しい失敗を照合する際に、すべてのステータスのissueを考慮します。クローズされたissueの新しい失敗を見つけた場合、失敗を投稿してissueを再度開きます。したがって、失敗が本当に消えたかどうかを確認するために数週間待つ必要はなく、修正が適用されたらissueをクローズしても問題ありません。新しい失敗が発生した場合、issueは自動的に再度開かれます。

Watchflakesは独自のステートを維持しません。すべてのステートはGitHub issueにあります。実行されるたびに、過去60日間のビルドダッシュボードの失敗を考慮し、すべての見かけ上のフレークがTest Flakesプロジェクトで考慮されていることを確認します。issueに一致する失敗がすでにそのissueに投稿されている場合、watchflakesは再度投稿することはありません。また、特定の失敗を除外するようにパターンを更新するためにissueが編集された場合、watchflakesは古い投稿を削除しませんが、それらの失敗に対して別の照合issueを探し、新しいissueを作成する可能性も含めます。

構文

各issueのwatchflakesスタンザは、issueの説明の先頭に表示する必要があります。これはコードブロック(```で囲まれているか、インデントされている)である必要があり、watchflakesが関係のないコードブロックを誤解しないように、最初の行は#!watchflakesである必要があります。

ブロックの残りは、小さなwatchflakesスクリプトです。行末までのコメントは#で導入されます。スクリプトは、action <- pattern(patternの一致をactionに送信する)という形式を持つルールのシーケンスです。

アクション

アクションは次のとおりです。

レコード

パターンへの入力は、名前付きフィールドを持つレコードであり、各フィールドには文字列値があります。

パターン

パターンは、複雑な式を作成するための||、&&、!、(、および)を許可するGoのような構文のブール式です。フィールドを文字列リテラルと比較するための==、!=、<、<=、>、および>=、および正規表現との照合のための~および!~。

すべての文字列比較は、左側にフィールド名、右側に二重引用符で囲まれた文字列リテラルが必要です(例:builder == "linux-amd64-alpine"または`goos == ")。

すべての正規表現一致は、左側にフィールド名、右側にバッククォートで囲まれた文字列リテラルが必要です(例:builder ~ `corellium`)。

バッククォートで囲まれた文字列リテラルは、それ自体でoutputフィールドとの比較と見なされ、これはパターンの正規表現の大部分に適切です。

これらすべてをまとめると、ここにいくつかのスクリプト例があります。

#!watchflakes
post <- pkg == "net/http" && test == "TestHandlerAbortRacesBodyRead"

#55277のこのスクリプトは、http.TestHandlerAbortRacesBodyReadで失敗したビルド実行に応じて、watchflakesによって自動的に作成されました。issueの作成を促した特定の失敗はタイムアウトでした。そのテストで異なる根本原因を持つ失敗がさらに見つかった場合は、&& `panic: test timed out`を追加するか、パターンを改良することが適切になる可能性があります。

#!watchflakes
post <- goos == "openbsd" && `unlinkat .*: operation not permitted`

#49751のこのスクリプトは、openbsdでos.Removeがunlinkatを呼び出したときに発生する予期しないEPERMエラーによって引き起こされる失敗を収集します。これらの失敗はさまざまなテストで問題を引き起こすため、pkgまたはtestに条件はありません。

#!watchflakes
post <- pkg ~ `^cmd/go` && `appspot.com.*: 503`

#54608のこのスクリプトは、cmd/go/…パッケージ階層(cmd/go自体だけでなく)のすべてのテストで、appspot.comからの503応答によるネットワークの問題を追跡します。

#!watchflakes
post <- goos == "windows" &&
        (`dnsquery: DNS server failure` || `getaddrinfow: This is usually a temporary error`)

#55165のこのスクリプトは、Windowsを実行しているビルダーのすべてのテストで、特定のDNS障害に一致します。

#!watchflakes
post <- builder == "darwin-arm64-12" && pkg == "" && test == ""

#55312のこのスクリプトは、特定のパッケージテストを実行する前に発生するdarwin-arm64-12ビルダーでの失敗を追跡するために、watchflakesによって自動的に作成されました。

#!watchflakes
# note: sometimes the URL is printed with one /
default <- `(Get|read) "https://?(goproxy.io|proxy.golang.com.cn|goproxy.cn)`

#55163のこのスクリプトは、特定の非標準Goプロキシを使用するエラーに一致します。これは、これらのプロキシによって引き起こされるより具体的な失敗の所有権を他のissueに許可するためにdefaultを使用します。他のissueと一致しない失敗は、新しいissueを作成する代わりに#55163に送信されます。

#!watchflakes
default <- `: internal compiler error:`

このスクリプト(#55257)は、どのパッケージやリポジトリがテストされていても、あらゆるビルドにおけるコンパイラの失敗を照合します。前の例と同じ理由でdefaultを使用しています。つまり、特定のコンパイラエラーに一致する問題は引き続きファイルできますが、他の問題に一致しない失敗は、問題をトリガーした特定のテストに割り当てられた新しい問題を作成する代わりに、#55257 にグループ化されます。


このコンテンツはGo Wikiの一部です。