diff --git a/internal/cli/configuration/defaults.go b/internal/cli/configuration/defaults.go index 953bd4762f5..b2437fb91af 100644 --- a/internal/cli/configuration/defaults.go +++ b/internal/cli/configuration/defaults.go @@ -84,7 +84,7 @@ func InjectEnvVars(settings *Settings) { // Bind env aliases to keep backward compatibility setIfEnvExists := func(key, env string) { if v, ok := os.LookupEnv(env); ok { - settings.SetFromCLIArgs(key, v) + settings.SetFromENV(key, v) } } setIfEnvExists("library.enable_unsafe_install", "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL") diff --git a/internal/go-configmap/cli.go b/internal/go-configmap/cli.go index d467cfc9c32..2e829191d6c 100644 --- a/internal/go-configmap/cli.go +++ b/internal/go-configmap/cli.go @@ -21,6 +21,43 @@ import ( "strings" ) +func (c *Map) SetFromENV(key string, arg string) error { + // in case of schemaless configuration, we don't know the type of the setting + // we will save it as a string + if len(c.schema) == 0 { + c.Set(key, arg) + return nil + } + + // Find the correct type for the given setting + valueType, ok := c.schema[key] + if !ok { + return fmt.Errorf("key not found: %s", key) + } + + var value any + { + var conversionError error + switch valueType.String() { + case "uint": + value, conversionError = strconv.Atoi(arg) + case "bool": + value, conversionError = strconv.ParseBool(arg) + case "string": + value = arg + case "[]string": + value = strings.Split(arg, " ") + default: + return fmt.Errorf("unhandled type: %s", valueType) + } + if conversionError != nil { + return fmt.Errorf("error setting value: %v", conversionError) + } + } + + return c.Set(key, value) +} + func (c *Map) SetFromCLIArgs(key string, args ...string) error { if len(args) == 0 { c.Delete(key) @@ -101,7 +138,7 @@ func (c *Map) InjectEnvVars(env []string, prefix string) []error { } // Update the configuration value - if err := c.SetFromCLIArgs(key, envValue); err != nil { + if err := c.SetFromENV(key, envValue); err != nil { errs = append(errs, err) } } diff --git a/internal/integrationtest/config/config_test.go b/internal/integrationtest/config/config_test.go index 5ed5145dd62..6e57eebf72f 100644 --- a/internal/integrationtest/config/config_test.go +++ b/internal/integrationtest/config/config_test.go @@ -902,3 +902,32 @@ build.unk: 123 require.NoError(t, err) require.Equal(t, "en", strings.TrimSpace(string(out))) } + +func TestConfigViaEnvVars(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + // array of strings + out, _, err := cli.RunWithCustomEnv( + map[string]string{"ARDUINO_BOARD_MANAGER_ADDITIONAL_URLS": "https://espressif.github.io/arduino-esp32/package_esp32_index.json https://arduino.esp8266.com/stable/package_esp8266com_index.json"}, + "config", "get", "board_manager.additional_urls", + ) + require.NoError(t, err) + require.Equal(t, "- https://espressif.github.io/arduino-esp32/package_esp32_index.json\n- https://arduino.esp8266.com/stable/package_esp8266com_index.json\n\n", string(out)) + + // boolean + out, _, err = cli.RunWithCustomEnv( + map[string]string{"ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL": "True"}, + "config", "get", "library.enable_unsafe_install", + ) + require.NoError(t, err) + require.Equal(t, "true\n\n", string(out)) + + // integer + out, _, err = cli.RunWithCustomEnv( + map[string]string{"ARDUINO_BUILD_CACHE_COMPILATIONS_BEFORE_PURGE": "20"}, + "config", "get", "build_cache.compilations_before_purge", + ) + require.NoError(t, err) + require.Equal(t, "20\n\n", string(out)) +}