From c0d1dc69e70944ab30bdd9adb229d68be426cc9f Mon Sep 17 00:00:00 2001
From: per1234 <accounts@perglass.com>
Date: Tue, 8 Dec 2020 17:08:01 -0800
Subject: [PATCH] Control logging via environment variables instead of flags

The logging functionality is only needed when debugging the code. This is not something the user will have a use for, so
having command line flags adds unnecessary complexity to the UI.
---
 README.md                           | 10 ++++++++--
 cli/cli.go                          |  2 --
 configuration/configuration.go      | 25 ++++++++++++++-----------
 configuration/configuration_test.go | 25 ++++++++++++++++++-------
 configuration/defaults.go           |  3 +++
 5 files changed, 43 insertions(+), 22 deletions(-)

diff --git a/README.md b/README.md
index faae3ed8..1330481e 100644
--- a/README.md
+++ b/README.md
@@ -10,5 +10,11 @@
 
 After installing `arduino-check`, run the command `arduino-check --help` for usage documentation.
 
-Set the `ARDUINO_CHECK_OFFICIAL` environment variable to "true" to run the checks that only apply to official Arduino
-projects.
+A few additional configuration options only of use for internal/development use of the tool can be set via environment
+variables:
+
+- `ARDUINO_CHECK_OFFICIAL` - Set to `"true"` to run the checks that only apply to official Arduino projects.
+- `ARDUINO_CHECK_LOG_LEVEL` - Messages with this level and above will be logged.
+  - Supported values: `trace`, `debug`, `info`, `warn`, `error`, `fatal`, `panic`
+- `ARDUINO_CHECK_LOG_FORMAT` - The output format for the logs.
+  - Supported values: `text`, `json`
diff --git a/cli/cli.go b/cli/cli.go
index 20e9cc95..48be6222 100644
--- a/cli/cli.go
+++ b/cli/cli.go
@@ -34,8 +34,6 @@ func Root() *cobra.Command {
 	rootCommand.PersistentFlags().String("compliance", "specification", "Configure how strict the tool is. Can be {strict|specification|permissive}")
 	rootCommand.PersistentFlags().String("format", "text", "The output format can be {text|json}.")
 	rootCommand.PersistentFlags().String("library-manager", "", "Configure the checks for libraries in the Arduino Library Manager index. Can be {submit|update|false}.\nsubmit: Also run additional checks required to pass before a library is accepted for inclusion in the index.\nupdate: Also run additional checks required to pass before new releases of a library already in the index are accepted.\nfalse: Don't run any Library Manager-specific checks.")
-	rootCommand.PersistentFlags().String("log-format", "text", "The output format for the logs, can be {text|json}.")
-	rootCommand.PersistentFlags().String("log-level", "panic", "Messages with this level and above will be logged. Valid levels are: trace, debug, info, warn, error, fatal, panic")
 	rootCommand.PersistentFlags().String("project-type", "all", "Only check projects of the specified type and their subprojects. Can be {sketch|library|all}.")
 	rootCommand.PersistentFlags().Bool("recursive", true, "Search path recursively for Arduino projects to check. Can be {true|false}.")
 	rootCommand.PersistentFlags().String("report-file", "", "Save a report on the checks to this file.")
diff --git a/configuration/configuration.go b/configuration/configuration.go
index 34dc8124..e93d3527 100644
--- a/configuration/configuration.go
+++ b/configuration/configuration.go
@@ -56,19 +56,23 @@ func Initialize(flags *pflag.FlagSet, projectPaths []string) error {
 		}
 	}
 
-	logFormatString, _ := flags.GetString("log-format")
-	logFormat, err := logFormatFromString(logFormatString)
-	if err != nil {
-		return fmt.Errorf("--log-format flag value %s not valid", logFormatString)
+	if logFormatString, ok := os.LookupEnv("ARDUINO_CHECK_LOG_FORMAT"); ok {
+		logFormat, err := logFormatFromString(logFormatString)
+		if err != nil {
+			return fmt.Errorf("--log-format flag value %s not valid", logFormatString)
+		}
+		logrus.SetFormatter(logFormat)
 	}
-	logrus.SetFormatter(logFormat)
 
-	logLevelString, _ := flags.GetString("log-level")
-	logLevel, err := logrus.ParseLevel(logLevelString)
-	if err != nil {
-		return fmt.Errorf("--log-level flag value %s not valid", logLevelString)
+	if logLevelString, ok := os.LookupEnv("ARDUINO_CHECK_LOG_LEVEL"); ok {
+		logLevel, err := logrus.ParseLevel(logLevelString)
+		if err != nil {
+			return fmt.Errorf("--log-level flag value %s not valid", logLevelString)
+		}
+		logrus.SetLevel(logLevel)
+	} else {
+		logrus.SetLevel(defaultLogLevel)
 	}
-	logrus.SetLevel(logLevel)
 
 	superprojectTypeFilterString, _ := flags.GetString("project-type")
 	superprojectTypeFilter, err = projecttype.FromString(superprojectTypeFilterString)
@@ -117,7 +121,6 @@ func Initialize(flags *pflag.FlagSet, projectPaths []string) error {
 		"output format":                   OutputFormat(),
 		"Library Manager submission mode": customCheckModes[checkmode.LibraryManagerSubmission],
 		"Library Manager update mode":     customCheckModes[checkmode.LibraryManagerIndexed],
-		"log format":                      logFormatString,
 		"log level":                       logrus.GetLevel().String(),
 		"superproject type filter":        SuperprojectTypeFilter(),
 		"recursive":                       Recursive(),
diff --git a/configuration/configuration_test.go b/configuration/configuration_test.go
index 016cd897..c3fa325f 100644
--- a/configuration/configuration_test.go
+++ b/configuration/configuration_test.go
@@ -24,6 +24,7 @@ import (
 	"github.com/arduino/arduino-check/result/outputformat"
 	"github.com/arduino/arduino-check/util/test"
 	"github.com/arduino/go-paths-helper"
+	"github.com/sirupsen/logrus"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
@@ -107,16 +108,26 @@ func TestInitializeLibraryManager(t *testing.T) {
 }
 
 func TestInitializeLogFormat(t *testing.T) {
-	flags := test.ConfigurationFlags()
+	os.Setenv("ARDUINO_CHECK_LOG_FORMAT", "foo")
+	assert.Error(t, Initialize(test.ConfigurationFlags(), projectPaths), "Invalid format")
 
-	flags.Set("log-format", "foo")
-	assert.Error(t, Initialize(flags, projectPaths))
+	os.Setenv("ARDUINO_CHECK_LOG_FORMAT", "text")
+	assert.Nil(t, Initialize(test.ConfigurationFlags(), projectPaths), "text format")
 
-	flags.Set("log-format", "text")
-	assert.Nil(t, Initialize(flags, projectPaths))
+	os.Setenv("ARDUINO_CHECK_LOG_FORMAT", "json")
+	assert.Nil(t, Initialize(test.ConfigurationFlags(), projectPaths), "json format")
+}
 
-	flags.Set("log-format", "json")
-	assert.Nil(t, Initialize(flags, projectPaths))
+func TestInitializeLogLevel(t *testing.T) {
+	require.Nil(t, Initialize(test.ConfigurationFlags(), projectPaths))
+	assert.Equal(t, defaultLogLevel, logrus.GetLevel(), "Default level")
+
+	os.Setenv("ARDUINO_CHECK_LOG_LEVEL", "foo")
+	assert.Error(t, Initialize(test.ConfigurationFlags(), projectPaths), "Invalid level")
+
+	os.Setenv("ARDUINO_CHECK_LOG_LEVEL", "info")
+	assert.Nil(t, Initialize(test.ConfigurationFlags(), projectPaths), "Valid level")
+	assert.Equal(t, logrus.InfoLevel, logrus.GetLevel())
 }
 
 func TestInitializeProjectType(t *testing.T) {
diff --git a/configuration/defaults.go b/configuration/defaults.go
index 83f99adc..a4cc1e3b 100644
--- a/configuration/defaults.go
+++ b/configuration/defaults.go
@@ -20,6 +20,7 @@ package configuration
 import (
 	"github.com/arduino/arduino-check/configuration/checkmode"
 	"github.com/arduino/arduino-check/project/projecttype"
+	"github.com/sirupsen/logrus"
 )
 
 // Default check modes for each superproject type.
@@ -58,3 +59,5 @@ var defaultCheckModes = map[projecttype.Type]map[checkmode.Type]bool{
 		checkmode.Official:                 false,
 	},
 }
+
+var defaultLogLevel = logrus.FatalLevel