git-project-manager/cmd/root.go

130 lines
3.5 KiB
Go
Raw Normal View History

2023-12-04 21:53:01 +00:00
package cmd
import (
2023-12-05 21:56:47 +00:00
"context"
2023-12-04 21:53:01 +00:00
"os"
2023-12-05 21:56:47 +00:00
"os/signal"
"strings"
2023-12-04 21:53:01 +00:00
2023-12-07 17:08:56 +00:00
"github.com/pterm/pterm"
2023-12-04 21:53:01 +00:00
"github.com/spf13/cobra"
"github.com/spf13/viper"
2023-12-05 21:56:47 +00:00
"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/config"
2023-12-04 21:53:01 +00:00
)
2023-12-05 21:56:47 +00:00
var conf config.Config
2023-12-07 17:08:56 +00:00
var plog *pterm.Logger
2023-12-05 21:56:47 +00:00
2023-12-04 21:53:01 +00:00
var rootCmd = &cobra.Command{
2023-12-08 21:52:26 +00:00
Use: "gitlab-project-manager",
Short: "Find and use GitLab projects locally",
Long: rootCmdLong,
2023-12-05 21:56:47 +00:00
PersistentPreRun: initRootCmd,
}
// Hook traversal is enabled, so this will be run for all
// sub-commands regardless of their registered pre-hooks
func initRootCmd(cmd *cobra.Command, args []string) {
initProjectPath(cmd, args)
2023-12-04 21:53:01 +00:00
}
// 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() {
2023-12-05 21:56:47 +00:00
ctx, cncl := signal.NotifyContext(context.Background(), os.Kill, os.Interrupt)
defer cncl()
err := rootCmd.ExecuteContext(ctx)
2023-12-04 21:53:01 +00:00
if err != nil {
2023-12-07 17:08:56 +00:00
plog.Error("Failed to execute command", plog.Args("err", err))
2023-12-04 21:53:01 +00:00
os.Exit(1)
}
}
func init() {
2023-12-05 21:56:47 +00:00
cobra.EnableTraverseRunHooks = true
2023-12-04 21:53:01 +00:00
cobra.OnInitialize(initConfig)
2023-12-05 21:56:47 +00:00
rootCmd.PersistentFlags().String("config", "",
"config file (default is $HOME/.gitlab-project-manager.yaml)")
rootCmd.PersistentFlags().String("gitlabHost", defGitlabHost,
"GitLab Hostname (e.g. gitlab.com)")
rootCmd.PersistentFlags().String("gitlabToken", "",
"GitLab Tokenname (e.g. gitlab.com)")
rootCmd.PersistentFlags().String("projectPath", defProjectsPath,
"Sets a path for local clones of projects")
rootCmd.PersistentFlags().String("logLevel", defLogLevel,
"Default log level -- info, warn, error, debug")
2023-12-04 21:53:01 +00:00
viper.BindPFlags(rootCmd.PersistentFlags())
}
// initConfig reads in config file and ENV variables if set.
func initConfig() {
cfgFile := viper.GetString("config")
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := os.UserHomeDir()
cobra.CheckErr(err)
// Search config in home directory with name ".gitlab-project-manager" (without extension).
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".gitlab-project-manager")
}
2023-12-05 21:56:47 +00:00
viper.AutomaticEnv()
viper.ReadInConfig()
2023-12-04 21:53:01 +00:00
2023-12-05 21:56:47 +00:00
checkConfigPerms(viper.ConfigFileUsed()) // Abort on world-readable config
2023-12-07 17:08:56 +00:00
// Configure pretty logger
plog = pterm.DefaultLogger.WithLevel(getPtermLogLevel(viper.GetString("logLevel")))
if plog.Level == pterm.LogLevelDebug {
pterm.EnableDebugMessages()
}
2023-12-05 21:56:47 +00:00
// Load into struct to not be so darn pythonic, retrieving
// settings by untyped string "name"
if err := viper.Unmarshal(&conf); err != nil {
2023-12-07 17:08:56 +00:00
plog.Error("Failed loading config", plog.Args("err", err))
2023-12-05 21:56:47 +00:00
}
2023-12-07 17:08:56 +00:00
plog.Debug("Configuration loaded", plog.Args("conf", conf))
2023-12-05 21:56:47 +00:00
}
2023-12-07 17:08:56 +00:00
func getPtermLogLevel(level string) pterm.LogLevel {
var pLevel pterm.LogLevel
2023-12-05 21:56:47 +00:00
switch strings.ToLower(level) {
case "error":
2023-12-07 17:08:56 +00:00
pLevel = pterm.LogLevelError
2023-12-05 21:56:47 +00:00
case "warn":
2023-12-07 17:08:56 +00:00
pLevel = pterm.LogLevelWarn
2023-12-05 21:56:47 +00:00
case "info":
2023-12-07 17:08:56 +00:00
pLevel = pterm.LogLevelInfo
2023-12-05 21:56:47 +00:00
case "debug":
2023-12-07 17:08:56 +00:00
pLevel = pterm.LogLevelDebug
2023-12-05 21:56:47 +00:00
default:
2023-12-07 17:08:56 +00:00
pLevel = pterm.LogLevelInfo
2023-12-05 21:56:47 +00:00
}
2023-12-07 17:08:56 +00:00
return pLevel
2023-12-05 21:56:47 +00:00
}
// Don't allow world-readable configuration
func checkConfigPerms(file string) {
stat, err := os.Stat(file)
if err != nil {
2023-12-07 17:08:56 +00:00
plog.Error("Failure reading configuration", plog.Args("err", err))
2023-12-05 21:56:47 +00:00
return
}
if stat.Mode().Perm()&0004 == 0004 {
2023-12-07 17:08:56 +00:00
plog.Error("Configuration is world-readable. Recomment 0400.",
plog.Args("mode", stat.Mode().String()))
2023-12-05 21:56:47 +00:00
os.Exit(1)
2023-12-04 21:53:01 +00:00
}
}