[bug-0zkpwxbsdxcn] Own canonical offline private Go module tooling #2
@@ -79,7 +79,7 @@ func generate() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(temp)
|
defer func() { _ = os.RemoveAll(temp) }()
|
||||||
if err := os.WriteFile(filepath.Join(temp, "go.mod"), []byte(archiveBoundary), 0444); err != nil {
|
if err := os.WriteFile(filepath.Join(temp, "go.mod"), []byte(archiveBoundary), 0444); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,31 +13,31 @@ import (
|
|||||||
|
|
||||||
func TestBundleRejectsStaleMissingModifiedAndUnexpectedArtifacts(t *testing.T) {
|
func TestBundleRejectsStaleMissingModifiedAndUnexpectedArtifacts(t *testing.T) {
|
||||||
t.Chdir(t.TempDir())
|
t.Chdir(t.TempDir())
|
||||||
os.WriteFile("go.mod", []byte("module example.invalid/test\n"), 0600)
|
mustFixture(t, os.WriteFile("go.mod", []byte("module example.invalid/test\n"), 0600))
|
||||||
os.WriteFile("go.sum", []byte("recorded sum\n"), 0600)
|
mustFixture(t, os.WriteFile("go.sum", []byte("recorded sum\n"), 0600))
|
||||||
mod, _ := inputDigest("go.mod")
|
mod, _ := inputDigest("go.mod")
|
||||||
sum, _ := inputDigest("go.sum")
|
sum, _ := inputDigest("go.sum")
|
||||||
m := manifest{Version: 1, GoModSHA256: mod, GoSumSHA256: sum, Modules: []module{{Path: "code.fritzlab.net/agenthub/example", Version: "v0.1.0"}}}
|
m := manifest{Version: 1, GoModSHA256: mod, GoSumSHA256: sum, Modules: []module{{Path: "code.fritzlab.net/agenthub/example", Version: "v0.1.0"}}}
|
||||||
for _, ext := range []string{".info", ".mod", ".zip"} {
|
for _, ext := range []string{".info", ".mod", ".zip"} {
|
||||||
name := "code.fritzlab.net/agenthub/example/@v/v0.1.0" + ext
|
name := "code.fritzlab.net/agenthub/example/@v/v0.1.0" + ext
|
||||||
b := []byte("canonical artifact " + ext)
|
b := []byte("canonical artifact " + ext)
|
||||||
os.MkdirAll(filepath.Dir(filepath.Join(bundleRoot, name)), 0700)
|
mustFixture(t, os.MkdirAll(filepath.Dir(filepath.Join(bundleRoot, name)), 0700))
|
||||||
os.WriteFile(filepath.Join(bundleRoot, name), b, 0600)
|
mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, name), b, 0600))
|
||||||
m.Modules[0].Files = append(m.Modules[0].Files, artifact{Path: name, Size: int64(len(b)), SHA256: digest(b)})
|
m.Modules[0].Files = append(m.Modules[0].Files, artifact{Path: name, Size: int64(len(b)), SHA256: digest(b)})
|
||||||
}
|
}
|
||||||
b, _ := json.Marshal(m)
|
b, _ := json.Marshal(m)
|
||||||
os.WriteFile(filepath.Join(bundleRoot, "manifest.json"), b, 0600)
|
mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, "manifest.json"), b, 0600))
|
||||||
os.WriteFile(filepath.Join(bundleRoot, "go.mod"), []byte(archiveBoundary), 0600)
|
mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, "go.mod"), []byte(archiveBoundary), 0600))
|
||||||
if err := check(); err != nil {
|
if err := check(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
for _, boundary := range []string{"", "module unexpected.invalid/nested\n"} {
|
for _, boundary := range []string{"", "module unexpected.invalid/nested\n"} {
|
||||||
os.WriteFile(filepath.Join(bundleRoot, "go.mod"), []byte(boundary), 0600)
|
mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, "go.mod"), []byte(boundary), 0600))
|
||||||
if check() == nil {
|
if check() == nil {
|
||||||
t.Fatal("missing or changed archive boundary accepted")
|
t.Fatal("missing or changed archive boundary accepted")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
os.WriteFile(filepath.Join(bundleRoot, "go.mod"), []byte(archiveBoundary), 0600)
|
mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, "go.mod"), []byte(archiveBoundary), 0600))
|
||||||
originalPath, originalVersion := m.Modules[0].Path, m.Modules[0].Version
|
originalPath, originalVersion := m.Modules[0].Path, m.Modules[0].Version
|
||||||
for _, change := range []string{"path", "version"} {
|
for _, change := range []string{"path", "version"} {
|
||||||
if change == "path" {
|
if change == "path" {
|
||||||
@@ -46,36 +46,36 @@ func TestBundleRejectsStaleMissingModifiedAndUnexpectedArtifacts(t *testing.T) {
|
|||||||
m.Modules[0].Version = "v0.2.0"
|
m.Modules[0].Version = "v0.2.0"
|
||||||
}
|
}
|
||||||
changed, _ := json.Marshal(m)
|
changed, _ := json.Marshal(m)
|
||||||
os.WriteFile(filepath.Join(bundleRoot, "manifest.json"), changed, 0600)
|
mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, "manifest.json"), changed, 0600))
|
||||||
if check() == nil {
|
if check() == nil {
|
||||||
t.Fatal("artifact accepted under different module identity")
|
t.Fatal("artifact accepted under different module identity")
|
||||||
}
|
}
|
||||||
m.Modules[0].Path, m.Modules[0].Version = originalPath, originalVersion
|
m.Modules[0].Path, m.Modules[0].Version = originalPath, originalVersion
|
||||||
}
|
}
|
||||||
os.WriteFile(filepath.Join(bundleRoot, "manifest.json"), b, 0600)
|
mustFixture(t, os.WriteFile(filepath.Join(bundleRoot, "manifest.json"), b, 0600))
|
||||||
os.WriteFile("go.mod", []byte("changed graph\n"), 0600)
|
mustFixture(t, os.WriteFile("go.mod", []byte("changed graph\n"), 0600))
|
||||||
if check() == nil {
|
if check() == nil {
|
||||||
t.Fatal("stale dependency closure accepted")
|
t.Fatal("stale dependency closure accepted")
|
||||||
}
|
}
|
||||||
os.WriteFile("go.mod", []byte("module example.invalid/test\n"), 0600)
|
mustFixture(t, os.WriteFile("go.mod", []byte("module example.invalid/test\n"), 0600))
|
||||||
path := filepath.Join(bundleRoot, m.Modules[0].Files[2].Path)
|
path := filepath.Join(bundleRoot, m.Modules[0].Files[2].Path)
|
||||||
original, _ := os.ReadFile(path)
|
original, _ := os.ReadFile(path)
|
||||||
os.WriteFile(path, []byte("corrupted zip"), 0600)
|
mustFixture(t, os.WriteFile(path, []byte("corrupted zip"), 0600))
|
||||||
if check() == nil {
|
if check() == nil {
|
||||||
t.Fatal("modified artifact accepted")
|
t.Fatal("modified artifact accepted")
|
||||||
}
|
}
|
||||||
os.Remove(path)
|
mustFixture(t, os.Remove(path))
|
||||||
if check() == nil {
|
if check() == nil {
|
||||||
t.Fatal("missing artifact accepted")
|
t.Fatal("missing artifact accepted")
|
||||||
}
|
}
|
||||||
os.WriteFile(path, original, 0600)
|
mustFixture(t, os.WriteFile(path, original, 0600))
|
||||||
extra := filepath.Join(bundleRoot, "extra")
|
extra := filepath.Join(bundleRoot, "extra")
|
||||||
os.WriteFile(extra, []byte("unlisted"), 0600)
|
mustFixture(t, os.WriteFile(extra, []byte("unlisted"), 0600))
|
||||||
if check() == nil {
|
if check() == nil {
|
||||||
t.Fatal("unlisted artifact accepted")
|
t.Fatal("unlisted artifact accepted")
|
||||||
}
|
}
|
||||||
os.Remove(extra)
|
mustFixture(t, os.Remove(extra))
|
||||||
os.Symlink("manifest.json", extra)
|
mustFixture(t, os.Symlink("manifest.json", extra))
|
||||||
if check() == nil {
|
if check() == nil {
|
||||||
t.Fatal("symlink accepted")
|
t.Fatal("symlink accepted")
|
||||||
}
|
}
|
||||||
@@ -90,20 +90,22 @@ func TestNativeGoSumRejectsChangedModuleArtifact(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
mod := []byte("module " + modulePath + "\n\ngo 1.27.0\n")
|
mod := []byte("module " + modulePath + "\n\ngo 1.27.0\n")
|
||||||
os.WriteFile(base+".mod", mod, 0600)
|
mustFixture(t, os.WriteFile(base+".mod", mod, 0600))
|
||||||
os.WriteFile(base+".info", []byte(`{"Version":"v0.1.0","Time":"2026-01-01T00:00:00Z"}`), 0600)
|
mustFixture(t, os.WriteFile(base+".info", []byte(`{"Version":"v0.1.0","Time":"2026-01-01T00:00:00Z"}`), 0600))
|
||||||
var archive bytes.Buffer
|
var archive bytes.Buffer
|
||||||
zw := zip.NewWriter(&archive)
|
zw := zip.NewWriter(&archive)
|
||||||
entry, err := zw.Create(modulePath + "@" + version + "/go.mod")
|
entry, err := zw.Create(modulePath + "@" + version + "/go.mod")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
entry.Write(mod)
|
if _, err := entry.Write(mod); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
if err = zw.Close(); err != nil {
|
if err = zw.Close(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
os.WriteFile(base+".zip", archive.Bytes(), 0600)
|
mustFixture(t, os.WriteFile(base+".zip", archive.Bytes(), 0600))
|
||||||
os.WriteFile(filepath.Join(root, "go.mod"), []byte("module example.invalid/checksum\n\ngo 1.27.0\n\nrequire "+modulePath+" "+version+"\n"), 0600)
|
mustFixture(t, os.WriteFile(filepath.Join(root, "go.mod"), []byte("module example.invalid/checksum\n\ngo 1.27.0\n\nrequire "+modulePath+" "+version+"\n"), 0600))
|
||||||
run := func(cache string) ([]byte, error) {
|
run := func(cache string) ([]byte, error) {
|
||||||
cmd := exec.Command("go", "mod", "download", modulePath+"@"+version)
|
cmd := exec.Command("go", "mod", "download", modulePath+"@"+version)
|
||||||
cmd.Dir = root
|
cmd.Dir = root
|
||||||
@@ -113,7 +115,7 @@ func TestNativeGoSumRejectsChangedModuleArtifact(t *testing.T) {
|
|||||||
if output, err := run("original-cache"); err != nil {
|
if output, err := run("original-cache"); err != nil {
|
||||||
t.Fatalf("native fixture admission: %v: %s", err, output)
|
t.Fatalf("native fixture admission: %v: %s", err, output)
|
||||||
}
|
}
|
||||||
os.WriteFile(base+".mod", append(mod, '\n'), 0600)
|
mustFixture(t, os.WriteFile(base+".mod", append(mod, '\n'), 0600))
|
||||||
output, err := run("fresh-cache")
|
output, err := run("fresh-cache")
|
||||||
if err == nil || !bytes.Contains(output, []byte("checksum mismatch")) {
|
if err == nil || !bytes.Contains(output, []byte("checksum mismatch")) {
|
||||||
t.Fatalf("native module checksum guard failed: %v: %s", err, output)
|
t.Fatalf("native module checksum guard failed: %v: %s", err, output)
|
||||||
@@ -123,12 +125,12 @@ func TestNativeGoSumRejectsChangedModuleArtifact(t *testing.T) {
|
|||||||
func TestGeneratorMissingPrivateMetadataNeverInvokesGit(t *testing.T) {
|
func TestGeneratorMissingPrivateMetadataNeverInvokesGit(t *testing.T) {
|
||||||
root := t.TempDir()
|
root := t.TempDir()
|
||||||
t.Chdir(root)
|
t.Chdir(root)
|
||||||
os.WriteFile("go.mod", []byte("module example.invalid/offline\n\ngo 1.27.0\n\nrequire code.fritzlab.net/agenthub/missing v0.0.1\n"), 0600)
|
mustFixture(t, os.WriteFile("go.mod", []byte("module example.invalid/offline\n\ngo 1.27.0\n\nrequire code.fritzlab.net/agenthub/missing v0.0.1\n"), 0600))
|
||||||
os.WriteFile("go.sum", nil, 0600)
|
mustFixture(t, os.WriteFile("go.sum", nil, 0600))
|
||||||
bin := filepath.Join(root, "bin")
|
bin := filepath.Join(root, "bin")
|
||||||
os.Mkdir(bin, 0700)
|
mustFixture(t, os.Mkdir(bin, 0700))
|
||||||
marker := filepath.Join(root, "git-invoked")
|
marker := filepath.Join(root, "git-invoked")
|
||||||
os.WriteFile(filepath.Join(bin, "git"), []byte("#!/bin/sh\nprintf invoked > \"$PRIVATE_GIT_PROBE\"\nexit 99\n"), 0700)
|
mustFixture(t, os.WriteFile(filepath.Join(bin, "git"), []byte("#!/bin/sh\nprintf invoked > \"$PRIVATE_GIT_PROBE\"\nexit 99\n"), 0700))
|
||||||
t.Setenv("PATH", bin+string(os.PathListSeparator)+os.Getenv("PATH"))
|
t.Setenv("PATH", bin+string(os.PathListSeparator)+os.Getenv("PATH"))
|
||||||
t.Setenv("PRIVATE_GIT_PROBE", marker)
|
t.Setenv("PRIVATE_GIT_PROBE", marker)
|
||||||
t.Setenv("GOMODCACHE", filepath.Join(root, "empty-cache"))
|
t.Setenv("GOMODCACHE", filepath.Join(root, "empty-cache"))
|
||||||
@@ -149,7 +151,7 @@ func TestGeneratorMissingPrivateMetadataNeverInvokesGit(t *testing.T) {
|
|||||||
if _, err = os.Stat(bundleRoot); !os.IsNotExist(err) {
|
if _, err = os.Stat(bundleRoot); !os.IsNotExist(err) {
|
||||||
t.Fatal("failed generation published output")
|
t.Fatal("failed generation published output")
|
||||||
}
|
}
|
||||||
os.WriteFile("go.mod", []byte("module example.invalid/offline\n\ngo 1.999.0\n"), 0600)
|
mustFixture(t, os.WriteFile("go.mod", []byte("module example.invalid/offline\n\ngo 1.999.0\n"), 0600))
|
||||||
_, err = nativeGo("list", "-m", "-json", "all")
|
_, err = nativeGo("list", "-m", "-json", "all")
|
||||||
if !errors.As(err, &failure) || !bytes.Contains(failure.Stderr, []byte("GOTOOLCHAIN=local")) {
|
if !errors.As(err, &failure) || !bytes.Contains(failure.Stderr, []byte("GOTOOLCHAIN=local")) {
|
||||||
t.Fatalf("toolchain download not disabled: %v", err)
|
t.Fatalf("toolchain download not disabled: %v", err)
|
||||||
@@ -186,3 +188,10 @@ func TestLazyGraphModuleCacheIdentity(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustFixture(t *testing.T, err error) {
|
||||||
|
t.Helper()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user