package meshdeliverycheckerclient import ( "encoding/json" "fmt" "strings" checker "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshdeliverychecker" "git.novox.be/novox/mesh-sdk/go/keys" ) // The codecs of the three states the checker writes and others read (the view and the gate read verdicts, the indexer reads // previews, the checker and the tools read kept verdicts): a value is written at the version of the kept values after its rules // (CheckVerdict, CheckKept, CheckPreview) and read back through the same rules. The checker's owed state is read by no other // part and keeps its own codec. // EncodeVerdict is v as JSON at the kept values' version, refused by CheckVerdict's rules. func EncodeVerdict(v checker.VerdictsByGroupHeadsValue) ([]byte, error) { if err := CheckVerdict(v); err != nil { return nil, err } v.V = keys.Version return json.Marshal(v) } // DecodeVerdict reads a `verdicts` value; it refuses an unknown version (keys.ErrUnknownVersion) and what EncodeVerdict refuses. func DecodeVerdict(data []byte) (checker.VerdictsByGroupHeadsValue, error) { var v checker.VerdictsByGroupHeadsValue if err := decode(data, &v); err != nil { return v, err } if err := CheckVerdict(v); err != nil { return checker.VerdictsByGroupHeadsValue{}, err } return v, nil } // EncodeKept is k as JSON at the kept values' version, refused by CheckKept's rules. func EncodeKept(k checker.KeptByLevelDigestValue) ([]byte, error) { if err := CheckKept(k); err != nil { return nil, err } k.V = keys.Version return json.Marshal(k) } // DecodeKept reads a `kept` value; it refuses an unknown version and what EncodeKept refuses. func DecodeKept(data []byte) (checker.KeptByLevelDigestValue, error) { var k checker.KeptByLevelDigestValue if err := decode(data, &k); err != nil { return k, err } if err := CheckKept(k); err != nil { return checker.KeptByLevelDigestValue{}, err } return k, nil } // EncodePreview is p as JSON at the kept values' version, refused by CheckPreview's rules. func EncodePreview(p checker.PreviewsByRepositoryHeadTrunkValue) ([]byte, error) { if err := CheckPreview(p); err != nil { return nil, err } p.V = keys.Version return json.Marshal(p) } // DecodePreview reads a `previews` value; it refuses an unknown version and what EncodePreview refuses. func DecodePreview(data []byte) (checker.PreviewsByRepositoryHeadTrunkValue, error) { var p checker.PreviewsByRepositoryHeadTrunkValue if err := decode(data, &p); err != nil { return p, err } if err := CheckPreview(p); err != nil { return checker.PreviewsByRepositoryHeadTrunkValue{}, err } return p, nil } func decode(data []byte, into any) error { if err := keys.CheckVersion(data); err != nil { return err } if err := json.Unmarshal(data, into); err != nil { return fmt.Errorf("meshdeliverycheckerclient: value does not fit its shape: %w", err) } return nil } // KeptKey is the key, in the state kept, of a kept verdict: `.`, the level unit or integration and the digest, // lowercase hex, of everything that package's tests read at that level as the language's build module names it. func KeptKey(level, digest string) (string, error) { if err := checkLevel(level); err != nil { return "", err } if digest == "" || strings.Trim(digest, "0123456789abcdef") != "" { return "", fmt.Errorf("meshdeliverycheckerclient: %q is not a digest, lowercase hex", digest) } return checker.KeptByLevelDigestKey(level, digest), nil } // ParseKeptKey is the inverse of KeptKey. func ParseKeptKey(key string) (level, digest string, err error) { level, digest, ok := checker.ParseKeptByLevelDigestKey(key) if !ok { return "", "", fmt.Errorf("meshdeliverycheckerclient: %q is not a kept key, .", key) } if _, err = KeptKey(level, digest); err != nil { return "", "", fmt.Errorf("meshdeliverycheckerclient: %q is not a kept key: %w", key, err) } return level, digest, nil } // PreviewKey is the key, in the state previews, of a head merged onto a trunk commit: `..`, the // repository's owner and name each escaped (keys.EscapeName). func PreviewKey(repository, head, trunk string) (string, error) { if err := CheckRepository(repository); err != nil { return "", err } if err := keys.CheckName("head", head); err != nil { return "", err } if err := keys.CheckName("trunk commit", trunk); err != nil { return "", err } owner, name, _ := strings.Cut(repository, "/") return checker.PreviewsByRepositoryHeadTrunkKey(keys.EscapeName(owner)+"/"+keys.EscapeName(name), head, trunk), nil } // ParsePreviewKey is the inverse of PreviewKey. func ParsePreviewKey(key string) (repository, head, trunk string, err error) { repo, head, trunk, ok := checker.ParsePreviewsByRepositoryHeadTrunkKey(key) if !ok || strings.Contains(trunk, ".") { return "", "", "", fmt.Errorf("meshdeliverycheckerclient: %q is not a preview key, ..", key) } owner, name, found := strings.Cut(repo, "/") if !found { return "", "", "", fmt.Errorf("meshdeliverycheckerclient: %q is not a preview key: the repository has no slash", key) } owner, err1 := keys.UnescapeName(owner) name, err2 := keys.UnescapeName(name) if err1 != nil || err2 != nil { return "", "", "", fmt.Errorf("meshdeliverycheckerclient: %q is not a preview key: the repository does not unescape", key) } repository = owner + "/" + name if _, err := PreviewKey(repository, head, trunk); err != nil { return "", "", "", fmt.Errorf("meshdeliverycheckerclient: %q is not a preview key: %w", key, err) } return repository, head, trunk, nil }