diff --git a/pkg/toolinstall/resolver.go b/pkg/toolinstall/resolver.go index 98e865888..370071d61 100644 --- a/pkg/toolinstall/resolver.go +++ b/pkg/toolinstall/resolver.go @@ -25,14 +25,23 @@ func EnsureCommand(ctx context.Context, command, version string) (string, error) return command, nil } - lower := strings.ToLower(strings.TrimSpace(version)) + version = strings.TrimSpace(version) + lower := strings.ToLower(version) if lower == "false" || lower == "off" { return command, nil } resolvedPath, err := resolve(ctx, command, version) if err != nil { - return "", fmt.Errorf("auto-installing command %q: %w", command, err) + if version != "" { + return "", fmt.Errorf("auto-installing command %q: %w", command, err) + } + + slog.Warn("Auto-install failed, falling back to original command", + "command", command, + "error", err, + ) + return command, nil } return resolvedPath, nil diff --git a/pkg/toolinstall/resolver_test.go b/pkg/toolinstall/resolver_test.go index f233a14d1..09416b0d6 100644 --- a/pkg/toolinstall/resolver_test.go +++ b/pkg/toolinstall/resolver_test.go @@ -50,7 +50,16 @@ func TestEnsureCommand_DisabledPerToolset(t *testing.T) { } } -func TestEnsureCommand_SoftFail(t *testing.T) { +func TestEnsureCommand_AutoDetectFailureFallsBackToOriginalCommand(t *testing.T) { + t.Setenv("DOCKER_AGENT_TOOLS_DIR", t.TempDir()) + t.Setenv("DOCKER_AGENT_AUTO_INSTALL", "") + + result, err := EnsureCommand(t.Context(), "nonexistent-tool", "") + require.NoError(t, err) + assert.Equal(t, "nonexistent-tool", result) +} + +func TestEnsureCommand_ExplicitVersionFailureStillErrors(t *testing.T) { t.Setenv("DOCKER_AGENT_TOOLS_DIR", t.TempDir()) t.Setenv("DOCKER_AGENT_AUTO_INSTALL", "") @@ -73,7 +82,7 @@ func TestEnsureCommand_FoundInBinDir(t *testing.T) { assert.Equal(t, fakeBin, result) } -func TestEnsureCommand_NonExecutableInBinDirIsSkipped(t *testing.T) { +func TestEnsureCommand_NonExecutableInBinDirFallsBackToOriginalCommand(t *testing.T) { toolsDir := t.TempDir() t.Setenv("DOCKER_AGENT_TOOLS_DIR", toolsDir) t.Setenv("DOCKER_AGENT_AUTO_INSTALL", "") @@ -82,9 +91,9 @@ func TestEnsureCommand_NonExecutableInBinDirIsSkipped(t *testing.T) { require.NoError(t, os.MkdirAll(binDir, 0o755)) require.NoError(t, os.WriteFile(filepath.Join(binDir, "not-executable"), []byte("data"), 0o644)) - // Falls through to auto-install → fails → returns error. - _, err := EnsureCommand(t.Context(), "not-executable", "") - require.Error(t, err) + result, err := EnsureCommand(t.Context(), "not-executable", "") + require.NoError(t, err) + assert.Equal(t, "not-executable", result) } // --- resolve tests ---