2023-04-22 21:41:28 -04:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
2023-04-25 20:32:08 -04:00
|
|
|
"context"
|
2023-04-22 21:41:28 -04:00
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"github.com/mobyvb/pull-pal/pullpal"
|
|
|
|
"github.com/mobyvb/pull-pal/vc"
|
2023-05-08 20:14:19 -04:00
|
|
|
"github.com/sashabaranov/go-openai"
|
2023-04-25 20:32:08 -04:00
|
|
|
"go.uber.org/zap"
|
2023-04-24 19:49:10 -04:00
|
|
|
|
2023-04-22 21:41:28 -04:00
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/spf13/viper"
|
|
|
|
)
|
|
|
|
|
2023-04-24 19:49:10 -04:00
|
|
|
// todo: some of this config definition/usage can be moved to other packages
|
|
|
|
type config struct {
|
|
|
|
// bot credentials + github info
|
|
|
|
selfHandle string
|
|
|
|
selfEmail string
|
|
|
|
githubToken string
|
2023-04-25 20:32:08 -04:00
|
|
|
openAIToken string
|
2023-04-24 19:49:10 -04:00
|
|
|
|
|
|
|
// remote repo info
|
|
|
|
repoDomain string
|
|
|
|
repoHandle string
|
|
|
|
repoName string
|
|
|
|
|
|
|
|
// local paths
|
|
|
|
localRepoPath string
|
|
|
|
|
|
|
|
// program settings
|
|
|
|
promptToClipboard bool
|
|
|
|
usersToListenTo []string
|
|
|
|
requiredIssueLabels []string
|
|
|
|
}
|
|
|
|
|
|
|
|
func getConfig() config {
|
|
|
|
return config{
|
|
|
|
selfHandle: viper.GetString("handle"),
|
|
|
|
selfEmail: viper.GetString("email"),
|
|
|
|
githubToken: viper.GetString("github-token"),
|
2023-04-25 20:32:08 -04:00
|
|
|
openAIToken: viper.GetString("open-ai-token"),
|
2023-04-24 19:49:10 -04:00
|
|
|
|
|
|
|
repoDomain: viper.GetString("repo-domain"),
|
|
|
|
repoHandle: viper.GetString("repo-handle"),
|
|
|
|
repoName: viper.GetString("repo-name"),
|
|
|
|
|
|
|
|
localRepoPath: viper.GetString("local-repo-path"),
|
|
|
|
|
|
|
|
promptToClipboard: viper.GetBool("prompt-to-clipboard"),
|
|
|
|
usersToListenTo: viper.GetStringSlice("users-to-listen-to"),
|
|
|
|
requiredIssueLabels: viper.GetStringSlice("required-issue-labels"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-25 20:32:08 -04:00
|
|
|
func getPullPal(ctx context.Context, cfg config) (*pullpal.PullPal, error) {
|
2023-05-04 20:01:46 -04:00
|
|
|
// TODO figure out debug logging
|
2023-05-02 20:07:48 -04:00
|
|
|
log, err := zap.NewProduction()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
//log := zap.L()
|
2023-04-25 20:32:08 -04:00
|
|
|
|
|
|
|
author := vc.Author{
|
|
|
|
Email: cfg.selfEmail,
|
|
|
|
Handle: cfg.selfHandle,
|
|
|
|
Token: cfg.githubToken,
|
|
|
|
}
|
|
|
|
repo := vc.Repository{
|
|
|
|
LocalPath: cfg.localRepoPath,
|
|
|
|
HostDomain: cfg.repoDomain,
|
|
|
|
Name: cfg.repoName,
|
|
|
|
Owner: vc.Author{
|
|
|
|
Handle: cfg.repoHandle,
|
|
|
|
},
|
|
|
|
}
|
2023-05-02 20:07:48 -04:00
|
|
|
listIssueOptions := vc.ListIssueOptions{
|
|
|
|
Handles: cfg.usersToListenTo,
|
|
|
|
Labels: cfg.requiredIssueLabels,
|
|
|
|
}
|
2023-05-08 20:14:19 -04:00
|
|
|
// TODO make model configurable
|
|
|
|
p, err := pullpal.NewPullPal(ctx, log.Named("pullpal"), listIssueOptions, author, repo, openai.GPT4, cfg.openAIToken)
|
2023-04-25 20:32:08 -04:00
|
|
|
|
|
|
|
return p, err
|
|
|
|
}
|
|
|
|
|
2023-04-22 21:41:28 -04:00
|
|
|
// rootCmd represents the base command when called without any subcommands
|
|
|
|
var rootCmd = &cobra.Command{
|
2023-05-04 20:01:46 -04:00
|
|
|
Short: "run an automated digital assitant to monitor and make code changes to a github repository",
|
2023-04-22 21:41:28 -04:00
|
|
|
Run: func(cmd *cobra.Command, args []string) {
|
2023-04-24 19:49:10 -04:00
|
|
|
cfg := getConfig()
|
2023-04-22 21:41:28 -04:00
|
|
|
|
2023-04-25 20:32:08 -04:00
|
|
|
p, err := getPullPal(cmd.Context(), cfg)
|
2023-04-22 21:41:28 -04:00
|
|
|
if err != nil {
|
2023-04-22 22:44:44 -04:00
|
|
|
fmt.Println("error creating new pull pal", err)
|
2023-04-22 21:41:28 -04:00
|
|
|
return
|
|
|
|
}
|
2023-04-22 22:44:44 -04:00
|
|
|
fmt.Println("Successfully initialized pull pal")
|
|
|
|
|
2023-05-04 20:01:46 -04:00
|
|
|
err = p.Run()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("error running", err)
|
|
|
|
return
|
2023-04-22 21:41:28 -04: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() {
|
|
|
|
err := rootCmd.Execute()
|
|
|
|
if err != nil {
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var cfgFile string
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
cobra.OnInitialize(initConfig)
|
|
|
|
|
|
|
|
// TODO make config values requried
|
|
|
|
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.pull-pal.yaml)")
|
|
|
|
|
|
|
|
rootCmd.PersistentFlags().StringP("handle", "u", "HANDLE", "handle to use for version control actions")
|
|
|
|
rootCmd.PersistentFlags().StringP("email", "e", "EMAIL", "email to use for version control actions")
|
2023-04-24 19:49:10 -04:00
|
|
|
rootCmd.PersistentFlags().StringP("github-token", "t", "GITHUB TOKEN", "token for authenticating Github actions")
|
2023-04-25 20:32:08 -04:00
|
|
|
rootCmd.PersistentFlags().StringP("open-ai-token", "k", "OPENAI TOKEN", "token for authenticating OpenAI")
|
2023-04-24 19:49:10 -04:00
|
|
|
|
2023-04-22 21:41:28 -04:00
|
|
|
rootCmd.PersistentFlags().StringP("repo-domain", "d", "github.com", "domain for version control server")
|
|
|
|
rootCmd.PersistentFlags().StringP("repo-handle", "o", "REPO-HANDLE", "handle of repository's owner on version control server")
|
|
|
|
rootCmd.PersistentFlags().StringP("repo-name", "n", "REPO-NAME", "name of repository on version control server")
|
2023-04-24 19:49:10 -04:00
|
|
|
|
2023-05-04 20:01:46 -04:00
|
|
|
rootCmd.PersistentFlags().StringP("local-repo-path", "l", "/tmp/pullpallrepo", "local path to check out ephemeral repository in")
|
2023-04-22 21:41:28 -04:00
|
|
|
|
2023-04-24 19:49:10 -04:00
|
|
|
rootCmd.PersistentFlags().StringSliceP("users-to-listen-to", "a", []string{}, "a list of Github users that Pull Pal will respond to")
|
|
|
|
rootCmd.PersistentFlags().StringSliceP("required-issue-labels", "i", []string{}, "a list of labels that are required for Pull Pal to select an issue")
|
|
|
|
|
2023-04-22 21:41:28 -04:00
|
|
|
viper.BindPFlag("handle", rootCmd.PersistentFlags().Lookup("handle"))
|
|
|
|
viper.BindPFlag("email", rootCmd.PersistentFlags().Lookup("email"))
|
2023-04-24 19:49:10 -04:00
|
|
|
viper.BindPFlag("github-token", rootCmd.PersistentFlags().Lookup("github-token"))
|
2023-04-25 20:32:08 -04:00
|
|
|
viper.BindPFlag("open-ai-token", rootCmd.PersistentFlags().Lookup("open-ai-token"))
|
2023-04-24 19:49:10 -04:00
|
|
|
|
2023-04-22 21:41:28 -04:00
|
|
|
viper.BindPFlag("repo-domain", rootCmd.PersistentFlags().Lookup("repo-domain"))
|
|
|
|
viper.BindPFlag("repo-handle", rootCmd.PersistentFlags().Lookup("repo-handle"))
|
|
|
|
viper.BindPFlag("repo-name", rootCmd.PersistentFlags().Lookup("repo-name"))
|
2023-04-24 19:49:10 -04:00
|
|
|
|
2023-04-22 21:41:28 -04:00
|
|
|
viper.BindPFlag("local-repo-path", rootCmd.PersistentFlags().Lookup("local-repo-path"))
|
2023-04-24 19:49:10 -04:00
|
|
|
|
|
|
|
viper.BindPFlag("users-to-listen-to", rootCmd.PersistentFlags().Lookup("users-to-listen-to"))
|
|
|
|
viper.BindPFlag("required-issue-labels", rootCmd.PersistentFlags().Lookup("required-issue-labels"))
|
2023-04-22 21:41:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func initConfig() {
|
|
|
|
if cfgFile != "" {
|
|
|
|
fmt.Println("cfg file exists")
|
|
|
|
// 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 ".cobra" (without extension).
|
|
|
|
viper.AddConfigPath(home)
|
|
|
|
viper.SetConfigType("yaml")
|
|
|
|
viper.SetConfigName(".pull-pal")
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO figure out how to get env variables to work
|
|
|
|
viper.SetEnvPrefix("pullpal")
|
|
|
|
viper.AutomaticEnv()
|
|
|
|
|
|
|
|
if err := viper.ReadInConfig(); err == nil {
|
|
|
|
fmt.Println("Using config file:", viper.ConfigFileUsed())
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|