mesh-build-go: let a check's go vet warm the shared Go build cache with cgo off, and say each linted directory as it ends
A check's lint recompiled every package from a cold layer on each ask (g14 linted mesh-catalog's 8 directories in 141 s where ace, warm, took 17 s), and said nothing until it ended. ADR 0541 §2 and ADR 0542 §1 decided this; the built speed-up on feat/try-speed (S11) was parked. Ported here alone: CGO_ENABLED=0 in every check command's go environment, vet runs with the shared caches writable, and the lint says a phase per finished directory (issue 1921).
This commit is contained in:
@@ -296,6 +296,7 @@ func (m *Module) goEnv() []string {
|
||||
modcache = m.GoModCache
|
||||
}
|
||||
return append([]string{
|
||||
"CGO_ENABLED=0", // as a production build compiles (build.go), so a check tests what ships and the warm cache matches (ADR 0542 §1)
|
||||
"GOTOOLCHAIN=local",
|
||||
"GOFLAGS=-mod=mod",
|
||||
"GOMODCACHE=" + modcache,
|
||||
|
||||
@@ -45,7 +45,7 @@ func (m *Module) isolation(workspace string, write bool) buildstep.Isolation {
|
||||
}
|
||||
|
||||
// stepRunner is the runner of a run step of the workspace: buildstep.Isolated over m.Run, so every command it runs is
|
||||
// shut off; write is true for a trunk build alone (the shared caches are written by trunk builds only). Inside is the
|
||||
// shut off; write is true for a trunk build and for a check's go vet, compile steps that run nothing of the change (ADR 0541 §2). Inside is the
|
||||
// integration level's own process, already running shut off (level.go): it runs its commands as they are.
|
||||
func (m *Module) stepRunner(workspace string, write bool) (forgekey.Runner, error) {
|
||||
if m.Inside {
|
||||
|
||||
@@ -130,8 +130,23 @@ func TestTheUnitLevelRunsEveryGoTestShutOff(t *testing.T) {
|
||||
if ran == 0 || len(seen) != ran {
|
||||
t.Fatalf("%d go commands ran, %d of them shut off: %v", ran, len(seen), *calls)
|
||||
}
|
||||
// A check compiles with cgo off as a build does (ADR 0542 §1), and the lint's go vet, a compile that runs nothing
|
||||
// of the change, writes the shared caches; every other command reads them beneath its own layer (ADR 0541 §2).
|
||||
for _, c := range *calls {
|
||||
if strings.HasPrefix(c.line, "go ") && !slices.Contains(c.env, "CGO_ENABLED=0") {
|
||||
t.Errorf("%s ran without CGO_ENABLED=0: %v", c.line, c.env)
|
||||
}
|
||||
}
|
||||
vets := 0
|
||||
for _, s := range seen {
|
||||
checkShutOff(t, m, s, false)
|
||||
vet := strings.Contains(s.command, " vet ")
|
||||
if vet {
|
||||
vets++
|
||||
}
|
||||
checkShutOff(t, m, s, vet)
|
||||
}
|
||||
if vets == 0 {
|
||||
t.Error("no go vet ran shut off")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-sdk/go/buildstep"
|
||||
"git.novox.be/novox/mesh-sdk/go/forgekey"
|
||||
@@ -144,6 +145,18 @@ func (m *Module) lintAll(ctx context.Context, run forgekey.Runner, tree string,
|
||||
var wg sync.WaitGroup
|
||||
var crash any // a panic of a lint goes on in the caller, as a panic of a test run does
|
||||
var crashMu sync.Mutex
|
||||
// Each directory's end is said as a phase, so a long lint is readable while it runs (issue 1921): which directories
|
||||
// are done and how long the last one took.
|
||||
var doneMu sync.Mutex
|
||||
done := 0
|
||||
said := func(d string, began time.Time) {
|
||||
doneMu.Lock()
|
||||
defer doneMu.Unlock()
|
||||
done++
|
||||
if done < len(dirs) {
|
||||
buildstep.Phase(ctx, fmt.Sprintf("unit: lint of %d directories, %d done (%s in %s)", len(dirs), done, d, m.clock().Sub(began).Round(time.Second)))
|
||||
}
|
||||
}
|
||||
for i, d := range dirs {
|
||||
wg.Add(1)
|
||||
slots <- struct{}{}
|
||||
@@ -157,7 +170,9 @@ func (m *Module) lintAll(ctx context.Context, run forgekey.Runner, tree string,
|
||||
crashMu.Unlock()
|
||||
}
|
||||
}()
|
||||
began := m.clock()
|
||||
answers[i].failed, answers[i].err = m.lint(ctx, run, tree, d, env(d))
|
||||
said(d, began)
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
@@ -251,8 +251,15 @@ func (m *Module) runLevel(ctx context.Context, tree string, o levelOpts) (*TestR
|
||||
if o.level == LevelUnit {
|
||||
// gofmt and go vet of each directory the level runs come before its tests (ADR 0529 §1; issue 1887 D7-go): a
|
||||
// directory that fails them fails the level at once, and their time is the result's Lint.
|
||||
// go vet compiles and runs nothing of the change, with cgo off (goEnv), so it writes the shared cache and warms it
|
||||
// for every later check, a pull request's head included (ADR 0541 §2, ADR 0542 §1); the tests run beneath their
|
||||
// own throwaway layer.
|
||||
compile, err := m.stepRunner(o.workspace, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
linted := m.clock()
|
||||
failed, err := m.lintAll(ctx, run, tree, todo, func(d string) []string {
|
||||
failed, err := m.lintAll(ctx, compile, tree, todo, func(d string) []string {
|
||||
return append(m.goEnvFor(filepath.Join(tree, d)), o.env...)
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user