Build modules publish through the registry clients over the parts sender

mesh-sdk's publish package left mesh-sdk (ADR 0627): buildstep binds each
registry seat to its client in mesh-contracts, over mesh-sdk's
seat-neutral sender of parts. The late publish uses the same path.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 16:27:07 +01:00
parent eb50bf1f48
commit 348f9631fe
6 changed files with 74 additions and 19 deletions
+2
View File
@@ -8,6 +8,8 @@ require (
)
require (
git.novox.be/novox/mesh-contracts/go/seats/containerimageregistry v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/seats/ociartifactregistry v0.0.0-00010101000000-000000000000
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op // indirect
github.com/google/go-tpm v0.9.8 // indirect
github.com/klauspost/compress v1.20.0 // indirect
+46 -16
View File
@@ -3,8 +3,8 @@ package buildstep
// The publish of a done build's file through a registry seat (novox/hq design 51 *Publishing*, ADR 0611; CAT-BG1,
// CAT-BN3): from the build module's own process, after the build step ended, through the seat's verbs publish and
// publish-part, which each build module's manifest `invokes`, in chunks, only what the holder lacks. The holder checks
// the build with the builder and says published or refused on the seat's events. One place for every build module, so
// the move to the registry clients is made here once.
// the build with the builder and says published or refused on the seat's events. One place for every build module: it
// binds each seat to its client in mesh-contracts (ADR 0627 §1), over mesh-sdk's seat-neutral sender of parts (§2).
import (
"bytes"
@@ -15,16 +15,23 @@ import (
"os"
"strings"
imageclient "git.novox.be/novox/mesh-contracts/go/clients/containerimageregistryclient"
goclient "git.novox.be/novox/mesh-contracts/go/clients/gopackageregistryclient"
npmclient "git.novox.be/novox/mesh-contracts/go/clients/npmpackageregistryclient"
ociclient "git.novox.be/novox/mesh-contracts/go/clients/ociartifactregistryclient"
reg "git.novox.be/novox/mesh-contracts/go/seats/containerimageregistry"
"git.novox.be/novox/mesh-sdk/go/publish"
goseat "git.novox.be/novox/mesh-contracts/go/seats/gopackageregistry"
npmseat "git.novox.be/novox/mesh-contracts/go/seats/npmpackageregistry"
ociseat "git.novox.be/novox/mesh-contracts/go/seats/ociartifactregistry"
"git.novox.be/novox/mesh-sdk/go/parts"
)
// The registry seats a build module publishes on.
const (
ArtifactSeat = "oci-artifact-registry"
ArtifactSeat = ociseat.Seat
ImageSeat = reg.Seat
GoSeat = "go-package-registry"
NpmSeat = "npm-package-registry"
GoSeat = goseat.Seat
NpmSeat = npmseat.Seat
)
// SeatCall asks one verb of a seat, `seat:<seat>.<verb>`, with a body, and answers its JSON (the bundle's stdio.Ask).
@@ -43,8 +50,8 @@ func TransferName(name, qualifier, digest string) string {
// PublishOne publishes body, of digest, as name (at version, when it has one) of kind on seat, in one part.
func PublishOne(ctx context.Context, call SeatCall, seat, name, kind, version, digest, transfer string, body []byte) error {
in := reg.PublishInput{Name: name, Kind: kind, Version: version, Digest: digest, Transfer: transfer}
_, err := OnSeat(ctx, seat, publishWhat(in), func() (publish.Sent, error) {
return publish.Publish(ctx, publish.Call(call), seat, in, []publish.Part{{Digest: digest, Size: int64(len(body)),
_, err := OnSeat(ctx, seat, publishWhat(in), func() (parts.Sent, error) {
return PublishParts(ctx, call, seat, in, []parts.Part{{Digest: digest, Size: int64(len(body)),
Open: func() (io.ReadCloser, error) { return io.NopCloser(bytes.NewReader(body)), nil }}})
}, SentHow(1))
return err
@@ -60,12 +67,35 @@ func publishWhat(in reg.PublishInput) string {
}
// SentHow says what of a publish of parts travelled, for its stored line.
func SentHow(parts int) func(publish.Sent) string {
return func(s publish.Sent) string {
return fmt.Sprintf("%d of its %d parts sent, the rest held", len(s.Parts), parts)
func SentHow(n int) func(parts.Sent) string {
return func(s parts.Sent) string {
return fmt.Sprintf("%d of its %d parts sent, the rest held", len(s.Parts), n)
}
}
// PublishParts publishes in with ps as its parts on seat, through that seat's client: in's fields are the seat's own
// (the four registry seats share the publish verb's input, design 51), the parts are written by the client.
func PublishParts(ctx context.Context, call SeatCall, seat string, in reg.PublishInput, ps []parts.Part) (parts.Sent, error) {
switch seat {
case ImageSeat:
s, err := imageclient.Publish(ctx, imageclient.Call(call), in, ps)
return s.Sent, err
case ArtifactSeat:
s, err := ociclient.Publish(ctx, ociclient.Call(call), ociseat.PublishInput{Name: in.Name, Kind: in.Kind, Version: in.Version,
Tag: in.Tag, Digest: in.Digest, Fingerprint: in.Fingerprint, Commit: in.Commit, Transfer: in.Transfer}, ps)
return s.Sent, err
case GoSeat:
s, err := goclient.Publish(ctx, goclient.Call(call), goseat.PublishInput{Name: in.Name, Kind: in.Kind, Version: in.Version,
Tag: in.Tag, Digest: in.Digest, Fingerprint: in.Fingerprint, Commit: in.Commit, Transfer: in.Transfer}, ps)
return s.Sent, err
case NpmSeat:
s, err := npmclient.Publish(ctx, npmclient.Call(call), npmseat.PublishInput{Name: in.Name, Kind: in.Kind, Version: in.Version,
Tag: in.Tag, Digest: in.Digest, Fingerprint: in.Fingerprint, Commit: in.Commit, Transfer: in.Transfer}, ps)
return s.Sent, err
}
return parts.Sent{}, fmt.Errorf("%s is no registry seat a build publishes on", seat)
}
// File is one part of a publish kept on disk: an image's config, layer or manifest, by its digest and size.
type File struct {
Digest string
@@ -75,12 +105,12 @@ type File struct {
// PublishFiles publishes in with files as its parts (an image's config, layers and manifest, CAT-BI1): the holder
// answers the parts it lacks, and only those are read and sent.
func PublishFiles(ctx context.Context, call SeatCall, seat string, in reg.PublishInput, files []File) (publish.Sent, error) {
ps := make([]publish.Part, 0, len(files))
func PublishFiles(ctx context.Context, call SeatCall, seat string, in reg.PublishInput, files []File) (parts.Sent, error) {
ps := make([]parts.Part, 0, len(files))
for _, f := range files {
ps = append(ps, publish.Part{Digest: f.Digest, Size: f.Size, Open: func() (io.ReadCloser, error) { return os.Open(f.Path) }})
ps = append(ps, parts.Part{Digest: f.Digest, Size: f.Size, Open: func() (io.ReadCloser, error) { return os.Open(f.Path) }})
}
return OnSeat(ctx, seat, publishWhat(in), func() (publish.Sent, error) {
return publish.Publish(ctx, publish.Call(call), seat, in, ps)
return OnSeat(ctx, seat, publishWhat(in), func() (parts.Sent, error) {
return PublishParts(ctx, call, seat, in, ps)
}, SentHow(len(files)))
}
@@ -19,7 +19,7 @@ import (
registry "git.novox.be/novox/mesh-contracts/go/seats/containerimageregistry"
stdio "git.novox.be/novox/mesh-sdk/go"
"git.novox.be/novox/mesh-sdk/go/delivery"
"git.novox.be/novox/mesh-sdk/go/publish"
"git.novox.be/novox/mesh-sdk/go/parts"
)
// NumberedPattern is the event type this module consumes for the late publish, as its manifest's `consumes` names it.
@@ -49,8 +49,8 @@ func (m *Module) LatePublish(ctx context.Context, body []byte) (bool, error) {
}
in := registry.PublishInput{Name: n.Name, Kind: n.Kind, Version: n.Version, Tag: n.Tag, Digest: n.Digest,
Fingerprint: n.Fingerprint, Commit: n.Commit, Transfer: transferName(n.Name, "v"+n.Version, n.Digest)}
sent, err := buildstep.OnSeat(ctx, seat, "late publish of "+n.Name+" "+n.Version+" at "+n.Digest, func() (publish.Sent, error) {
return publish.Publish(ctx, publish.Call(call), seat, in, []publish.Part{{Digest: n.Digest,
sent, err := buildstep.OnSeat(ctx, seat, "late publish of "+n.Name+" "+n.Version+" at "+n.Digest, func() (parts.Sent, error) {
return buildstep.PublishParts(ctx, call, seat, in, []parts.Part{{Digest: n.Digest,
Open: func() (io.ReadCloser, error) { return nil, errNotHere }}})
}, nil)
if err != nil {
+7
View File
@@ -13,7 +13,14 @@ require (
)
require (
git.novox.be/novox/mesh-contracts/go/clients/containerimageregistryclient v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/clients/gopackageregistryclient v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/clients/npmpackageregistryclient v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/clients/ociartifactregistryclient v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/seats/containerimageregistry v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/seats/gopackageregistry v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/seats/npmpackageregistry v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/seats/ociartifactregistry v0.0.0-00010101000000-000000000000
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
+8
View File
@@ -10,6 +10,14 @@ require (
)
require (
git.novox.be/novox/mesh-contracts/go/clients/containerimageregistryclient v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/clients/gopackageregistryclient v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/clients/npmpackageregistryclient v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/clients/ociartifactregistryclient v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/seats/containerimageregistry v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/seats/gopackageregistry v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/seats/npmpackageregistry v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/seats/ociartifactregistry v0.0.0-00010101000000-000000000000
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op // indirect
github.com/google/go-tpm v0.9.8 // indirect
github.com/klauspost/compress v1.20.0 // indirect
+8
View File
@@ -10,6 +10,14 @@ require (
)
require (
git.novox.be/novox/mesh-contracts/go/clients/containerimageregistryclient v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/clients/gopackageregistryclient v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/clients/npmpackageregistryclient v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/clients/ociartifactregistryclient v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/seats/containerimageregistry v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/seats/gopackageregistry v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/seats/npmpackageregistry v0.0.0-00010101000000-000000000000
git.novox.be/novox/mesh-contracts/go/seats/ociartifactregistry v0.0.0-00010101000000-000000000000
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect