91 lines
2.8 KiB
Go
91 lines
2.8 KiB
Go
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
|
|
}
|