Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Remove all usage of init() and global command objects #91

Merged
merged 3 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .golangci.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
[linters]
enable = ["cyclop", "gocognit", "gosec", "nilnil", "prealloc", "zerologlint"]
enable = [
"cyclop",
"gochecknoinits",
"gocognit",
"gosec",
"nilnil",
"prealloc",
"zerologlint",
]
JoseAngel1196 marked this conversation as resolved.
Show resolved Hide resolved
78 changes: 42 additions & 36 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,61 @@

import (
"github.com/rs/zerolog"
"github.com/underdog-tech/vulnbot/config"
"github.com/underdog-tech/vulnbot/logger"

"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "vulnbot",
Short: "Vulnbot: Your all-in-one security alert manager.",
Long: `Vulnbot is a comprehensive security alert manager designed to keep your code safe from vulnerabilities.

It is a versatile bot that can seamlessly integrate with multiple data sources, such as GitHub, and soon Phylum,
Vulnbot empowers developers and security teams to efficiently manage and respond to security threats.`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
quiet, _ := cmd.Flags().GetBool("quiet")
verbosity, _ := cmd.Flags().GetCount("verbose")

if quiet {
logger.SetLogLevel(zerolog.Disabled)
} else if verbosity > 0 {
if verbosity > 3 {
verbosity = 3
func NewRootCommand() *cobra.Command {
rootCmd := &cobra.Command{
Use: "vulnbot",
Short: "Vulnbot: Your all-in-one security alert manager.",
Long: `Vulnbot is a comprehensive security alert manager designed to keep your code safe from vulnerabilities.

It is a versatile bot that can seamlessly integrate with multiple data sources, such as GitHub, and soon Phylum,
Vulnbot empowers developers and security teams to efficiently manage and respond to security threats.`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
quiet, _ := cmd.Flags().GetBool("quiet")
verbosity, _ := cmd.Flags().GetCount("verbose")

if quiet {
logger.SetLogLevel(zerolog.Disabled)
} else if verbosity > 0 {
if verbosity > 3 {
verbosity = 3
}
logLevel := logger.DEFAULT_LOG_LEVEL - zerolog.Level(verbosity)
logger.SetLogLevel(logLevel)
} else {
logger.SetLogLevel(logger.DEFAULT_LOG_LEVEL)

Check warning on line 33 in cmd/root.go

View check run for this annotation

Codecov / codecov/patch

cmd/root.go#L21-L33

Added lines #L21 - L33 were not covered by tests
}
logLevel := logger.DEFAULT_LOG_LEVEL - zerolog.Level(verbosity)
logger.SetLogLevel(logLevel)
} else {
logger.SetLogLevel(logger.DEFAULT_LOG_LEVEL)
}
},
},
}
// Add all subcommand(s)
rootCmd.AddCommand(NewScanCommand())

// Set up flags for the command(s)
pflags := rootCmd.PersistentFlags()
pflags.StringP("config", "c", "config.toml", "Config file path.")
pflags.StringSliceP("reporters", "r", []string{"slack", "console"}, "Specify a list of reporters for reporting vulnerabilities.")
pflags.BoolP("quiet", "q", false, "Suppress all console output. (Mutually exclusive with 'verbose'.)")
pflags.CountP("verbose", "v", "More verbose output. Specifying multiple times increases verbosity. (Mutually exclusive with 'quiet'.)")
rootCmd.MarkFlagsMutuallyExclusive("verbose", "quiet")

// Set up Viper config
_ = viper.BindPFlags(pflags)
config.SetConfigDefaults()

return rootCmd
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
log := logger.Get()
err := rootCmd.Execute()
if err != nil {
if err := NewRootCommand().Execute(); err != nil {

Check warning on line 59 in cmd/root.go

View check run for this annotation

Codecov / codecov/patch

cmd/root.go#L59

Added line #L59 was not covered by tests
log.Fatal().Err(err).Msg("Failed to execute command.")
}
}

func init() {
persistent := rootCmd.PersistentFlags()
persistent.StringP("config", "c", "config.toml", "Config file path.")
persistent.StringSliceP("reporters", "r", []string{"slack", "console"}, "Specify a list of reporters for reporting vulnerabilities.")
persistent.BoolP("quiet", "q", false, "Suppress all console output. (Mutually exclusive with 'verbose'.)")
persistent.CountP("verbose", "v", "More verbose output. Specifying multiple times increases verbosity. (Mutually exclusive with 'quiet'.)")

_ = viper.BindPFlags(persistent)
rootCmd.MarkFlagsMutuallyExclusive("verbose", "quiet")
}
18 changes: 18 additions & 0 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package cmd_test

import (
"testing"

"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/underdog-tech/vulnbot/cmd"
)

func TestNewRootCommand(t *testing.T) {
// Mostly just ensure nothing errors out.
c := cmd.NewRootCommand()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!


assert.IsType(t, &cobra.Command{}, c)
assert.Equal(t, "vulnbot", c.Use)
assert.True(t, c.HasAvailableSubCommands())
}
20 changes: 9 additions & 11 deletions cmd/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@ import (
"github.com/spf13/cobra"
)

// scanCmd represents the scan command
var scanCmd = &cobra.Command{
Use: "scan",
Short: "",
Long: ``,
Run: internal.Scan,
Aliases: []string{"s", "scan"},
}

func init() {
rootCmd.AddCommand(scanCmd)
// NewScanCommand returns a Cobra command for running scans
func NewScanCommand() *cobra.Command {
return &cobra.Command{
Use: "scan",
Short: "",
Long: ``,
Run: internal.Scan,
Aliases: []string{"s", "scan"},
}
}
13 changes: 8 additions & 5 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,21 @@ func fileExists(fname string) bool {
return true
}

func GetUserConfig(configFile string) (Config, error) {
log := logger.Get()

userCfg := Config{}
func SetConfigDefaults() {
cfg := Config{}

// Use reflection to register all config fields in Viper to set up defaults
cfgFields := reflect.ValueOf(userCfg)
cfgFields := reflect.ValueOf(cfg)
cfgType := cfgFields.Type()

for i := 0; i < cfgFields.NumField(); i++ {
viper.SetDefault(cfgType.Field(i).Name, cfgFields.Field(i).Interface())
}
}

func GetUserConfig(configFile string) (Config, error) {
log := logger.Get()
userCfg := Config{}

// Load the main config file
if !fileExists(configFile) {
Expand Down
2 changes: 2 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ func TestGetUserConfigFromFile(t *testing.T) {
}

func TestGetUserConfigFromEnv(t *testing.T) {
config.SetConfigDefaults()

t.Setenv("VULNBOT_REPORTERS", "slack")
t.Setenv("VULNBOT_GITHUB_ORG", "hitchhikers")
// This should override the config file
Expand Down