Go Wiki: Watchflakes
Watchflakesは、build.golang.orgダッシュボード上の見かけ上のテストフレークをトリアージするプログラムです。
見かけ上のテストフレークとは、次の条件を満たす失敗のことです。
- 完全に失敗しているビルダー上ではない。
- 除外されたビルダー上ではない。
- 4つ以上のビルダーで失敗したコミットを実行しているのではない。
- 自身のビルダーで4つ以上の失敗したコミットの実行の一部ではない。
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に投稿されます。
- フレークがどのissueのパターンにも一致しない場合、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に送信する)という形式を持つルールのシーケンスです。
アクション
アクションは次のとおりです。
post
は、スクリプトが表示されるissueに失敗を投稿します。skip
は、失敗を無視し、破棄します。このアクションは、(たとえば、#55166のようにポリシーを設定する場合など)まれにのみ使用する必要があります。default
は、postの優先度の低いバージョンです。issueに失敗と一致するpost
またはskip
がある場合、watchflakesは代わりにそれを行います。ただし、他に一致するものがない場合、watchflakesはdefault
パターンの一致を考慮します。(それでもdefault
一致がない場合、watchflakesは新しいissueを作成します。)
レコード
パターンへの入力は、名前付きフィールドを持つレコードであり、各フィールドには文字列値があります。
-
pkg
は、ビルドに失敗したパッケージまたはテストに失敗したパッケージの完全なインポートパスです。 -
test
は、失敗したパッケージ内のテスト関数の名前です。 -
mode
は、ビルドの失敗かテストの失敗かに応じて、build
またはtest
です。 -
output
は、失敗したテストからの出力です。この出力は、テストバイナリが終了するときに出力される最後のFAIL
行の直前で停止します。同じ実行で失敗した他のテストケースからの出力や、テスト開始前にall.bashまたはbuildletによって出力されたコンテキストは含まれません。 -
log
は、失敗したビルドログ全体です。 -
snippet
は、issue自体に投稿されるoutput
の短縮形です。一致は、ほとんど常に代わりにoutput
を使用する必要があります。 -
builder
は、テストを実行したビルダーの名前(dragonfly-amd64-622
など)です。 -
repo
は、テストされているリポジトリの名前(go
、net
、tools
、…)です。 -
goos
は、GOOS値(linux
、windows
、…)です。 -
goarch
は、GOARCH値(amd64
、mips64le
、…)です。 -
date
は、テストされているコミットの日付であり、2006-01-02T15:04:05
の形式です。日付比較ロジックはありません。代わりに文字列比較を使用してください。日付の比較は、まれに使用する必要があります。 -
section
は、失敗が発生したビルドログのセクションです。all.bash出力では、セクションは#####
で導入され、ブートストラップ中の各Building
行も独自のセクションと見なされます。サブリポジトリでは、:: Running
行のそれぞれが、実行されているgoコマンドの名前(たとえば、go test golang.org/x/tools/...
)で名前が付けられたセクションを導入します。ほとんどのパターンは
section
を使用する必要はありません。これは、代替実行環境でテストを再実行するメインリポジトリのテストに最も役立ちます。
パターン
パターンは、複雑な式を作成するための||、&&、!、(、および)を許可する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の一部です。