Separate Go discovery configuration from diagnostics

This commit is contained in:
2026-10-07 00:45:23 +00:00
parent ceb7e2847a
commit e6def4ed7b
4 changed files with 55 additions and 8 deletions

View File

@@ -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

View File

@@ -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.

View File

@@ -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)
}

View File

@@ -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 {