Every served bundle is its own process now, so each carries its own copy of what it imports: after the compile and the launchers, the toolchain image's esbuild bundles every entrypoint in place and every launcher under its own name into one ES module file, the SDK inlined, require provided to inlined CommonJS, the launcher's shebang kept and its mode 0755. The toolchain's node_modules is copied only for packages an artifact names external. An image without the bundler is refused by name. Issue 212: build.on already passes a published package by its exact version and plans the toolchain after it; tests say so.
123 lines
4.8 KiB
Go
123 lines
4.8 KiB
Go
package inventory
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
)
|
|
|
|
// The catalogue's one dependency relation (novox/hq ADR 0162): four kinds of edge from one call.
|
|
func TestDependenciesAreOneRelationWithTheirKinds(t *testing.T) {
|
|
entry := func(name, repository string) Entry {
|
|
return Entry{Manifest: catalogue.Manifest{Module: name}, Source: Source{Repository: repository}}
|
|
}
|
|
builder := entry("builder", "http://forge/novox/mesh-catalog.git")
|
|
builder.Manifest.Claims = []catalogue.Claim{{Name: "node-build-agent", Scope: catalogue.ScopeNode}}
|
|
plugin := entry("shop-plugin", "http://forge/novox/mesh-catalog.git")
|
|
plugin.Manifest.Build = &catalogue.Build{On: []catalogue.BuildsOn{{Arg: "BASE", Module: "shop"}}}
|
|
entries := []Entry{
|
|
entry("mesh-tools", "http://forge/novox/mesh-tools.git"),
|
|
entry("shop", "http://forge/novox/mesh-catalog.git"),
|
|
plugin,
|
|
builder,
|
|
entry("mesh-controller", "http://forge/novox/mesh-controller.git"),
|
|
entry("route-proxy", "http://forge/novox/mesh-catalog.git"),
|
|
{Manifest: catalogue.Manifest{Module: "hand-made"}},
|
|
}
|
|
against := map[string][]string{
|
|
"shop": {catalogue.ArtifactStoreScheme + "mesh-tools/runtime@sha256:a"},
|
|
"builder": {catalogue.ArtifactStoreScheme + "mesh-tools/runtime@sha256:a"},
|
|
}
|
|
read := map[string][]ReadRepository{
|
|
"route-proxy": {{Repository: "http://forge/novox/mesh-controller.git", Ref: "main"}},
|
|
}
|
|
got := dependenciesOf(entries, against, read)
|
|
has := func(from, to, kind string) bool {
|
|
for _, e := range got {
|
|
if e == (Edge{From: from, To: to, Kind: kind}) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
for _, want := range []Edge{
|
|
{"shop", "mesh-tools", EdgeStandsOn},
|
|
{"builder", "mesh-tools", EdgeStandsOn},
|
|
{"shop-plugin", "shop", EdgeDeclared},
|
|
{"route-proxy", "mesh-controller", EdgePackages},
|
|
{"shop", "builder", EdgeBuiltBy},
|
|
{"mesh-controller", "builder", EdgeBuiltBy},
|
|
{"mesh-tools", "builder", EdgeBuiltBy},
|
|
} {
|
|
if !has(want.From, want.To, want.Kind) {
|
|
t.Errorf("missing %+v in %+v", want, got)
|
|
}
|
|
}
|
|
if has("builder", "builder", EdgeBuiltBy) {
|
|
t.Error("the builder is not built by itself")
|
|
}
|
|
for _, e := range got {
|
|
if e.From == "hand-made" {
|
|
t.Errorf("a module with no source depends on nothing: %+v", e)
|
|
}
|
|
}
|
|
}
|
|
|
|
// novox/hq 04-ISSUES/211: a bundle stands on the toolchain it is compiled in, so a merge moving both
|
|
// builds the toolchain first — read from the manifest, before any build recorded it.
|
|
func TestABundleStandsOnTheToolchainItIsCompiledIn(t *testing.T) {
|
|
entries := []Entry{
|
|
{Manifest: catalogue.Manifest{Module: "mesh-tools"}, Source: Source{Repository: "novox/mesh-tools"}},
|
|
{Manifest: catalogue.Manifest{Module: "mesh-tools-go"}, Source: Source{Repository: "novox/mesh-tools-go"}},
|
|
{Manifest: catalogue.Manifest{Module: "node-tools", Build: &catalogue.Build{Artifacts: []catalogue.Artifact{
|
|
{Name: "runtime", Kind: catalogue.ArtifactBundle, Language: "go", System: "arch", From: "cmd/node-tools"}}}},
|
|
Source: Source{Repository: "novox/mesh-tools"}},
|
|
{Manifest: catalogue.Manifest{Module: "nftables", Build: &catalogue.Build{Artifacts: []catalogue.Artifact{
|
|
{Name: "tools", Kind: catalogue.ArtifactBundle, Language: "typescript", Entrypoints: []string{"tools/index.js"}}}}},
|
|
Source: Source{Repository: "novox/mesh-catalog"}},
|
|
{Manifest: catalogue.Manifest{Module: "photos", Build: &catalogue.Build{Artifacts: []catalogue.Artifact{
|
|
{Name: "server", Kind: catalogue.ArtifactImage, From: "Dockerfile"}}}},
|
|
Source: Source{Repository: "novox/photos"}},
|
|
}
|
|
edges := dependenciesOf(entries, nil, nil)
|
|
has := func(from, to string) bool {
|
|
for _, e := range edges {
|
|
if e.From == from && e.To == to && e.Kind == EdgeStandsOn {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
if !has("nftables", "mesh-tools") {
|
|
t.Errorf("a TypeScript bundle does not stand on the TypeScript toolchain: %v", edges)
|
|
}
|
|
if !has("node-tools", "mesh-tools-go") {
|
|
t.Errorf("a Go bundle does not stand on the Go toolchain: %v", edges)
|
|
}
|
|
for _, e := range edges {
|
|
if e.From == "photos" && e.Kind == EdgeStandsOn {
|
|
t.Errorf("an image stands on a toolchain it is not compiled in: %v", e)
|
|
}
|
|
}
|
|
}
|
|
|
|
// novox/hq 04-ISSUES/212: a toolchain standing on the SDK's package is planned after the SDK, so a
|
|
// release of the SDK rebuilds the toolchain, and every bundle compiled in it after that.
|
|
func TestAToolchainStandingOnTheSDKFollowsIt(t *testing.T) {
|
|
entries := []Entry{
|
|
{Manifest: catalogue.Manifest{Module: "mesh-sdk"}},
|
|
{Manifest: catalogue.Manifest{Module: "mesh-tools", Build: &catalogue.Build{
|
|
On: []catalogue.BuildsOn{{Arg: "MESH_SDK", Module: "mesh-sdk", Artifact: "lib"}}}}},
|
|
}
|
|
edges := dependenciesOf(entries, nil, nil)
|
|
found := false
|
|
for _, e := range edges {
|
|
if e.From == "mesh-tools" && e.To == "mesh-sdk" {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
t.Errorf("no edge from the toolchain to the SDK: %v", edges)
|
|
}
|
|
}
|