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"
2023-05-12 00:59:21 -04:00
"time"
2023-04-22 21:41:28 -04:00
"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
2023-05-12 00:59:21 -04:00
repos [ ] string
2023-04-24 19:49:10 -04:00
// local paths
localRepoPath string
// program settings
usersToListenTo [ ] string
requiredIssueLabels [ ] string
2023-05-12 00:59:21 -04:00
waitDuration time . Duration
2023-04-24 19:49:10 -04:00
}
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
2023-05-12 00:59:21 -04:00
repos : viper . GetStringSlice ( "repos" ) ,
2023-04-24 19:49:10 -04:00
localRepoPath : viper . GetString ( "local-repo-path" ) ,
usersToListenTo : viper . GetStringSlice ( "users-to-listen-to" ) ,
requiredIssueLabels : viper . GetStringSlice ( "required-issue-labels" ) ,
2023-05-12 00:59:21 -04:00
waitDuration : viper . GetDuration ( "wait-duration" ) ,
2023-04-24 19:49:10 -04:00
}
}
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 ,
}
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
2023-05-12 00:59:21 -04:00
ppCfg := pullpal . Config {
WaitDuration : cfg . waitDuration ,
LocalRepoPath : cfg . localRepoPath ,
Repos : cfg . repos ,
Self : author ,
ListIssueOptions : listIssueOptions ,
// TODO configurable model
Model : openai . GPT4 ,
OpenAIToken : cfg . openAIToken ,
}
p , err := pullpal . NewPullPal ( ctx , log . Named ( "pullpal" ) , ppCfg )
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-05-12 00:59:21 -04:00
rootCmd . PersistentFlags ( ) . StringSliceP ( "repos" , "r" , [ ] string { } , "a list of git repositories that Pull Pal will monitor" )
2023-04-24 19:49:10 -04:00
2023-05-12 00:59:21 -04:00
rootCmd . PersistentFlags ( ) . StringP ( "local-repo-path" , "l" , "/tmp/pullpalrepo" , "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-05-12 00:59:21 -04:00
rootCmd . PersistentFlags ( ) . Duration ( "wait-time" , 30 * time . Second , "the amount of time Pull Pal should wait when no issues or comments are found to address" )
2023-04-24 19:49:10 -04:00
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-05-12 00:59:21 -04:00
viper . BindPFlag ( "repos" , rootCmd . PersistentFlags ( ) . Lookup ( "repos" ) )
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-05-12 00:59:21 -04:00
viper . BindPFlag ( "wait-time" , rootCmd . PersistentFlags ( ) . Lookup ( "wait-time" ) )
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 ( ) )
}
}