Separate Go discovery configuration from diagnostics
This commit is contained in:
@@ -20,6 +20,10 @@ and native cgo/C-tool configuration into its settings. This captures values
|
||||
supplied by either the process environment or the persistent Go environment
|
||||
file.
|
||||
|
||||
Configuration discovery parses JSON from stdout. Stderr is captured separately
|
||||
and included in command-failure diagnostics, so a successful query can emit
|
||||
warnings while supplying valid configuration.
|
||||
|
||||
## Command environments
|
||||
|
||||
Every Go command receives `GOENV=off`, so removed persistent values cannot
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Date: 2026-10-06.
|
||||
Reviewed source: `55333b0`.
|
||||
Status: Two findings require remediation.
|
||||
Status: R1 resolved; R2 requires remediation.
|
||||
|
||||
## Scope and assessment
|
||||
|
||||
@@ -30,7 +30,7 @@ repairs within those decisions.
|
||||
|
||||
## R1 — Medium: Go discovery treats successful diagnostics as invalid configuration
|
||||
|
||||
Status: Open.
|
||||
Status: Resolved.
|
||||
Category: Correctness and an accidental environment prerequisite.
|
||||
Introduced by: `0809312`.
|
||||
|
||||
@@ -67,6 +67,13 @@ the settings. A failing command retains useful stderr and its cause. Existing
|
||||
ambient/persistent flag, host-target, cache, and architecture-tuning regressions
|
||||
continue to pass. These checks add no warning-free configuration requirement.
|
||||
|
||||
**Resolution (2026-10-07):** Discovery captures stdout and stderr separately,
|
||||
parses configuration from stdout, and preserves diagnostic output and subprocess
|
||||
causes on failure. A subprocess fixture proves successful JSON discovery accepts
|
||||
stderr diagnostics and preserves host/cache settings; another verifies failure
|
||||
diagnostics and exit-error identity. The success regression failed before the
|
||||
fix. Go-environment, candidate-validation, and build regression checks pass.
|
||||
|
||||
## R2 — Medium: Wrapper regression testing repeats the project suite inside itself
|
||||
|
||||
Status: Open.
|
||||
|
||||
@@ -187,18 +187,18 @@ func discoveryEnvironment() map[string]string {
|
||||
}
|
||||
|
||||
func discover(ctx context.Context, directory string, environment map[string]string, args ...string) ([]byte, error) {
|
||||
captured := &combinedWriter{}
|
||||
var configuration, diagnostics bytes.Buffer
|
||||
err := process.Run(ctx, process.Invocation{
|
||||
Args: args,
|
||||
Dir: directory,
|
||||
Env: environment,
|
||||
Stdout: captured,
|
||||
Stderr: captured,
|
||||
Stdout: &configuration,
|
||||
Stderr: &diagnostics,
|
||||
})
|
||||
contents := captured.Bytes()
|
||||
contents := configuration.Bytes()
|
||||
if err != nil {
|
||||
if len(contents) != 0 {
|
||||
return contents, fmt.Errorf("%s: %w: %s", strings.Join(args, " "), err, strings.TrimSpace(string(contents)))
|
||||
if output := strings.TrimSpace(configuration.String() + diagnostics.String()); output != "" {
|
||||
return contents, fmt.Errorf("%s: %w: %s", strings.Join(args, " "), err, output)
|
||||
}
|
||||
return contents, fmt.Errorf("%s: %w", strings.Join(args, " "), err)
|
||||
}
|
||||
|
||||
@@ -47,6 +47,18 @@ func runGoPreparationFixture() int {
|
||||
return 11
|
||||
}
|
||||
switch os.Getenv("RELEASEKIT_GO_FIXTURE_MODE") {
|
||||
case "discovery":
|
||||
settings := make(map[string]string)
|
||||
for _, key := range os.Args[3:] {
|
||||
settings[key] = os.Getenv(key)
|
||||
}
|
||||
settings["GOHOSTOS"] = runtime.GOOS
|
||||
settings["GOHOSTARCH"] = runtime.GOARCH
|
||||
fmt.Fprintln(os.Stderr, "fixture discovery diagnostic")
|
||||
if err := json.NewEncoder(os.Stdout).Encode(settings); err != nil {
|
||||
return 12
|
||||
}
|
||||
return 0
|
||||
case "fail":
|
||||
fmt.Fprintln(os.Stderr, "fixture dependency failure")
|
||||
return 23
|
||||
@@ -59,6 +71,30 @@ func runGoPreparationFixture() int {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscoveryAcceptsDiagnosticsWithValidConfiguration(t *testing.T) {
|
||||
repository, _ := installGoPreparationFixture(t)
|
||||
t.Setenv("RELEASEKIT_GO_FIXTURE_MODE", "discovery")
|
||||
cache := filepath.Join(t.TempDir(), "cache")
|
||||
t.Setenv("GOCACHE", cache)
|
||||
tool, err := New(context.Background(), repository)
|
||||
if err != nil {
|
||||
t.Fatalf("New() rejected successful discovery: %v", err)
|
||||
}
|
||||
if tool.HostTarget() != (Target{OS: runtime.GOOS, Arch: runtime.GOARCH}) || tool.settings["GOCACHE"] != cache {
|
||||
t.Fatalf("discovered host=%v cache=%q", tool.HostTarget(), tool.settings["GOCACHE"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscoveryPreservesFailureDiagnosticsAndCause(t *testing.T) {
|
||||
repository, _ := installGoPreparationFixture(t)
|
||||
t.Setenv("RELEASEKIT_GO_FIXTURE_MODE", "fail")
|
||||
_, err := New(context.Background(), repository)
|
||||
var exitError *exec.ExitError
|
||||
if !errors.As(err, &exitError) || exitError.ExitCode() != 23 || !strings.Contains(err.Error(), "fixture dependency failure") {
|
||||
t.Fatalf("New() error = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func mustGetwd() string {
|
||||
directory, err := os.Getwd()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user