Skip to content

Commit f21dfde

Browse files
venjiangwoorui
andauthored
refactor: cli (#1092)
# Description refactor CLI ## gen - Replace language-based configuration (`lang`) with runtime-based configuration (`runtime`), enabling support for multiple runtime environments like "node" and "go" - improve error handling, refactor serverless function registration, and enhance build and run processes for better clarity and usability. --------- Co-authored-by: woorui <[email protected]>
1 parent 4436f07 commit f21dfde

File tree

14 files changed

+145
-209
lines changed

14 files changed

+145
-209
lines changed

cli/build.go

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,32 +26,28 @@ import (
2626

2727
// buildCmd represents the build command
2828
var buildCmd = &cobra.Command{
29-
Use: "build [flags] app.go",
29+
Use: "build [flags]",
3030
Short: "Build the YoMo Stream Function",
3131
Long: "Build the YoMo Stream Function",
3232
Run: func(cmd *cobra.Command, args []string) {
33-
if err := parseFileArg(args, &opts, defaultSFNSourceTSFile); err != nil {
33+
loadOptionsFromViper(viper.BuildViper, &opts)
34+
if err := parseFileArg(&opts); err != nil {
3435
log.FailureStatusEvent(os.Stdout, "%s", err.Error())
3536
os.Exit(127)
36-
// return
3737
}
38-
loadOptionsFromViper(viper.BuildViper, &opts)
39-
40-
log.InfoStatusEvent(os.Stdout, "YoMo Stream Function file: %v", opts.Filename)
38+
log.InfoStatusEvent(os.Stdout, "YoMo Stream Function runtime: %v", opts.Runtime)
4139
log.InfoStatusEvent(os.Stdout, "YoMo Stream Function parsing...")
4240
s, err := serverless.Create(&opts)
4341
if err != nil {
4442
log.FailureStatusEvent(os.Stdout, "%s", err.Error())
4543
os.Exit(127)
46-
// return
4744
}
4845
log.InfoStatusEvent(os.Stdout, "YoMo Stream Function parse done.")
4946
// build
5047
log.PendingStatusEvent(os.Stdout, "Building YoMo Stream Function instance...")
5148
if err := s.Build(true); err != nil {
5249
log.FailureStatusEvent(os.Stdout, "%s", err.Error())
5350
os.Exit(127)
54-
// return
5551
}
5652
log.SuccessStatusEvent(os.Stdout, "YoMo Stream Function build successful!")
5753
},
@@ -61,6 +57,7 @@ func init() {
6157
rootCmd.AddCommand(buildCmd)
6258

6359
buildCmd.Flags().StringVarP(&opts.ModFile, "modfile", "m", "", "custom go.mod")
60+
buildCmd.Flags().StringVarP(&opts.Runtime, "runtime", "r", "node", "serverless runtime type")
6461

6562
viper.BindPFlags(viper.BuildViper, buildCmd.Flags())
6663
}

cli/cli.go

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package cli
44

55
import (
6+
"errors"
67
"fmt"
78
"path"
89
"path/filepath"
@@ -21,7 +22,6 @@ const (
2122
defaultSFNSourceTSFile = "src/app.ts"
2223
defaultSFNTestSourceFile = "app_test.go"
2324
defaultSFNTestSourceTSFile = "app_test.ts"
24-
defaultSFNCompliedFile = "sfn.yomo"
2525
)
2626

2727
// GetRootPath get root path
@@ -64,24 +64,19 @@ func loadOptionsFromViper(v *viper.Viper, opts *serverless.Options) {
6464
opts.Runtime = v.GetString("runtime")
6565
}
6666

67-
// parseFileArg parses the filename from command line arguments or uses default files if none provided.
68-
// It updates the given serverless.Options with the filename and validates it via checkOptions.
69-
// Returns nil if a valid filename is found, otherwise continues trying default files.
70-
func parseFileArg(args []string, opts *serverless.Options, defaultFiles ...string) error {
71-
// parse filename from args, like `yomo run app.go`
72-
if len(args) >= 1 && args[0] != "" {
73-
opts.Filename = args[0]
74-
return checkOptions(opts)
67+
// parseFileArg parses the file argument and sets the default file name based on the runtime
68+
func parseFileArg(opts *serverless.Options) error {
69+
runtime := opts.Runtime
70+
if runtime == "" {
71+
return errors.New("runtime is not specified, please use `-r` flag to specify the runtime")
7572
}
76-
// if no filename is provided, use the default files
77-
for _, f := range defaultFiles {
78-
opts.Filename = f
79-
err := checkOptions(opts)
80-
if err == nil {
81-
break
82-
}
73+
switch runtime {
74+
case "go": // go
75+
opts.Filename = defaultSFNSourceFile
76+
default: // node
77+
opts.Filename = defaultSFNSourceTSFile
8378
}
84-
return nil
79+
return checkOptions(opts)
8580
}
8681

8782
func checkOptions(opts *serverless.Options) error {
@@ -96,22 +91,22 @@ func checkOptions(opts *serverless.Options) error {
9691
return nil
9792
}
9893

99-
// DefaultSFNSourceFile returns the default source file name for the given language
100-
func DefaultSFNSourceFile(lang string) string {
101-
switch lang {
102-
case "node":
103-
return defaultSFNSourceTSFile
104-
default:
94+
// DefaultSFNSourceFile returns the default source file name for the given runtime
95+
func DefaultSFNSourceFile(runtime string) string {
96+
switch runtime {
97+
case "go": // go
10598
return defaultSFNSourceFile
99+
default: // node
100+
return defaultSFNSourceTSFile
106101
}
107102
}
108103

109104
// DefaultSFNTestSourceFile returns the default test source file name
110-
func DefaultSFNTestSourceFile(lang string) string {
111-
switch lang {
112-
case "node":
113-
return defaultSFNTestSourceTSFile
114-
default:
105+
func DefaultSFNTestSourceFile(runtime string) string {
106+
switch runtime {
107+
case "go": // go
115108
return defaultSFNTestSourceFile
109+
default: // node
110+
return defaultSFNTestSourceTSFile
116111
}
117112
}

cli/dev.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ package cli
1717

1818
import (
1919
"os"
20-
"path/filepath"
2120

2221
"github.com/spf13/cobra"
2322
"github.com/yomorun/yomo/cli/serverless"
@@ -30,13 +29,14 @@ var devCmd = &cobra.Command{
3029
Use: "dev [flags]",
3130
Short: "Test a YoMo Stream Function",
3231
Long: "Test a YoMo Stream Function with public zipper and mocking data",
32+
Hidden: true,
3333
FParseErrWhitelist: cobra.FParseErrWhitelist{UnknownFlags: true},
3434
Run: func(cmd *cobra.Command, args []string) {
35-
if err := parseFileArg(args, &opts, defaultSFNCompliedFile, defaultSFNSourceFile); err != nil {
35+
loadOptionsFromViper(viper.RunViper, &opts)
36+
if err := parseFileArg(&opts); err != nil {
3637
log.FailureStatusEvent(os.Stdout, "%s", err.Error())
3738
return
3839
}
39-
loadOptionsFromViper(viper.RunViper, &opts)
4040
// Serverless
4141
log.InfoStatusEvent(os.Stdout, "YoMo Stream Function file: %v", opts.Filename)
4242
// resolve serverless
@@ -55,23 +55,19 @@ var devCmd = &cobra.Command{
5555
log.FailureStatusEvent(os.Stdout, "%s", err.Error())
5656
return
5757
}
58-
if !s.Executable() {
59-
log.FailureStatusEvent(os.Stdout,
60-
"You cannot run `%s` directly. build first with the `yomo build %s` command and then run with the 'yomo run %s' command.",
61-
opts.Filename,
62-
opts.Filename,
63-
opts.Filename,
64-
)
65-
return
66-
}
67-
// build if it's go file
68-
if ext := filepath.Ext(opts.Filename); ext == ".go" {
58+
59+
// if has `--production` flag, skip s.Build() process
60+
isProduction := opts.Production
61+
if !isProduction {
62+
// build
6963
log.PendingStatusEvent(os.Stdout, "Building YoMo Stream Function instance...")
7064
if err := s.Build(true); err != nil {
7165
log.FailureStatusEvent(os.Stdout, "%s", err.Error())
7266
os.Exit(127)
7367
}
7468
log.SuccessStatusEvent(os.Stdout, "YoMo Stream Function build successful!")
69+
} else {
70+
log.InfoStatusEvent(os.Stdout, "YoMo Serverless LLM Function is running in [production] mode")
7571
}
7672
// run
7773
log.InfoStatusEvent(
@@ -91,6 +87,8 @@ func init() {
9187
rootCmd.AddCommand(devCmd)
9288

9389
devCmd.Flags().StringVarP(&opts.ModFile, "modfile", "m", "", "custom go.mod")
90+
devCmd.Flags().StringVarP(&opts.Runtime, "runtime", "r", "node", "serverless runtime type")
91+
devCmd.Flags().BoolVarP(&opts.Production, "production", "p", false, "run in production mode, skip the build process")
9492

9593
viper.BindPFlags(viper.DevViper, devCmd.Flags())
9694
}

cli/init.go

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,12 @@ import (
2525
"github.com/spf13/cobra"
2626
"github.com/yomorun/yomo/cli/serverless"
2727
"github.com/yomorun/yomo/cli/template"
28+
"github.com/yomorun/yomo/cli/viper"
2829
"github.com/yomorun/yomo/pkg/file"
2930
"github.com/yomorun/yomo/pkg/log"
3031
)
3132

32-
var (
33-
sfnType string
34-
lang string
35-
)
33+
var sfnType string
3634

3735
// initCmd represents the init command
3836
var initCmd = &cobra.Command{
@@ -46,18 +44,21 @@ var initCmd = &cobra.Command{
4644
opts.Name = name
4745
}
4846
if name == "" {
49-
log.FailureStatusEvent(os.Stdout, "Please input your app name, e.g. `yomo init my-tool [-l node -t llm]`")
47+
log.FailureStatusEvent(os.Stdout, "Please input your app name, e.g. `yomo init my-tool [-r node -t llm]`")
5048
return
5149
}
52-
log.PendingStatusEvent(os.Stdout, "Initializing the Serverless LLM Function...")
50+
51+
loadOptionsFromViper(viper.InitViper, &opts)
52+
53+
log.PendingStatusEvent(os.Stdout, "Initializing the Serverless LLM Function with [%s] runtime...", opts.Runtime)
5354
name = strings.ReplaceAll(name, " ", "_")
5455

55-
filename := filepath.Join(name, DefaultSFNSourceFile(lang))
56+
filename := filepath.Join(name, DefaultSFNSourceFile(opts.Runtime))
5657
opts.Filename = filename
5758

5859
// create app source file
59-
fname := filepath.Join(name, DefaultSFNSourceFile(lang))
60-
contentTmpl, err := template.GetContent("init", sfnType, lang, false)
60+
fname := filepath.Join(name, DefaultSFNSourceFile(opts.Runtime))
61+
contentTmpl, err := template.GetContent("init", sfnType, opts.Runtime, false)
6162
if err != nil {
6263
log.FailureStatusEvent(os.Stdout, "%s", err.Error())
6364
return
@@ -73,8 +74,8 @@ var initCmd = &cobra.Command{
7374
return
7475
}
7576
// create app test file
76-
testName := filepath.Join(name, DefaultSFNTestSourceFile(lang))
77-
testTmpl, err := template.GetContent("init", sfnType, lang, true)
77+
testName := filepath.Join(name, DefaultSFNTestSourceFile(opts.Runtime))
78+
testTmpl, err := template.GetContent("init", sfnType, opts.Runtime, true)
7879
if err != nil {
7980
if !errors.Is(err, template.ErrUnsupportedTest) {
8081
log.FailureStatusEvent(os.Stdout, "%s", err.Error())
@@ -88,7 +89,11 @@ var initCmd = &cobra.Command{
8889
}
8990
// create .env
9091
fname = filepath.Join(name, ".env")
91-
if err := file.PutContents(fname, []byte(fmt.Sprintf("YOMO_SFN_NAME=%s\nYOMO_SFN_ZIPPER=localhost:9000\n", name))); err != nil {
92+
var sb strings.Builder
93+
sb.WriteString(fmt.Sprintf("YOMO_SFN_RUNTIME=%s\n", opts.Runtime))
94+
sb.WriteString(fmt.Sprintf("YOMO_SFN_NAME=%s\n", name))
95+
sb.WriteString(fmt.Sprintf("YOMO_SFN_ZIPPER=%s\n", "localhost:9000"))
96+
if err := file.PutContents(fname, []byte(sb.String())); err != nil {
9297
log.FailureStatusEvent(os.Stdout, "Write Serverless LLM Function .env file failure with the error: %v", err)
9398
return
9499
}
@@ -103,5 +108,7 @@ func init() {
103108
rootCmd.AddCommand(initCmd)
104109

105110
initCmd.Flags().StringVarP(&sfnType, "type", "t", "llm", "The type of Serverless LLM Function, support normal and llm")
106-
initCmd.Flags().StringVarP(&lang, "lang", "l", "node", "The language of Serverless LLM Function, support go and node")
111+
initCmd.Flags().StringVarP(&opts.Runtime, "runtime", "r", "node", "serverless runtime type, support node and go")
112+
113+
viper.BindPFlags(viper.InitViper, initCmd.Flags())
107114
}

cli/run.go

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323

2424
// serverless registrations
2525
"github.com/yomorun/yomo/cli/serverless"
26-
_ "github.com/yomorun/yomo/cli/serverless/exec"
2726
_ "github.com/yomorun/yomo/cli/serverless/golang"
2827
_ "github.com/yomorun/yomo/cli/serverless/nodejs"
2928
"github.com/yomorun/yomo/cli/viper"
@@ -35,11 +34,11 @@ var runCmd = &cobra.Command{
3534
Short: "Run a YoMo Serverless LLM Function",
3635
Long: "Run a YoMo Serverless LLM Function",
3736
Run: func(cmd *cobra.Command, args []string) {
38-
if err := parseFileArg(args, &opts, defaultSFNCompliedFile, defaultSFNSourceFile, defaultSFNSourceTSFile); err != nil {
37+
loadOptionsFromViper(viper.RunViper, &opts)
38+
if err := parseFileArg(&opts); err != nil {
3939
log.FailureStatusEvent(os.Stdout, "%s", err.Error())
4040
return
4141
}
42-
loadOptionsFromViper(viper.RunViper, &opts)
4342
// Serverless
4443
log.InfoStatusEvent(os.Stdout, "YoMo Serverless LLM Function file: %v", opts.Filename)
4544
if opts.Name == "" {
@@ -57,24 +56,19 @@ var runCmd = &cobra.Command{
5756
log.FailureStatusEvent(os.Stdout, "%s", err.Error())
5857
return
5958
}
60-
if !s.Executable() {
61-
log.FailureStatusEvent(os.Stdout,
62-
"You cannot run `%s` directly. build first with the `yomo build %s` command and then run with the 'yomo run %s' command.",
63-
opts.Filename,
64-
opts.Filename,
65-
opts.Filename,
66-
)
67-
return
68-
}
6959

7060
// if has `--production` flag, skip s.Build() process
7161
isProduction := opts.Production
72-
log.InfoStatusEvent(os.Stdout, "production mode is %v", opts.Production)
7362
if !isProduction {
63+
// build
64+
log.PendingStatusEvent(os.Stdout, "Building YoMo Stream Function instance...")
7465
if err := s.Build(true); err != nil {
7566
log.FailureStatusEvent(os.Stdout, "%s", err.Error())
7667
os.Exit(127)
7768
}
69+
log.SuccessStatusEvent(os.Stdout, "YoMo Stream Function build successful!")
70+
} else {
71+
log.InfoStatusEvent(os.Stdout, "YoMo Serverless LLM Function is running in [production] mode")
7872
}
7973

8074
log.InfoStatusEvent(
@@ -97,7 +91,7 @@ func init() {
9791
runCmd.Flags().StringVarP(&opts.Name, "name", "n", "", "yomo Serverless LLM Function name.")
9892
runCmd.Flags().StringVarP(&opts.ModFile, "modfile", "m", "", "custom go.mod")
9993
runCmd.Flags().StringVarP(&opts.Credential, "credential", "d", "", "client credential payload, eg: `token:dBbBiRE7`")
100-
runCmd.Flags().StringVarP(&opts.Runtime, "runtime", "r", "", "serverless runtime type")
94+
runCmd.Flags().StringVarP(&opts.Runtime, "runtime", "r", "node", "serverless runtime type")
10195
runCmd.Flags().BoolVarP(&opts.Production, "production", "p", false, "run in production mode, skip the build process")
10296

10397
viper.BindPFlags(viper.RunViper, runCmd.Flags())

0 commit comments

Comments
 (0)