fix(qualitygate): keep both layering walks out of dot directories

skipLayeringScopeDir named .git explicitly and skipped every "_" prefix, but the
go command ignores "." and "_" alike, so `go list ./...` never offers a dot
directory's files to any configuration. The walk descended into them anyway, and
TestLayeringBuildConfigsSelectEveryFile then demanded a configuration that had
compiled them: a gitignored .cache/ holding one Go probe file fails the suite with
"is compiled by none of the 28 executed configurations". CI checks out clean, so
this only ever bit a developer with build scratch in the tree.

The predicate now answers the scope its own comment claims — what `go list ./...`
builds — and the module root stays in scope whatever it is called, so a checkout
under a directory the rules would otherwise reject does not empty both walks.
This commit is contained in:
shanglei
2026-07-30 14:26:15 +08:00
parent 8f3e9630a1
commit 1698ac1ff3

View File

@@ -365,13 +365,23 @@ func collectBuildConstraints(t *testing.T, root string) []buildConstraintGroup {
// contradiction: a constraint in a nested module would add a configuration whose
// only justification is a file that module walk never requires to be selected.
func skipLayeringScopeDir(root, path, name string) bool {
// Directories the Go tool never builds from.
if name == ".git" || name == "node_modules" || name == "testdata" || strings.HasPrefix(name, "_") {
// The module root is in scope whatever it is called: a checkout can sit
// under a directory the rules below would otherwise reject (".worktrees/x"),
// and skipping it would empty both walks.
if path == root {
return false
}
// Directories the Go tool never builds from. Every name beginning with "."
// or "_" is ignored by the go command — which covers ".git" without naming
// it, and keeps a gitignored scratch directory that happens to hold Go files
// (".cache/…") from being demanded of configurations `go list ./...` never
// offered it to.
if strings.HasPrefix(name, ".") || strings.HasPrefix(name, "_") || name == "node_modules" || name == "testdata" {
return true
}
// Nested modules: `go list ./...` stops at them, and the rules are written
// against this module's import paths.
return path != root && isModuleRoot(path)
return isModuleRoot(path)
}
// isModuleRoot reports whether dir declares its own module.
@@ -1390,6 +1400,16 @@ func TestLayeringScopeStopsAtNestedModules(t *testing.T) {
if skipLayeringScopeDir(root, root, filepath.Base(root)) {
t.Error("the module root declares this module and must stay in scope")
}
// The go command ignores directories whose name begins with "." or "_", so
// `go list ./...` never offers their files to any configuration. Walking
// into one turns a developer's gitignored scratch directory into a file the
// selection check demands and cannot find.
for _, name := range []string{".cache", ".git", "_scratch", "node_modules", "testdata"} {
if !skipLayeringScopeDir(root, filepath.Join(root, name), name) {
t.Errorf("%s is outside what `go list ./...` builds and must be out of scope for both walks", name)
}
}
}
func mustParseConstraint(t *testing.T, line string) constraint.Expr {