From 3422e1a6f8fdc8a011ecb002eb2ebdcde8369982 Mon Sep 17 00:00:00 2001 From: jochen Date: Sat, 7 Nov 2026 15:51:38 +0100 Subject: [PATCH] A module the tree no longer holds does not stop the others' packages being published (issue 1585) publish asked the forge for every published module of the repository in one call; when the merge removed one (seatfiles), the whole call failed and a revision's own new Go modules stayed unpublished, so the take-in waited for a version only its own take-in would publish. packagesAt now reads the modules one by one when the tree lacks a directory and leaves the missing one out, said. --- .../internal/index/packages.go | 27 ++++++++++- .../internal/index/pending_test.go | 48 +++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/modules/mesh-delivery-indexer/internal/index/packages.go b/modules/mesh-delivery-indexer/internal/index/packages.go index 6acae49c..956a6fa6 100644 --- a/modules/mesh-delivery-indexer/internal/index/packages.go +++ b/modules/mesh-delivery-indexer/internal/index/packages.go @@ -149,12 +149,35 @@ func (ix *Indexer) packagesAt(ctx context.Context, repository, commit string, mo } } } - if err := list(slices.Sorted(maps.Values(dirOf))); err != nil { - return nil, err + // The modules are read in one call; when the tree at the commit lacks a directory of them (a module published at an earlier + // merge that this one removed or moved), each is read alone and the missing one is left out, said, so it never keeps the + // others from being published (issue 1585): a revision's own new module is published at the revision's own merge. + absent := map[string]bool{} + dirs := slices.Sorted(maps.Values(dirOf)) + if err := list(dirs); err != nil { + if !errors.Is(err, ErrNotInTree) || len(dirs) < 2 { + return nil, err + } + whole := err + for _, d := range dirs { + if err := list([]string{d}); err != nil { + if !errors.Is(err, ErrNotInTree) { + return nil, err + } + ix.logf("%s at %s: the directory %q is not in the tree, so the module there is not read: %v", repository, commit, d, err) + absent[d] = true + } + } + if len(absent) == len(dirs) { + return nil, whole // the tree itself fails: the caller asks once per head (candidatePublished) + } } out := map[string]meshcatalog.PackagesByModuleValue{} for _, m := range slices.Sorted(maps.Keys(dirOf)) { dir := dirOf[m] + if absent[dir] { + continue + } requires, pkgs, err := fingerprint.Packages(m, listings[dir]) if err != nil { ix.logf("%s at %s: %v; it is not published", repository, commit, err) diff --git a/modules/mesh-delivery-indexer/internal/index/pending_test.go b/modules/mesh-delivery-indexer/internal/index/pending_test.go index c13e5146..b971a30c 100644 --- a/modules/mesh-delivery-indexer/internal/index/pending_test.go +++ b/modules/mesh-delivery-indexer/internal/index/pending_test.go @@ -4,12 +4,15 @@ import ( "context" "encoding/json" "errors" + "fmt" "reflect" "slices" "strings" "testing" + "time" "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient" + "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog" "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-forge-bridge/forgemsg" "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-indexer/takein" "git.novox.be/novox/mesh-delivery/sdk/trunk" @@ -207,6 +210,51 @@ func TestTakeIn(t *testing.T) { // 1585/T3-T13 (ADR 0633) t.Errorf("said %v, want %v", b.events(), want) } }) + t.Run("P1 a revision that adds a Go module its own indexer uses is computed against that module's packages at its merge", func(t *testing.T) { + // The Go module exists only at the revision's own merge: nothing publishes it before the take-in, so the fingerprint + // the revision names must come from the packages its merge holds (issue 1585, ADR 0593 §2), not wait for a version only + // its own take-in publishes. + const sibling = "git.novox.be/novox/mesh-catalog/modules/mesh-new/pkg" + b := newTakeInBed(t) + f := b.merge(21, sha('c'), "tree-avahi-3", "tree-indexer-2") + if b.ix.Packages == nil { + b.ix.Packages = newMem() + } + b.ix.GoMod = func(_ context.Context, _, commit, dir string) ([]byte, error) { + if commit == f.Merge && dir == "modules/"+Module { + return []byte("module x\n\nreplace " + sibling + " => ../mesh-new/pkg\n"), nil + } + return []byte("module x\n"), nil + } + b.ix.Files = func(_ context.Context, repository, commit string, dirs []string) (map[string]map[string]string, error) { + out := map[string]map[string]string{} + for _, d := range dirs { + if repository != catalogueRepo || commit != f.Merge || d != "modules/mesh-new/pkg" { + return nil, fmt.Errorf("no directory %s: %w", d, ErrNotInTree) + } + out[d] = map[string]string{"go.mod": "m1", "go.sum": "s1", "x.go": "g1"} + } + return out, nil + } + // A Go module the repository published before and its merge no longer holds does not stop the others being published. + const gone = "git.novox.be/novox/mesh-catalog/modules/mesh-gone/pkg" + old, err := EncodePublishedPackages(meshcatalog.PackagesByModuleValue{Module: gone, Repository: catalogueRepo, Dir: "modules/mesh-gone/pkg", + Commit: sha('a'), Requires: "r", At: ptr(time.Now()), Packages: []meshcatalog.PackagesByModuleValuePackagesItem{{Package: gone, Digest: "d"}}}) + if err != nil { + t.Fatal(err) + } + goneKey, _ := PackagesKey(gone) + if err := b.ix.Packages.Create(ctx, goneKey, old); err != nil { + t.Fatal(err) + } + b.arrive(t, 2, f) + if len(b.said) != 1 || !strings.HasPrefix(b.said[0].WaitsFor, "src2:") { + t.Errorf("said %+v, want m.2 waiting for the indexer build its merge's packages give, not for a version no take-in has published", b.said) + } + if _, ok := b.ix.publishedAll(ctx)[sibling]; !ok { + t.Errorf("the packages the revision publishes at its merge lack %s", sibling) + } + }) t.Run("K1 the indexer a revision names is judged with the seat definitions the revision carries", func(t *testing.T) { // A successor's manifest invokes a verb of the node-engine's seat that the seat list lacks and the revision's // definitions add (ADR 0633 §1, §6): refused without them, with its reason said on the wait and in indexer_pending; -- 2.54.0