//go:build integration package builder import ( "context" "os" "path/filepath" "strings" "testing" ) func TestAnImageBuildGetsTheCredentialInTheContextAndHostNetwork(t *testing.T) { r, workspace := aRepository(t, withBoth, map[string]string{"Dockerfile": "FROM scratch\nCOPY .npmrc ./", "files/x": "y"}) n := Npmrc{Scope: "@novox", Registry: "https://forge.invalid/api/packages/novox/npm/", Token: "t"} npmrc := filepath.Join(workspace, "source", ".npmrc") inContext := false run := func(ctx context.Context, dir, name string, args ...string) (string, error) { if name == "docker" && len(args) > 0 && args[0] == "build" { _, err := os.Stat(npmrc) inContext = err == nil } return r.run(ctx, dir, name, args...) } if _, err := Build(context.Background(), run, r, "https://forge.invalid/meshboard.git", "", "", workspace, nil, n, GitCredential{}, nil); err != nil { t.Fatalf("the build failed: %v", err) } var build string for _, line := range r.ran { if strings.HasPrefix(line, "docker build") { build = line } } if build == "" { t.Fatal("no docker build ran") } if strings.Contains(build, "--secret") { t.Fatalf("the build used a buildkit secret, which this path avoids: %s", build) } if !strings.Contains(build, "--network host") { t.Fatalf("the build was not given the host network to reach the registry: %s", build) } // The .npmrc is written into the build context (the source tree), where a Dockerfile COPYs it, and // removed with the tree when the build ends: a later check's container mounts the workspace (novox/hq // issue 462). if !inContext { t.Fatal("the credential was not in the build context when the image was built") } if _, err := os.Stat(npmrc); !os.IsNotExist(err) { t.Fatalf("the credential outlives the build in the workspace: %v", err) } } func TestAnImageBuildWithoutACredentialGetsNoHostNetwork(t *testing.T) { r, workspace := aRepository(t, withBoth, map[string]string{"Dockerfile": "FROM scratch", "files/x": "y"}) if _, err := Build(context.Background(), r.run, r, "https://forge.invalid/meshboard.git", "", "", workspace, nil, Npmrc{}, GitCredential{}, nil); err != nil { t.Fatalf("the build failed: %v", err) } for _, line := range r.ran { if strings.HasPrefix(line, "docker build") && (strings.Contains(line, "--secret") || strings.Contains(line, "--network host")) { t.Fatalf("a build with no credential was still given build-network or a secret: %s", line) } } tree := filepath.Join(workspace, "source") if _, err := os.Stat(filepath.Join(tree, ".npmrc")); err == nil { t.Fatal("an .npmrc was written into a build that has no credential") } } func TestAPackageIsBuiltOnAPublicBaseAndPublishedByVersion(t *testing.T) { r, workspace := aRepository(t, aPackage, map[string]string{ "package.json": `{"name":"@novox/mesh-sdk","version":"0.1.0"}`, }) n := Npmrc{Scope: "@novox", Registry: "https://forge.invalid/api/packages/novox/npm/", Token: "t"} got, err := Build(context.Background(), r.run, r, "https://forge.invalid/mesh-sdk.git", "", "", workspace, nil, n, GitCredential{}, nil) if err != nil { t.Fatalf("the package did not build: %v", err) } if len(got.Built) != 1 || got.Built[0].Reference != "@novox/mesh-sdk@0.1.0" { t.Fatalf("a package is published by name and version, got %+v", got.Built) } if len(r.images) != 0 || len(r.archives) != 0 { t.Fatal("a package was pushed to the artifact store, which is not where packages live") } var ran string for _, line := range r.ran { if strings.HasPrefix(line, "docker run") { ran = line } } if ran == "" { t.Fatal("nothing ran to build the package") } if !strings.Contains(ran, "node:22-bookworm-slim") { t.Fatalf("a package was not built on a public base: %s", ran) } if !strings.Contains(ran, ":/root/.npmrc:ro") { t.Fatalf("the credential was not mounted read-only for the publish: %s", ran) } } func TestAPackageWithNoRegistryIsRefused(t *testing.T) { r, workspace := aRepository(t, aPackage, map[string]string{ "package.json": `{"name":"@novox/mesh-sdk","version":"0.1.0"}`, }) _, err := Build(context.Background(), r.run, r, "https://forge.invalid/mesh-sdk.git", "", "", workspace, nil, Npmrc{}, GitCredential{}, nil) if err == nil { t.Fatal("a package built with no registry to publish to, silently") } } func TestAnImageThatDoesNotAskForTheCredentialDoesNotGetIt(t *testing.T) { // A Dockerfile with no .npmrc reference (like the control plane's) must build clean: no .npmrc // in its context, no host network — so its image stays deterministic and the credential does not // leak into a build that never resolves a mesh package. r, workspace := aRepository(t, withBoth, map[string]string{"Dockerfile": "FROM scratch\nCOPY . .", "files/x": "y"}) n := Npmrc{Scope: "@novox", Registry: "https://forge.invalid/api/packages/novox/npm/", Token: "t"} if _, err := Build(context.Background(), r.run, r, "https://forge.invalid/meshboard.git", "", "", workspace, nil, n, GitCredential{}, nil); err != nil { t.Fatalf("the build failed: %v", err) } for _, line := range r.ran { if strings.HasPrefix(line, "docker build") && strings.Contains(line, "--network host") { t.Fatalf("a build that does not ask for the credential got the host network: %s", line) } } if _, err := os.Stat(filepath.Join(workspace, "source", ".npmrc")); err == nil { t.Fatal("an .npmrc was written into a build that does not reference it") } }