package check import ( "context" "errors" "fmt" "sort" "time" "git.novox.be/novox/mesh-sdk/go/delivery" ) // Kept is the checker's bucket of kept verdicts (ADR 0444, ADR 0484 clause 13): a passing verdict per package and level, // under the digest the language's build module named for it. A key is written once, by a create that fails when it // exists, from the result the checker read from the test step and never from anything the code under test wrote; nothing // changes it afterwards. type Kept struct{ Store KV } // Lookup is the kept verdict of a level under a digest, or none. func (k Kept) Lookup(ctx context.Context, level, digest string) (delivery.Kept, bool, error) { key, err := delivery.KeptKey(level, digest) if err != nil { return delivery.Kept{}, false, err } value, _, found, err := k.Store.Get(ctx, key) if err != nil || !found { return delivery.Kept{}, false, err } v, err := delivery.DecodeKept(value) if err != nil { return delivery.Kept{}, false, fmt.Errorf("%s holds what is not a kept verdict: %w", key, err) } return v, true, nil } // Keep writes v under level and digest by a create. It answers false, and writes nothing, when the key exists: the first // value stands. func (k Kept) Keep(ctx context.Context, level, digest string, v delivery.Kept) (bool, error) { key, err := delivery.KeptKey(level, digest) if err != nil { return false, err } v.Level = level data, err := delivery.EncodeKept(v) if err != nil { return false, err } if _, err := k.Store.Create(ctx, key, data); err != nil { if errors.Is(err, ErrConflict) { return false, nil } return false, fmt.Errorf("%s: %w", key, err) } return true, nil } // KeepPasses keeps, for the packages of a test result that passed with tests, a verdict under the digest the build module // named for the package at the level. A package that failed, has no tests or has no digest is never kept (ADR 0444 clause // 1): it runs every check. It answers the packages it kept now. func (k Kept) KeepPasses(ctx context.Context, repository, level, toolchain string, res Tested, digests map[string]string, at time.Time) ([]string, error) { var kept []string for _, p := range res.Packages { digest, ok := digests[p.Package] if !ok || !p.Passed || p.NoTests || p.Tests == 0 { continue } if failedIn(res, p.Package) { continue } made, err := k.Keep(ctx, level, digest, delivery.Kept{State: delivery.VerdictPass, Repository: repository, Package: p.Package, Level: level, Tests: p.Tests, Took: int64(p.Elapsed * 1000), Toolchain: toolchain, At: at}) if err != nil { return kept, err } if made { kept = append(kept, p.Package) } } sort.Strings(kept) return kept, nil } func failedIn(res Tested, pkg string) bool { for _, f := range res.Failed { if f.Package == pkg { return true } } return false }