Isolate synthetic module downloads in workflow tests
This commit is contained in:
@@ -150,6 +150,19 @@ func TestWoodpeckerTagDeliveryTemplate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWoodpeckerTagDeliveryUsesTaggedModuleVersion(t *testing.T) {
|
func TestWoodpeckerTagDeliveryUsesTaggedModuleVersion(t *testing.T) {
|
||||||
|
// Synthetic downloads must leave the caller's module cache untouched.
|
||||||
|
callerCache := t.TempDir()
|
||||||
|
t.Setenv("GOMODCACHE", callerCache)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
entries, err := os.ReadDir(callerCache)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(entries) != 0 {
|
||||||
|
t.Errorf("synthetic module downloads modified the caller's cache: %v", entries)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
root := cliRepositoryRoot(t)
|
root := cliRepositoryRoot(t)
|
||||||
contents, err := os.ReadFile(filepath.Join(root, "examples", "woodpecker", "tag-delivery.yml"))
|
contents, err := os.ReadFile(filepath.Join(root, "examples", "woodpecker", "tag-delivery.yml"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -185,7 +198,7 @@ func TestWoodpeckerTagDeliveryUsesTaggedModuleVersion(t *testing.T) {
|
|||||||
moduleBefore := readWoodpeckerFixtureFile(t, filepath.Join(repository, "go.mod"))
|
moduleBefore := readWoodpeckerFixtureFile(t, filepath.Join(repository, "go.mod"))
|
||||||
commit := oldCommit
|
commit := oldCommit
|
||||||
env := templateEnvironment(repository, commit, goDir, goLog)
|
env := templateEnvironment(repository, commit, goDir, goLog)
|
||||||
env["GOPROXY"] = "file://" + filepath.ToSlash(proxy)
|
useSyntheticModuleProxy(t, env, "file://"+filepath.ToSlash(proxy))
|
||||||
sumLog := filepath.Join(t.TempDir(), "tool-only-sums")
|
sumLog := filepath.Join(t.TempDir(), "tool-only-sums")
|
||||||
env["RELEASEKIT_SUM_LOG"] = sumLog
|
env["RELEASEKIT_SUM_LOG"] = sumLog
|
||||||
output := runWoodpeckerBlock(t, command, repository, env)
|
output := runWoodpeckerBlock(t, command, repository, env)
|
||||||
@@ -207,7 +220,7 @@ func TestWoodpeckerTagDeliveryUsesTaggedModuleVersion(t *testing.T) {
|
|||||||
commit := pushTaggedCLIRepository(t, repository)
|
commit := pushTaggedCLIRepository(t, repository)
|
||||||
moduleBefore := readWoodpeckerFixtureFile(t, filepath.Join(repository, "go.mod"))
|
moduleBefore := readWoodpeckerFixtureFile(t, filepath.Join(repository, "go.mod"))
|
||||||
env := templateEnvironment(repository, commit, goDir, goLog)
|
env := templateEnvironment(repository, commit, goDir, goLog)
|
||||||
env["GOPROXY"] = "file://" + filepath.ToSlash(proxy)
|
useSyntheticModuleProxy(t, env, "file://"+filepath.ToSlash(proxy))
|
||||||
sumLog := filepath.Join(t.TempDir(), "tool-only-sums")
|
sumLog := filepath.Join(t.TempDir(), "tool-only-sums")
|
||||||
env["RELEASEKIT_SUM_LOG"] = sumLog
|
env["RELEASEKIT_SUM_LOG"] = sumLog
|
||||||
output := runWoodpeckerBlock(t, command, repository, env)
|
output := runWoodpeckerBlock(t, command, repository, env)
|
||||||
@@ -245,21 +258,15 @@ func TestWoodpeckerSourceDeliveryTemplateSelfBootstraps(t *testing.T) {
|
|||||||
defer proxy.Close()
|
defer proxy.Close()
|
||||||
writeRepositoryFile(t, repository, "go.mod", "module example.com/cli-candidate\n\ngo 1.25.0\n\nrequire "+dependency+" v1.0.0\n")
|
writeRepositoryFile(t, repository, "go.mod", "module example.com/cli-candidate\n\ngo 1.25.0\n\nrequire "+dependency+" v1.0.0\n")
|
||||||
writeRepositoryFile(t, repository, "cmd/releasekit/main.go", "package main\n\nimport (\"fmt\"; \"os\"; helper \""+dependency+"\")\n\nfunc main() {\n\tfmt.Println(\"self-bootstrap \" + helper.Message)\n\tfmt.Printf(\"tool-args=%q\\n\", os.Args[1:])\n}\n")
|
writeRepositoryFile(t, repository, "cmd/releasekit/main.go", "package main\n\nimport (\"fmt\"; \"os\"; helper \""+dependency+"\")\n\nfunc main() {\n\tfmt.Println(\"self-bootstrap \" + helper.Message)\n\tfmt.Printf(\"tool-args=%q\\n\", os.Args[1:])\n}\n")
|
||||||
preparationEnv := map[string]string{
|
preparationEnv := map[string]string{}
|
||||||
"GOPROXY": proxy.URL, "GOSUMDB": "off", "GONOPROXY": "none", "GOPRIVATE": "",
|
useSyntheticModuleProxy(t, preparationEnv, proxy.URL)
|
||||||
"GOWORK": "off", "GOTOOLCHAIN": "local", "GOENV": "off", "GOFLAGS": "-modcacherw",
|
|
||||||
"GOMODCACHE": t.TempDir(),
|
|
||||||
}
|
|
||||||
runWoodpeckerBlock(t, "go mod download "+dependency, repository, preparationEnv)
|
runWoodpeckerBlock(t, "go mod download "+dependency, repository, preparationEnv)
|
||||||
cliGitRun(t, repository, "add", "cmd/releasekit/main.go", "go.mod", "go.sum")
|
cliGitRun(t, repository, "add", "cmd/releasekit/main.go", "go.mod", "go.sum")
|
||||||
cliGitRun(t, repository, "commit", "-m", "add the self-bootstrapped command")
|
cliGitRun(t, repository, "commit", "-m", "add the self-bootstrapped command")
|
||||||
commit := pushTaggedCLIRepository(t, repository)
|
commit := pushTaggedCLIRepository(t, repository)
|
||||||
goDir, goLog := installGoBootstrapShim(t)
|
goDir, goLog := installGoBootstrapShim(t)
|
||||||
env := templateEnvironment(repository, commit, goDir, goLog)
|
env := templateEnvironment(repository, commit, goDir, goLog)
|
||||||
for key, value := range preparationEnv {
|
useSyntheticModuleProxy(t, env, proxy.URL)
|
||||||
env[key] = value
|
|
||||||
}
|
|
||||||
env["GOMODCACHE"] = t.TempDir()
|
|
||||||
proxyRequests.Store(0)
|
proxyRequests.Store(0)
|
||||||
env["CI_COMMIT_SHA"] = strings.Repeat("0", len(commit))
|
env["CI_COMMIT_SHA"] = strings.Repeat("0", len(commit))
|
||||||
if output, err := executeWoodpeckerBlock(command, repository, env); err == nil {
|
if output, err := executeWoodpeckerBlock(command, repository, env); err == nil {
|
||||||
@@ -426,6 +433,19 @@ esac
|
|||||||
return shimDir, goLog
|
return shimDir, goLog
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func useSyntheticModuleProxy(t *testing.T, environment map[string]string, proxyURL string) {
|
||||||
|
t.Helper()
|
||||||
|
environment["GOMODCACHE"] = t.TempDir()
|
||||||
|
environment["GOPROXY"] = proxyURL
|
||||||
|
environment["GOSUMDB"] = "off"
|
||||||
|
environment["GONOPROXY"] = "none"
|
||||||
|
environment["GOPRIVATE"] = ""
|
||||||
|
environment["GOWORK"] = "off"
|
||||||
|
environment["GOTOOLCHAIN"] = "local"
|
||||||
|
environment["GOENV"] = "off"
|
||||||
|
environment["GOFLAGS"] = "-modcacherw"
|
||||||
|
}
|
||||||
|
|
||||||
func templateEnvironment(repository, commit, shimDir, goLog string) map[string]string {
|
func templateEnvironment(repository, commit, shimDir, goLog string) map[string]string {
|
||||||
realGo, _ := exec.LookPath("go")
|
realGo, _ := exec.LookPath("go")
|
||||||
return map[string]string{
|
return map[string]string{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# PromptKit Bug Report: v0.2.0 Module Checksum Mismatch
|
# PromptKit Bug Report: v0.2.0 Module Checksum Mismatch
|
||||||
|
|
||||||
**Status:** Stale local module metadata confirmed; cache recovery and test
|
**Status:** Stale local module metadata confirmed; test isolation fixed.
|
||||||
isolation follow-up remain pending.
|
Shared-cache recovery and PromptKit's adoption retry remain pending.
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
@@ -95,22 +95,32 @@ Recovery was verified in a copied cache; PromptKit's adoption retry remains pend
|
|||||||
### Related Test-Isolation Defect
|
### Related Test-Isolation Defect
|
||||||
|
|
||||||
The workflow tests' [environment helper](../../cmd/releasekit/woodpecker_test.go)
|
The workflow tests' [environment helper](../../cmd/releasekit/woodpecker_test.go)
|
||||||
disables checksum verification for synthetic fixtures and inherits the caller's
|
disabled checksum verification for synthetic fixtures and inherited the caller's
|
||||||
module cache. The version-selection test serves synthetic ReleaseKit versions
|
module cache. The version-selection test serves synthetic ReleaseKit versions
|
||||||
from a local module proxy.
|
from a local module proxy.
|
||||||
|
|
||||||
Running `TestWoodpeckerTagDeliveryUsesTaggedModuleVersion` with a disposable
|
Running `TestWoodpeckerTagDeliveryUsesTaggedModuleVersion` with a disposable
|
||||||
inherited `GOMODCACHE` passed and left synthetic `v0.2.197` and `v0.2.198`
|
inherited `GOMODCACHE` passed and left synthetic `v0.2.197` and `v0.2.198`
|
||||||
metadata in that cache. This confirms that the tests can contaminate a
|
metadata in that cache. This confirmed that the tests could contaminate a
|
||||||
developer's module cache. It establishes a related defect; attribution of the
|
developer's module cache. It established a related defect; attribution of the
|
||||||
stale `v0.2.0` entry to a particular test or command remains unconfirmed.
|
stale `v0.2.0` entry to a particular test or command remains unconfirmed.
|
||||||
|
|
||||||
|
### Test-Isolation Resolution
|
||||||
|
|
||||||
|
Both synthetic-proxy test families now use a shared environment helper that
|
||||||
|
assigns a fresh test-owned `GOMODCACHE` and scopes proxy/checksum settings to
|
||||||
|
their Go subprocesses. Source-bootstrap preparation and execution retain
|
||||||
|
separate caches. Tests that build real ReleaseKit source continue to use their
|
||||||
|
prepared dependencies.
|
||||||
|
|
||||||
|
The existing tagged-version test now supplies a disposable caller cache and
|
||||||
|
asserts that it remains empty after fixture execution. This regression failed
|
||||||
|
before the fix and passed afterward. All Woodpecker workflow tests passed.
|
||||||
|
|
||||||
## Recommended Follow-Up
|
## Recommended Follow-Up
|
||||||
|
|
||||||
1. Quarantine the affected local `v0.2.0.mod` entry and retry PromptKit's adoption
|
1. Quarantine the affected local `v0.2.0.mod` entry and retry PromptKit's adoption
|
||||||
with normal checksum verification. Retain the quarantined bytes as evidence.
|
with normal checksum verification. Retain the quarantined bytes as evidence.
|
||||||
2. Give synthetic module-proxy tests a temporary `GOMODCACHE` owned by the test
|
2. Record the actual cache recovery and consumer retry outcomes here. Preserve
|
||||||
fixture, with focused regression coverage for cache isolation.
|
|
||||||
3. Record the actual cache recovery and consumer retry outcomes here. Preserve
|
|
||||||
the published v0.2.0 tag and checksums; this incident requires no replacement
|
the published v0.2.0 tag and checksums; this incident requires no replacement
|
||||||
release.
|
release.
|
||||||
|
|||||||
Reference in New Issue
Block a user