jira-cli/internal/cmd/root/root.go

189 lines
4.8 KiB
Go

package root
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/ankitpokhrel/jira-cli/internal/cmd/board"
"github.com/ankitpokhrel/jira-cli/internal/cmd/completion"
"github.com/ankitpokhrel/jira-cli/internal/cmd/epic"
initCmd "github.com/ankitpokhrel/jira-cli/internal/cmd/init"
"github.com/ankitpokhrel/jira-cli/internal/cmd/issue"
"github.com/ankitpokhrel/jira-cli/internal/cmd/man"
"github.com/ankitpokhrel/jira-cli/internal/cmd/me"
"github.com/ankitpokhrel/jira-cli/internal/cmd/open"
"github.com/ankitpokhrel/jira-cli/internal/cmd/project"
"github.com/ankitpokhrel/jira-cli/internal/cmd/serverinfo"
"github.com/ankitpokhrel/jira-cli/internal/cmd/sprint"
"github.com/ankitpokhrel/jira-cli/internal/cmd/version"
"github.com/ankitpokhrel/jira-cli/internal/cmdutil"
jiraConfig "github.com/ankitpokhrel/jira-cli/internal/config"
"github.com/ankitpokhrel/jira-cli/pkg/jira"
"github.com/ankitpokhrel/jira-cli/pkg/netrc"
"github.com/zalando/go-keyring"
)
const (
jiraCLIHelpLink = "https://github.com/ankitpokhrel/jira-cli#getting-started"
jiraAPITokenLink = "https://id.atlassian.com/manage-profile/security/api-tokens"
)
var (
config string
debug bool
)
func init() {
cobra.OnInitialize(func() {
if config != "" {
viper.SetConfigFile(config)
} else {
home, err := cmdutil.GetConfigHome()
if err != nil {
cmdutil.Failed("Error: %s", err)
return
}
viper.AddConfigPath(fmt.Sprintf("%s/%s", home, jiraConfig.Dir))
viper.SetConfigName(jiraConfig.FileName)
viper.SetConfigType(jiraConfig.FileType)
}
viper.AutomaticEnv()
viper.SetEnvPrefix("jira")
if err := viper.ReadInConfig(); err == nil && debug {
fmt.Printf("Using config file: %s\n", viper.ConfigFileUsed())
}
})
}
// NewCmdRoot is a root command.
func NewCmdRoot() *cobra.Command {
cmd := cobra.Command{
Use: "jira <command> <subcommand>",
Short: "Interactive Jira CLI",
Long: "Interactive Jira command line.",
RunE: func(cmd *cobra.Command, args []string) error {
return cmd.Help()
},
PersistentPreRun: func(cmd *cobra.Command, args []string) {
subCmd := cmd.Name()
if !cmdRequireToken(subCmd) {
return
}
// mTLS doesn't need Jira API Token.
if viper.GetString("auth_type") != string(jira.AuthTypeMTLS) {
checkForJiraToken(viper.GetString("server"), viper.GetString("login"))
}
configFile := viper.ConfigFileUsed()
if !jiraConfig.Exists(configFile) {
cmdutil.Failed("Missing configuration file.\nRun 'jira init' to configure the tool.")
}
},
}
configHome, err := cmdutil.GetConfigHome()
if err != nil {
cmdutil.Failed("Error: %s", err)
}
cmd.PersistentFlags().StringVarP(
&config, "config", "c", "",
fmt.Sprintf("Config file (default is %s/%s/%s.yml)", configHome, jiraConfig.Dir, jiraConfig.FileName),
)
cmd.PersistentFlags().StringP(
"project", "p", "",
fmt.Sprintf(
"Jira project to look into (defaults to %s/%s/%s.yml)",
configHome, jiraConfig.Dir, jiraConfig.FileName,
),
)
cmd.PersistentFlags().BoolVar(&debug, "debug", false, "Turn on debug output")
cmd.SetHelpFunc(helpFunc)
_ = viper.BindPFlag("config", cmd.PersistentFlags().Lookup("config"))
_ = viper.BindPFlag("project.key", cmd.PersistentFlags().Lookup("project"))
_ = viper.BindPFlag("debug", cmd.PersistentFlags().Lookup("debug"))
addChildCommands(&cmd)
return &cmd
}
func addChildCommands(cmd *cobra.Command) {
cmd.AddCommand(
initCmd.NewCmdInit(),
issue.NewCmdIssue(),
epic.NewCmdEpic(),
sprint.NewCmdSprint(),
board.NewCmdBoard(),
project.NewCmdProject(),
open.NewCmdOpen(),
me.NewCmdMe(),
serverinfo.NewCmdServerInfo(),
completion.NewCmdCompletion(),
version.NewCmdVersion(),
man.NewCmdMan(),
)
}
func cmdRequireToken(cmd string) bool {
allowList := []string{
"init",
"help",
"jira",
"version",
"completion",
"man",
}
for _, item := range allowList {
if item == cmd {
return false
}
}
return true
}
func checkForJiraToken(server string, login string) {
if os.Getenv("JIRA_API_TOKEN") != "" {
return
}
netrcConfig, _ := netrc.Read(server, login)
if netrcConfig != nil {
return
}
secret, _ := keyring.Get("jira-cli", login)
if secret != "" {
return
}
msg := fmt.Sprintf(`The tool needs a Jira API token to function.
For cloud server: you can generate the token using this link: %s
For local server: you can use the password you use to log in to Jira for basic auth or get a token from your Jira profile for PAT.
After generating the token, you can either:
- Export API token to your shell as a JIRA_API_TOKEN env variable
- Or, you can use a .netrc file to define required machine details
Once you are done with the above steps, run 'jira init' to generate the config if you haven't already.
For more details, see: %s
`, jiraAPITokenLink, jiraCLIHelpLink)
cmdutil.Warn(msg)
os.Exit(1)
}