128 lines
5.3 KiB
Go
128 lines
5.3 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
builds "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
|
)
|
|
|
|
const packageManifest = `{"module":"mesh-sdk","version":"1","build":{"artifacts":[{"name":"lib","kind":"package","language":"typescript","paths":["src","package.json"]}]}}`
|
|
|
|
// packageMachine is a machine whose workspace w1 holds the package @novox/mesh-sdk@0.1.15 at its root; npm pack writes
|
|
// the packed file tgz into its --pack-destination, as npm does.
|
|
func packageMachine(t *testing.T, tgz []byte) (*Module, *fakeMachine, string) {
|
|
t.Helper()
|
|
m, f, work := newMachine(t)
|
|
workspaceWith(t, work, map[string]string{"module.json": packageManifest, "src/index.ts": "export const v = 1;\n",
|
|
"package.json": `{"name":"@novox/mesh-sdk","version":"0.1.15","scripts":{"build":"tsc"}}`, "package-lock.json": `{"lockfileVersion":3}`})
|
|
f.effect = func(c call) {
|
|
if c.name != "npm" || len(c.args) == 0 || c.args[0] != "pack" {
|
|
return
|
|
}
|
|
for i, a := range c.args {
|
|
if a == "--pack-destination" {
|
|
write(t, filepath.Join(c.args[i+1], "novox-mesh-sdk-0.1.15.tgz"), string(tgz), 0o644)
|
|
}
|
|
}
|
|
}
|
|
return m, f, work
|
|
}
|
|
|
|
func publishes(f *fakeMachine) []call {
|
|
var out []call
|
|
for _, c := range f.calls {
|
|
if c.name == "npm" && len(c.args) > 0 && c.args[0] == "publish" {
|
|
out = append(out, c)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
// 1587-S15..S19 (ADR 0498 §5): a package is built by its own build script and packed, shut off; a candidate answers the
|
|
// packed file's digest, publishes nothing and asks the registry nothing; its reference is empty.
|
|
func TestACandidatesPackageIsBuiltAndPackedAndNeverPublished(t *testing.T) {
|
|
tgz := tgzOf(t, sdkPackage, "0.1.15")
|
|
m, f, _ := packageMachine(t, tgz)
|
|
asked := fakeRegistry(t, m, nil)
|
|
out, err := m.build(context.Background(), map[string]any{"workspace": "w1", "module": ".", "artifact": "lib"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r := out.(BuildResult)
|
|
if r.Digest != digestOf(tgz) || r.Reference != "" || r.Bytes != len(tgz) {
|
|
t.Errorf("result %+v, want the packed file's digest and no reference", r)
|
|
}
|
|
if len(publishes(f)) != 0 || asked.Load() != 0 {
|
|
t.Errorf("a candidate published %d times and asked the registry %d times", len(publishes(f)), asked.Load())
|
|
}
|
|
var ran []string
|
|
for _, s := range f.shut {
|
|
ran = append(ran, s.command)
|
|
}
|
|
if len(f.shut) != 2 || !strings.Contains(ran[0], "npm run build") || !strings.Contains(ran[1], "npm pack --ignore-scripts") {
|
|
t.Errorf("shut off %v, want the build and the pack", ran)
|
|
}
|
|
}
|
|
|
|
// ADR 0498 §5, CAT-BN3 (design 51 *Publishing*): a trunk build the builder gave a version packs the package under that
|
|
// version and publishes it through npm-package-registry, never by npm publish nor with a credential, and answers
|
|
// <name>@<version>; its package.json is put back. A trunk build not numbered publishes nothing; a refusal fails it
|
|
// not stored. The packed file is gone from the node afterwards.
|
|
func TestATrunkPackageIsPublishedOnceAndAVersionTakenIsRefused(t *testing.T) {
|
|
tgz := tgzOf(t, sdkPackage, "0.1.16")
|
|
args := map[string]any{"workspace": "w1", "module": ".", "artifact": "lib", "publish": true, "version": "0.1.16", "seat": "npm-package-registry"}
|
|
m, f, work := packageMachine(t, tgz)
|
|
var packedAs string
|
|
inner := f.effect
|
|
f.effect = func(c call) {
|
|
if c.name == "npm" && len(c.args) > 0 && c.args[0] == "pack" {
|
|
raw, _ := os.ReadFile(filepath.Join(work, "w1", "tree", "package.json"))
|
|
packedAs = string(raw)
|
|
}
|
|
inner(c)
|
|
}
|
|
store := withStore(t, m)
|
|
out, err := m.build(context.Background(), args)
|
|
if err != nil || out.(BuildResult).Reference != "@novox/mesh-sdk@0.1.16" || len(publishes(f)) != 0 {
|
|
t.Fatalf("a numbered trunk package: %+v %v, %d npm publishes", out, err, len(publishes(f)))
|
|
}
|
|
if !strings.Contains(packedAs, `"version": "0.1.16"`) {
|
|
t.Errorf("packed with package.json %s, want the builder's version", packedAs)
|
|
}
|
|
if raw, _ := os.ReadFile(filepath.Join(work, "w1", "tree", "package.json")); !strings.Contains(string(raw), `"version":"0.1.15"`) {
|
|
t.Errorf("package.json was not put back: %s", raw)
|
|
}
|
|
if len(store.published) != 1 || store.published[0].Name != "@novox/mesh-sdk" || store.published[0].Version != "0.1.16" ||
|
|
store.published[0].Kind != "package" || store.seats[0] != "npm-package-registry" || store.published[0].Digest != digestOf(tgz) {
|
|
t.Errorf("published %+v through %v", store.published, store.seats)
|
|
}
|
|
var left []string
|
|
filepath.WalkDir(work, func(p string, d os.DirEntry, err error) error {
|
|
if err == nil && strings.HasSuffix(p, ".tgz") || strings.Contains(p, ".npmrc") {
|
|
left = append(left, p)
|
|
}
|
|
return nil
|
|
})
|
|
if len(left) != 0 {
|
|
t.Errorf("left on the node: %v", left)
|
|
}
|
|
|
|
m, f, _ = packageMachine(t, tgz)
|
|
store = withStore(t, m)
|
|
unnumbered := map[string]any{"workspace": "w1", "module": ".", "artifact": "lib", "publish": true}
|
|
if out, err := m.build(context.Background(), unnumbered); err != nil || out.(BuildResult).Reference != "" || len(store.published) != 0 || len(publishes(f)) != 0 {
|
|
t.Errorf("a trunk package not numbered: %+v %v, %d published", out, err, len(store.published))
|
|
}
|
|
|
|
m, _, _ = packageMachine(t, tgz)
|
|
withStore(t, m).fail = errors.New("refused: the builder did not number it")
|
|
if _, err = m.build(context.Background(), args); err == nil || !strings.HasPrefix(err.Error(), builds.NotStored+"lib: ") {
|
|
t.Errorf("a refused publish: %v", err)
|
|
}
|
|
}
|