mesh-build-node: prove with the real npm that a trunk package is published once and a candidate's never (issue 1587, S20, ADR 0498 §5)

A registry of the test's own speaks npm's publish protocol and asks for the credential: a
candidate's build publishes nothing, a trunk build publishes the packed file the build
digested, and a second trunk build of the same package finds it and publishes nothing.
This commit is contained in:
2026-10-22 18:40:05 +02:00
parent 5a79776625
commit 035c950ff2
@@ -0,0 +1,121 @@
//go:build integration
package main
import (
"context"
"encoding/base64"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"os/exec"
"path/filepath"
"strings"
"sync"
"testing"
"git.novox.be/novox/mesh-sdk/go/forgekey"
)
// npmRegistry is a registry of the test's own speaking npm's publish protocol: a PUT of the package's document with the
// packed file attached, then GET of the document and the file; it asks for the account's credential.
type npmRegistry struct {
mu sync.Mutex
versions map[string]map[string]any
files map[string][]byte
publishes int
}
func (r *npmRegistry) serve(t *testing.T) *httptest.Server {
var srv *httptest.Server
srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, q *http.Request) {
r.mu.Lock()
defer r.mu.Unlock()
if u, p, ok := q.BasicAuth(); !ok || u != "builder" || p != "the write credential" {
w.WriteHeader(http.StatusUnauthorized)
return
}
doc := strings.TrimPrefix(q.URL.EscapedPath(), "/npm/")
switch {
case q.Method == http.MethodPut && (doc == "@novox%2fmesh-sdk" || doc == "@novox%2Fmesh-sdk"):
var body struct {
Versions map[string]map[string]any `json:"versions"`
Attachments map[string]struct {
Data string `json:"data"`
} `json:"_attachments"`
}
raw, _ := io.ReadAll(q.Body)
if err := json.Unmarshal(raw, &body); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
for v, meta := range body.Versions {
for name, a := range body.Attachments {
data, _ := base64.StdEncoding.DecodeString(a.Data)
r.files[name] = data
meta["dist"] = map[string]any{"tarball": srv.URL + "/files/" + name, "integrity": integrityOf(data)}
}
r.versions[v] = meta
}
r.publishes++
w.WriteHeader(http.StatusCreated)
w.Write([]byte(`{"ok":true}`))
case q.Method == http.MethodGet && (doc == "@novox%2fmesh-sdk" || doc == "@novox%2Fmesh-sdk"):
if len(r.versions) == 0 {
http.NotFound(w, q)
return
}
json.NewEncoder(w).Encode(map[string]any{"name": "@novox/mesh-sdk", "versions": r.versions})
case strings.HasPrefix(q.URL.Path, "/files/"):
w.Write(r.files[strings.TrimPrefix(q.URL.Path, "/files/")])
default:
http.NotFound(w, q)
}
}))
t.Cleanup(srv.Close)
return srv
}
// 1587-S20 (ADR 0498 §5): the real npm publishes a trunk build's package to a registry speaking npm's protocol, with
// the module's credential, once: a second trunk build of the same package finds its file there and publishes nothing;
// a candidate publishes nothing at all.
func TestARealTrunkPackageIsPublishedOnce(t *testing.T) {
for _, tool := range []string{"node", "npm", "bwrap"} {
if _, err := exec.LookPath(tool); err != nil {
t.Skipf("NOT RUN: no %s where this check runs; every build node has it", tool)
}
}
m, _, work := newMachine(t)
m.Run = forgekey.ExecRunner
reg := &npmRegistry{versions: map[string]map[string]any{}, files: map[string][]byte{}}
srv := reg.serve(t)
m.Toolchain.Registry = func() (Registry, error) {
return Registry{URL: srv.URL + "/npm/", Username: "builder", Password: "the write credential"}, nil
}
m.HTTP = srv.Client()
files := map[string]string{}
for n, c := range sdkFixture {
files[n] = c
}
workspaceWith(t, work, files)
dir := filepath.Join(work, "w1", "tree")
if err := m.installDev(context.Background(), filepath.Join(work, "w1"), dir, "."); err != nil {
t.Fatal(err)
}
args := map[string]any{"workspace": "w1", "module": ".", "artifact": "lib"}
if out, err := m.build(context.Background(), args); err != nil || out.(BuildResult).Reference != "" || reg.publishes != 0 {
t.Fatalf("a candidate: %+v %v, %d publishes", out, err, reg.publishes)
}
args["publish"] = true
out, err := m.build(context.Background(), args)
if err != nil || out.(BuildResult).Reference != "@novox/mesh-sdk@9.9.9" || reg.publishes != 1 {
t.Fatalf("a trunk build: %+v %v, %d publishes", out, err, reg.publishes)
}
if got := digestOf(reg.files["@novox/mesh-sdk-9.9.9.tgz"]); got != out.(BuildResult).Digest {
t.Errorf("the registry holds %s, the build packed %s (files %d)", got, out.(BuildResult).Digest, len(reg.files))
}
if again, err := m.build(context.Background(), args); err != nil || again.(BuildResult).Reference != "@novox/mesh-sdk@9.9.9" || reg.publishes != 1 {
t.Errorf("the same package again: %+v %v, %d publishes", again, err, reg.publishes)
}
}