From 2f17abedb977f473464e0bf664380ef949e5db5c Mon Sep 17 00:00:00 2001 From: Markus Pesch Date: Tue, 12 Aug 2025 16:28:40 +0200 Subject: [PATCH] fix: be compliant with golanci linter --- cmd/autharr/main.go | 24 +++++++++++++++++++----- cmd/healarr/main.go | 10 +++++++--- pkg/config/config.go | 26 ++++++++++++++++---------- pkg/config/config_test.go | 4 ++++ pkg/health/health.go | 7 ++++--- 5 files changed, 50 insertions(+), 21 deletions(-) diff --git a/cmd/autharr/main.go b/cmd/autharr/main.go index 00eef28..9e84593 100644 --- a/cmd/autharr/main.go +++ b/cmd/autharr/main.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "log" "os" "path/filepath" "time" @@ -26,7 +27,9 @@ autharr /etc/lidarr/config.xml`, } rootCmd.Flags().Bool("watch", false, "Listens for changes to the configuration and writes the token continuously to the output") - rootCmd.Execute() + if err := rootCmd.Execute(); err != nil { + log.Fatalln(err) + } } func runE(cmd *cobra.Command, args []string) error { @@ -84,10 +87,16 @@ func runWatch(cmd *cobra.Command, args []string) error { select { case <-cmd.Context().Done(): return nil - case err := <-errorChannel: - logrus.WithError(err).Errorln("Received from config watcher") + case err, open := <-errorChannel: + if !open { + return fmt.Errorf("error channel has been closed") + } + logrus.WithError(err).Errorln("received from config watcher") case <-timer.C: - writeConfig(cachedConfig, dest) + err = writeConfig(cachedConfig, dest) + if err != nil { + logrus.WithError(err).Errorln("failed to write config") + } case config := <-configChannel: cachedConfig = config timer.Reset(waitFor) @@ -105,18 +114,23 @@ func writeConfig(config *domain.Config, dest string) error { case len(dest) > 0: dirname := filepath.Dir(dest) + // #nosec G301 err := os.MkdirAll(dirname, 0755) if err != nil { return err } + // #nosec G304 f, err := os.Create(dest) if err != nil { return err } defer func() { _ = f.Close() }() - f.WriteString(config.API.Token) + _, err = f.WriteString(config.API.Token) + if err != nil { + return err + } } return nil diff --git a/cmd/healarr/main.go b/cmd/healarr/main.go index bdba94f..f2584ee 100644 --- a/cmd/healarr/main.go +++ b/cmd/healarr/main.go @@ -3,6 +3,7 @@ package main import ( "context" "fmt" + "log" "time" "git.cryptic.systems/volker.raschek/tarr/pkg/config" @@ -95,7 +96,10 @@ healarr sonarr https://sonarr.example.com:8443 --api-token my-token`, rootCmd.PersistentFlags().Bool("insecure", false, "Trust insecure TLS certificates") rootCmd.PersistentFlags().Duration("timeout", time.Minute, "Timeout") - rootCmd.Execute() + err := rootCmd.Execute() + if err != nil { + log.Fatalln(err) + } } func runBazarrE(cmd *cobra.Command, args []string) error { @@ -152,7 +156,7 @@ func runE(cmd *cobra.Command, args []string, queryKey string) error { switch { case len(apiToken) <= 0 && len(configPath) <= 0: - return fmt.Errorf("At least --api-token oder --config must be defined") + return fmt.Errorf("at least --api-token oder --config must be defined") case len(apiToken) > 0 && len(configPath) <= 0: err = health.NewReadinessProbe(args[0]). QueryAdd(queryKey, apiToken). @@ -175,7 +179,7 @@ func runE(cmd *cobra.Command, args []string, queryKey string) error { return err } default: - return fmt.Errorf("Neither --api-token nor --config can be used at the same time.") + return fmt.Errorf("neither --api-token nor --config can be used at the same time") } return nil diff --git a/pkg/config/config.go b/pkg/config/config.go index 6b8b391..3b35dd1 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -46,11 +46,12 @@ type YAMLConfig struct { // Read reads the config struct from a file. The decoding format will be determined by the file extension like // `xml` or `yaml`. func ReadConfig(name string) (*domain.Config, error) { + // #nosec G304 f, err := os.Open(name) if err != nil { return nil, err } - defer f.Close() + defer func() { _ = f.Close() }() switch { case strings.HasSuffix(name, "xml"): @@ -58,7 +59,7 @@ func ReadConfig(name string) (*domain.Config, error) { case strings.HasSuffix(name, "yml") || strings.HasSuffix(name, "yaml"): return readYAMLConfig(f) default: - return nil, fmt.Errorf("Unsupported file extension") + return nil, fmt.Errorf("unsupported file extension") } } @@ -97,8 +98,8 @@ func readYAMLConfig(r io.Reader) (*domain.Config, error) { } func WatchConfig(ctx context.Context, name string) (<-chan *domain.Config, <-chan error) { - configChannel := make(chan *domain.Config, 0) - errorChannel := make(chan error, 0) + configChannel := make(chan *domain.Config) + errorChannel := make(chan error) go func() { wait := time.Second * 3 @@ -110,14 +111,18 @@ func WatchConfig(ctx context.Context, name string) (<-chan *domain.Config, <-cha errorChannel <- err return } - watcher.Add(name) + err = watcher.Add(name) + if err != nil { + errorChannel <- err + return + } for { select { case <-ctx.Done(): close(configChannel) close(errorChannel) - break + return case event, open := <-watcher.Events: if !open { errorChannel <- fmt.Errorf("FSWatcher closed channel: %w", err) @@ -145,11 +150,12 @@ func WatchConfig(ctx context.Context, name string) (<-chan *domain.Config, <-cha // WriteConfig writes the config struct into the file. The encoding format will be determined by the file extension like // `xml` or `yaml`. func WriteConfig(name string, config *domain.Config) error { + // #nosec G304 f, err := os.Create(name) if err != nil { return err } - defer f.Close() + defer func() { _ = f.Close() }() switch { case strings.HasSuffix(name, "xml"): @@ -157,13 +163,13 @@ func WriteConfig(name string, config *domain.Config) error { case strings.HasSuffix(name, "yml") || strings.HasSuffix(name, "yaml"): return writeYAMLConfig(f, config) default: - return fmt.Errorf("Unsupported file extension") + return fmt.Errorf("unsupported file extension") } } func writeXMLConfig(w io.Writer, config *domain.Config) error { xmlEncoder := xml.NewEncoder(w) - defer xmlEncoder.Close() + defer func() { _ = xmlEncoder.Close() }() xmlConfig := &XMLConfig{ APIToken: config.API.Token, @@ -180,7 +186,7 @@ func writeXMLConfig(w io.Writer, config *domain.Config) error { func writeYAMLConfig(w io.Writer, config *domain.Config) error { yamlEncoder := yaml.NewEncoder(w) - defer yamlEncoder.Close() + defer func() { _ = yamlEncoder.Close() }() yamlConfig := &YAMLConfig{ Auth: YAMLConfigAuth{ diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 3417fee..517ca16 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -24,6 +24,7 @@ func TestReadWriteConfig_XML(t *testing.T) { t.Cleanup(func() { _ = os.RemoveAll(tmpDir) }) expectedXMLConfigName := filepath.Join(tmpDir, "expected_config.xml") + // #nosec G304 f, err := os.Create(expectedXMLConfigName) require.NoError(err) @@ -38,6 +39,7 @@ func TestReadWriteConfig_XML(t *testing.T) { err = config.WriteConfig(actualXMLConfigName, actualConfig) require.NoError(err) + // #nosec G304 b, err := os.ReadFile(actualXMLConfigName) require.NoError(err) require.Equal(expectedXMLConfig, string(b)) @@ -51,6 +53,7 @@ func TestReadWriteConfig_YAML(t *testing.T) { t.Cleanup(func() { _ = os.RemoveAll(tmpDir) }) expectedYAMLConfigName := filepath.Join(tmpDir, "expected_config.yaml") + // #nosec G304 f, err := os.Create(expectedYAMLConfigName) require.NoError(err) @@ -65,6 +68,7 @@ func TestReadWriteConfig_YAML(t *testing.T) { err = config.WriteConfig(actualYAMLConfigName, actualConfig) require.NoError(err) + // #nosec G304 b, err := os.ReadFile(actualYAMLConfigName) require.NoError(err) require.Equal(expectedYAMLConfig, string(b)) diff --git a/pkg/health/health.go b/pkg/health/health.go index e05ed27..23798eb 100644 --- a/pkg/health/health.go +++ b/pkg/health/health.go @@ -9,8 +9,8 @@ import ( "net/url" ) -var ErrNoAPIToken error = errors.New("No API token defined") -var ErrNoURL error = errors.New("No API token defined") +var ErrNoAPIToken error = errors.New("no API token defined") +var ErrNoURL error = errors.New("no API token defined") type ReadinessProbe struct { additionalQueryValues url.Values @@ -40,6 +40,7 @@ func (rp *ReadinessProbe) Run(ctx context.Context) error { httpClient := &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ + // #nosec G402 InsecureSkipVerify: rp.insecure, }, }, @@ -64,7 +65,7 @@ func (rp *ReadinessProbe) Run(ctx context.Context) error { } if resp.StatusCode != http.StatusOK { - return fmt.Errorf("Received unexpected HTTP status code %v", resp.StatusCode) + return fmt.Errorf("received unexpected HTTP status code %v", resp.StatusCode) } return nil