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。當 issue 關閉時,GitHub 會自動將其從 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(將模式的匹配項傳送到 action)。

Actions

Actions 是

  • post 將失敗釋出到指令碼所在的 issue。
  • skip 忽略失敗,將其丟棄。此操作應僅在很少使用(例如,用於設定策略,如 #55166)。
  • default 是 post 的低優先順序版本。如果 issue 有匹配失敗的 postskip,watchflakes 將執行該操作。但如果沒有其他匹配項,watchflakes 會考慮 default 模式匹配。(然後,如果沒有 default 匹配項,watchflakes 將建立一個新的 issue。)

Records

模式的輸入是一個具有命名欄位的記錄,每個欄位都有一個字串值

  • pkg 是失敗的構建或失敗的測試的包的完整匯入路徑。

  • test 是包中失敗的測試函式的名稱。

  • modebuildtest,取決於這是構建失敗還是測試失敗。

  • 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。它對於主倉庫中在備用執行環境中重新執行測試的測試最有幫助。

Patterns

模式是一個 Go 風格的語法中的布林表示式,允許使用 ||、&&、!、( 和 ) 構建複雜表示式;使用 ==、!=、<、<=、> 和 >= 將欄位與字串字面量進行比較;以及使用 ~ 和 !~ 與正則表示式進行匹配。

所有字串比較都必須在左側有一個欄位名,在右側有一個雙引號括起來的字串字面量,例如 builder == "linux-amd64-alpine" 或 `goos == "

所有正則表示式匹配都必須在左側有一個欄位名,在右側有一個反引號括起來的字串字面量,例如 builder ~ `corellium`

單獨的反引號字串字面量被視為與 output 欄位的比較,這適用於絕大多數模式中的正則表示式。

示例

將所有這些放在一起,這裡有一些示例指令碼。

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

此指令碼在 #55277 中是 watchflakes 響應 http.TestHandlerAbortRacesBodyRead 中的構建執行失敗而自動建立的。促使 issue 建立的具體失敗是超時。如果在該測試中發現了更多具有不同根本原因的失敗,則可能適當地新增 && `panic: test timed out` 或以其他方式細化模式。

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

此指令碼在 #49751 中收集了由於 os.Remove 呼叫 unlinkat 產生的意外 EPERM 錯誤在 openbsd 上引起的失敗。這些失敗會導致各種測試出現問題,因此對 pkgtest 沒有條件限制。

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

此指令碼在 #54608 中跟蹤了 cmd/go/... 包層次結構中任何測試的 appspot.com 產生的 503 響應的網路問題,而不僅僅是 cmd/go 本身。

#!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 中是 watchflakes 自動建立的,用於跟蹤 darwin-arm64-12 構建器上在該特定包測試執行之前發生的故障。

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

此指令碼在 #55163 中匹配使用某些非標準 Go 代理的錯誤。它使用 default 來允許其他 issue 承擔這些代理引起的更具體失敗的所有權。未匹配其他 issue 的失敗將轉到 #55163,而不是建立新的 issue。

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

此指令碼在 #55257 中匹配任何構建中的編譯器故障,無論正在測試什麼包或倉庫。它出於與上一個示例相同的原因使用 default:因此,匹配特定編譯器錯誤的 issue 仍然可以歸檔,但未匹配其他 issue 的失敗將被分組到 #55257 中,而不是建立分配給觸發問題的特定測試的新 issue。


此內容是 Go Wiki 的一部分。