The delivery repository's contracts and SDK live under modules/ as mesh-delivery-contracts and mesh-delivery-sdk, their Go module paths renamed to match the folders (the TypeScript names already did), and every importer in mesh-delivery, mesh-catalog, mesh-host, mesh-tools and mesh-sdk follows in the same group: a design as it should be, one path per module, checked by the group's check building every importer. Builds: design 47 G §427, §88 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
116 lines
4.0 KiB
Go
116 lines
4.0 KiB
Go
package check
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/clients/meshcatalogclient"
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
)
|
|
|
|
// declaredPackage is one package a group member declares: the module, its directory in the repository (RootPath for its
|
|
// root, empty when not known), and the artifact's name, paths and language.
|
|
type declaredPackage struct {
|
|
pull Pull
|
|
module, dir string
|
|
name string
|
|
paths []string
|
|
language string
|
|
}
|
|
|
|
// manifestAtHead is a touched module's manifest read from the forge at its member's head (the lead's ruling 4 on A2c's
|
|
// finding 4): with no preview of the merge, a package new in the group is declared only there, never at the trunk. The
|
|
// module's directory is the indexer's when it knows the module, else modules/<module> or the repository's root, the one
|
|
// whose manifest names the module. Found is false when no such file names it.
|
|
func (st *state) manifestAtHead(ctx context.Context, p Pull, module string) (m catalogue.Manifest, dir string, found bool, err error) {
|
|
var dirs []string
|
|
if st.j.Dirs != nil {
|
|
if d, ok := st.j.Dirs.ModuleDir(module); ok {
|
|
dirs = []string{d}
|
|
}
|
|
}
|
|
if dirs == nil {
|
|
dirs = []string{"modules/" + module, meshcatalogclient.RootPath}
|
|
}
|
|
for _, d := range dirs {
|
|
file := "module.json"
|
|
if t := strings.Trim(d, "/"); t != "" && t != meshcatalogclient.RootPath {
|
|
file = t + "/module.json"
|
|
}
|
|
text, err := st.j.Forge.File(ctx, p.Repository, file, p.Head)
|
|
if errors.Is(err, ErrNotFound) {
|
|
continue
|
|
}
|
|
if err != nil {
|
|
return catalogue.Manifest{}, "", false, fmt.Errorf("the manifest of %s at the head of %s cannot be read%s: %w", module, pullKey(p), unheardWords(err), err)
|
|
}
|
|
m, err := catalogue.Decode([]byte(text))
|
|
if err != nil {
|
|
return catalogue.Manifest{}, "", false, fmt.Errorf("the manifest %s of %s at the head of %s is no manifest: %w", file, module, pullKey(p), err)
|
|
}
|
|
if m.Module == module {
|
|
return m, d, true, nil
|
|
}
|
|
}
|
|
return catalogue.Manifest{}, "", false, nil
|
|
}
|
|
|
|
// declaredPackages are the packages the case's members declare, read from each touched module's manifest at the merge
|
|
// preview (the candidate's); with no preview, at the member's head on the forge, so a package new in the group is asked
|
|
// for on the first check too (trunk's manifest when no forge is read): a member that declares none is not asked for.
|
|
func (st *state) declaredPackages(ctx context.Context) ([]declaredPackage, error) {
|
|
if st.j.Read == nil && st.j.Forge == nil {
|
|
return nil, nil
|
|
}
|
|
var trunk map[string]string
|
|
if st.j.Manifests != nil {
|
|
trunk = st.j.Manifests.ManifestDigests()
|
|
}
|
|
var out []declaredPackage
|
|
for _, p := range st.c.Pulls {
|
|
for _, module := range p.Modules {
|
|
var m catalogue.Manifest
|
|
var dir string
|
|
digest := p.Fps[module].Manifest
|
|
switch {
|
|
case digest != "" && st.j.Read != nil:
|
|
var err error
|
|
if m, err = st.j.Read.Manifest(ctx, digest); err != nil {
|
|
return nil, fmt.Errorf("the manifest of %s (%s) cannot be read, so the packages it declares are not known: %w", module, pullKey(p), err)
|
|
}
|
|
case st.j.Forge != nil:
|
|
var found bool
|
|
var err error
|
|
if m, dir, found, err = st.manifestAtHead(ctx, p, module); err != nil {
|
|
return nil, fmt.Errorf("%v, so the packages it declares are not known", err)
|
|
}
|
|
if !found {
|
|
continue
|
|
}
|
|
case trunk[module] != "" && st.j.Read != nil:
|
|
var err error
|
|
if m, err = st.j.Read.Manifest(ctx, trunk[module]); err != nil {
|
|
return nil, fmt.Errorf("the manifest of %s (%s) cannot be read, so the packages it declares are not known: %w", module, pullKey(p), err)
|
|
}
|
|
default:
|
|
continue
|
|
}
|
|
if dir == "" && st.j.Dirs != nil {
|
|
dir, _ = st.j.Dirs.ModuleDir(module)
|
|
}
|
|
if m.Build == nil {
|
|
continue
|
|
}
|
|
for _, a := range m.Build.Artifacts {
|
|
if a.Kind != catalogue.ArtifactPackage {
|
|
continue
|
|
}
|
|
out = append(out, declaredPackage{pull: p, module: module, dir: dir, name: a.Name, paths: a.Paths, language: a.Language})
|
|
}
|
|
}
|
|
}
|
|
return out, nil
|
|
}
|