cmd/mbf: validate build determinism
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 3m2s
Test / ShareFS (push) Successful in 6m4s
Test / Hakurei (push) Successful in 6m15s
Test / Sandbox (race detector) (push) Successful in 7m31s
Test / Hakurei (race detector) (push) Successful in 8m49s
Test / Flake checks (push) Successful in 1m17s
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 3m2s
Test / ShareFS (push) Successful in 6m4s
Test / Hakurei (push) Successful in 6m15s
Test / Sandbox (race detector) (push) Successful in 7m31s
Test / Hakurei (race detector) (push) Successful in 8m49s
Test / Flake checks (push) Successful in 1m17s
This rebuilds a package repeatedly and compares outcomes. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -27,6 +27,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
@@ -897,6 +898,82 @@ func main() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.NewCommand(
|
||||||
|
"validate",
|
||||||
|
"Repeatedly cure named artifact to validate determinism",
|
||||||
|
func(args []string) error {
|
||||||
|
stage := rosa.Std
|
||||||
|
if len(args) == 3 {
|
||||||
|
switch args[0] {
|
||||||
|
case "boot":
|
||||||
|
stage -= 2
|
||||||
|
case "std":
|
||||||
|
stage -= 1
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid stage %q", args[0])
|
||||||
|
}
|
||||||
|
args = args[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(args) != 2 {
|
||||||
|
return errors.New("validate requires 2 arguments")
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := strconv.Atoi(args[0])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid passes %q", args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if n < 2 {
|
||||||
|
return errors.New("validate must rebuild at least twice")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, a := rosa.Native().New(stage).Load(rosa.ArtifactH(unique.Make(args[1])))
|
||||||
|
if a == nil {
|
||||||
|
return fmt.Errorf("unknown artifact %q", args[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.IsExclusive() && cm.jobs < 1 {
|
||||||
|
cm.jobs = runtime.NumCPU()/n + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
res := make([]unique.Handle[pkg.Checksum], n)
|
||||||
|
if err = cm.Do(func(cache *pkg.Cache) error {
|
||||||
|
errs := make([]error, n)
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := range n {
|
||||||
|
wg.Go(func() {
|
||||||
|
_, res[i], errs[i] = cache.CureNew(a)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
return errors.Join(errs...)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range n - 1 {
|
||||||
|
if res[i] == res[i+1] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf strings.Builder
|
||||||
|
buf.WriteString("nondeterminism:")
|
||||||
|
for _, o := range res {
|
||||||
|
buf.WriteString("\n\t")
|
||||||
|
buf.WriteString(filepath.Join(
|
||||||
|
cm.base,
|
||||||
|
"checksum",
|
||||||
|
pkg.Encode(o.Value()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
return errors.New(buf.String())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
cleanC := c.New("clean", "Remove unused entries from the cache")
|
cleanC := c.New("clean", "Remove unused entries from the cache")
|
||||||
cleanC.NewCommand(
|
cleanC.NewCommand(
|
||||||
"fault",
|
"fault",
|
||||||
|
|||||||
Reference in New Issue
Block a user