From 0348557653adb6cbe8497bedba893b4413e0d47b Mon Sep 17 00:00:00 2001 From: zongz Date: Tue, 26 Sep 2023 15:41:18 +0800 Subject: [PATCH] feat: add '--quiet' to control the kpm log message Signed-off-by: zongz --- .github/workflows/test.yaml | 1 + kpm.go | 12 ++ main.k | 1 - pkg/api/kpm_run.go | 133 +++++++++++------- pkg/client/client.go | 55 +++++--- pkg/cmd/cmd_flags.go | 1 + pkg/cmd/cmd_init.go | 10 +- pkg/cmd/cmd_login.go | 11 +- pkg/cmd/cmd_logout.go | 11 +- pkg/cmd/cmd_pkg.go | 8 +- pkg/cmd/cmd_push.go | 10 +- pkg/cmd/cmd_run.go | 12 +- pkg/oci/oci.go | 6 +- pkg/opt/opt.go | 10 ++ pkg/package/modfile.go | 6 +- pkg/package/package.go | 7 + pkg/package/toml.go | 6 +- pkg/reporter/reporter.go | 14 +- pkg/semver/semver.go | 5 +- pkg/semver/semver_test.go | 6 +- pkg/utils/utils.go | 7 +- .../push_kcl1_again/test_suite.stderr | 1 - .../push_kcl1_again/test_suite.stdout | 1 + .../push_kcl1_reg_not_exist/test_suite.stderr | 1 - .../push_kcl1_reg_not_exist/test_suite.stdout | 1 + .../init_with_no_args/test_suite.stderr | 1 - .../init_with_no_args/test_suite.stdout | 4 + .../login_with_no_args/test_suite.stderr | 4 +- .../logout_reg_without_args/test_suite.stderr | 4 +- .../kpm_run/test_kpm_run_quiet/test_suite.env | 2 + .../test_kpm_run_quiet/test_suite.input | 1 + .../test_kpm_run_quiet/test_suite.stderr | 0 .../test_kpm_run_quiet/test_suite.stdout | 76 ++++++++++ .../1.init_an_empty_pkg/test_suite.stderr | 3 - .../1.init_an_empty_pkg/test_suite.stdout | 4 + .../test_data/test_kpm_run_quiet/kcl.mod | 7 + .../test_data/test_kpm_run_quiet/kcl.mod.lock | 8 ++ .../test_data/test_kpm_run_quiet/main.k | 108 ++++++++++++++ 38 files changed, 430 insertions(+), 128 deletions(-) delete mode 100644 main.k create mode 100644 test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.env create mode 100644 test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.input create mode 100644 test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.stderr create mode 100644 test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.stdout create mode 100644 test/e2e/test_suites/test_data/test_kpm_run_quiet/kcl.mod create mode 100644 test/e2e/test_suites/test_data/test_kpm_run_quiet/kcl.mod.lock create mode 100644 test/e2e/test_suites/test_data/test_kpm_run_quiet/main.k diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 2eef9d3f..3b2e68e6 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -46,3 +46,4 @@ jobs: with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version version: v1.50.1 + timeout: 5m diff --git a/kpm.go b/kpm.go index be564eba..fc728b40 100644 --- a/kpm.go +++ b/kpm.go @@ -37,6 +37,18 @@ func main() { cmd.NewPushCmd(kpmcli), cmd.NewPullCmd(kpmcli), } + app.Flags = []cli.Flag{ + &cli.BoolFlag{ + Name: cmd.FLAG_QUIET, + Usage: "push in vendor mode", + }, + } + app.Before = func(c *cli.Context) error { + if c.Bool(cmd.FLAG_QUIET) { + kpmcli.SetLogWriter(nil) + } + return nil + } err = app.Run(os.Args) if err != nil { reporter.Fatal(err) diff --git a/main.k b/main.k deleted file mode 100644 index fa7048e6..00000000 --- a/main.k +++ /dev/null @@ -1 +0,0 @@ -The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/pkg/api/kpm_run.go b/pkg/api/kpm_run.go index d5a012ae..ad3a40c7 100644 --- a/pkg/api/kpm_run.go +++ b/pkg/api/kpm_run.go @@ -105,62 +105,11 @@ func getAbsInputPath(pkgPath string, inputPath string) (string, error) { // RunPkgWithOpt will compile the kcl package with the compile options. func RunPkgWithOpt(opts *opt.CompileOptions) (*kcl.KCLResultList, error) { - pkgPath, err := filepath.Abs(opts.PkgPath()) - if err != nil { - return nil, errors.InternalBug - } - - kclPkg, err := pkg.LoadKclPkg(pkgPath) - if err != nil { - return nil, fmt.Errorf("kpm: failed to load package, please check the package path '%s' is valid", pkgPath) - } - - kclPkg.SetVendorMode(opts.IsVendor()) - - globalPkgPath, err := env.GetAbsPkgPath() - if err != nil { - return nil, err - } - - err = kclPkg.ValidateKpmHome(globalPkgPath) - if err != (*reporter.KpmEvent)(nil) { - return nil, err - } - - if len(opts.Entries()) > 0 { - // add entry from '--input' - for _, entry := range opts.Entries() { - if filepath.IsAbs(entry) { - opts.Merge(kcl.WithKFilenames(entry)) - } else { - opts.Merge(kcl.WithKFilenames(filepath.Join(opts.PkgPath(), entry))) - } - } - // add entry from 'kcl.mod' - } else if len(kclPkg.GetEntryKclFilesFromModFile()) > 0 { - opts.Merge(*kclPkg.GetKclOpts()) - } else if !opts.HasSettingsYaml() { - // no entry - opts.Merge(kcl.WithKFilenames(opts.PkgPath())) - } - opts.Merge(kcl.WithWorkDir(opts.PkgPath())) - - // Calculate the absolute path of entry file described by '--input'. - compiler := runner.NewCompilerWithOpts(opts) - kpmcli, err := client.NewKpmClient() if err != nil { return nil, err } - - // Call the kcl compiler. - compileResult, err := kpmcli.Compile(kclPkg, compiler) - - if err != nil { - return nil, reporter.NewErrorEvent(reporter.CompileFailed, err, "failed to compile the kcl package") - } - - return compileResult, nil + return run(kpmcli, opts) } // RunCurrentPkg will compile the current kcl package. @@ -191,12 +140,16 @@ func RunTarPkg(tarPath string, opts *opt.CompileOptions) (*kcl.KCLResultList, er } opts.SetPkgPath(destDir) + kpmcli, err := client.NewKpmClient() + if err != nil { + return nil, err + } // The directory after extracting the tar package is taken as the root directory of the package, // and kclvm is called to compile the kcl program under the 'destDir'. // e.g. // if the tar path is 'xxx/xxx/xxx/test.tar', // the 'xxx/xxx/xxx/test' will be taken as the root path of the kcl package to compile. - return RunPkgWithOpt(opts) + return run(kpmcli, opts) } // RunOciPkg will compile the kcl package from an OCI reference. @@ -235,5 +188,77 @@ func RunOciPkg(ociRef, version string, opts *opt.CompileOptions) (*kcl.KCLResult return nil, errors.FailedPull } - return RunTarPkg(matches[0], opts) + // 4. Untar the tar file. + absTarPath, err := utils.AbsTarPath(matches[0]) + if err != nil { + return nil, err + } + // Extract the tar package to a directory with the same name. + // e.g. + // 'xxx/xxx/xxx/test.tar' will be extracted to the directory 'xxx/xxx/xxx/test'. + destDir := strings.TrimSuffix(absTarPath, filepath.Ext(absTarPath)) + err = utils.UnTarDir(absTarPath, destDir) + if err != nil { + return nil, err + } + + opts.SetPkgPath(destDir) + return run(kpmcli, opts) +} + +// 'run' will compile the kcl package from the compile options by kpm client. +func run(kpmcli *client.KpmClient, opts *opt.CompileOptions) (*kcl.KCLResultList, error) { + pkgPath, err := filepath.Abs(opts.PkgPath()) + if err != nil { + return nil, errors.InternalBug + } + + kclPkg, err := pkg.LoadKclPkg(pkgPath) + if err != nil { + return nil, fmt.Errorf("kpm: failed to load package, please check the package path '%s' is valid", pkgPath) + } + + kclPkg.SetVendorMode(opts.IsVendor()) + + globalPkgPath, err := env.GetAbsPkgPath() + if err != nil { + return nil, err + } + + err = kclPkg.ValidateKpmHome(globalPkgPath) + if err != (*reporter.KpmEvent)(nil) { + return nil, err + } + + if len(opts.Entries()) > 0 { + // add entry from '--input' + for _, entry := range opts.Entries() { + if filepath.IsAbs(entry) { + opts.Merge(kcl.WithKFilenames(entry)) + } else { + opts.Merge(kcl.WithKFilenames(filepath.Join(opts.PkgPath(), entry))) + } + } + // add entry from 'kcl.mod' + } else if len(kclPkg.GetEntryKclFilesFromModFile()) > 0 { + opts.Merge(*kclPkg.GetKclOpts()) + } else if !opts.HasSettingsYaml() { + // no entry + opts.Merge(kcl.WithKFilenames(opts.PkgPath())) + } + opts.Merge(kcl.WithWorkDir(opts.PkgPath())) + + // Calculate the absolute path of entry file described by '--input'. + compiler := runner.NewCompilerWithOpts(opts) + + kpmcli.SetLogWriter(opts.LogWriter()) + + // Call the kcl compiler. + compileResult, err := kpmcli.Compile(kclPkg, compiler) + + if err != nil { + return nil, reporter.NewErrorEvent(reporter.CompileFailed, err, "failed to compile the kcl package") + } + + return compileResult, nil } diff --git a/pkg/client/client.go b/pkg/client/client.go index 6b84fec7..72b0d1dc 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -54,6 +54,14 @@ func NewKpmClient() (*KpmClient, error) { }, nil } +func (c *KpmClient) SetLogWriter(writer io.Writer) { + c.logWriter = writer +} + +func (c *KpmClient) GetLogWriter() io.Writer { + return c.logWriter +} + // SetHomePath will set the home path of kpm. func (c *KpmClient) SetHomePath(homePath string) { c.homePath = homePath @@ -339,26 +347,41 @@ func (c *KpmClient) CompileOciPkg(ociSource, version string, opts *opt.CompileOp return c.CompileTarPkg(matches[0], opts) } -// InitEmptyPkg will initialize an empty kcl package. -func (c *KpmClient) InitEmptyPkg(kclPkg *pkg.KclPkg) error { +// createIfNotExist will create a file if it does not exist. +func (c *KpmClient) createIfNotExist(filepath string, storeFunc func() error) error { + reporter.ReportMsgTo(fmt.Sprintf("kpm: creating new :%s", filepath), c.GetLogWriter()) err := utils.CreateFileIfNotExist( - kclPkg.ModFile.GetModFilePath(), - kclPkg.ModFile.StoreModFile, + filepath, + storeFunc, ) + if err != nil { + if errEvent, ok := err.(*reporter.KpmEvent); ok { + if errEvent.Type() != reporter.FileExists { + return err + } else { + reporter.ReportMsgTo(fmt.Sprintf("kpm: '%s' already exists", filepath), c.GetLogWriter()) + } + } else { + return err + } + } + + return nil +} + +// InitEmptyPkg will initialize an empty kcl package. +func (c *KpmClient) InitEmptyPkg(kclPkg *pkg.KclPkg) error { + err := c.createIfNotExist(kclPkg.ModFile.GetModFilePath(), kclPkg.ModFile.StoreModFile) if err != nil { return err } - err = utils.CreateFileIfNotExist( - kclPkg.ModFile.GetModLockFilePath(), - kclPkg.LockDepsVersion, - ) + err = c.createIfNotExist(kclPkg.ModFile.GetModLockFilePath(), kclPkg.LockDepsVersion) if err != nil { return err } - // create the default kcl program. - err = createDefaultPkgIn(kclPkg.HomePath) + err = c.createIfNotExist(filepath.Join(kclPkg.ModFile.HomePath, constants.DEFAULT_KCL_FILE_NAME), kclPkg.CreateDefauleMain) if err != nil { return err } @@ -991,18 +1014,6 @@ func (c *KpmClient) pullTarFromOci(localPath string, ociOpts *opt.OciOptions) er return nil } -// createDefaultPkgIn will create the default kcl program in the local path. -func createDefaultPkgIn(localPath string) error { - mainProgPath := filepath.Join(localPath, constants.DEFAULT_KCL_FILE_NAME) - if !utils.DirExists(mainProgPath) { - err := os.WriteFile(mainProgPath, []byte(constants.DEFAULT_KCL_FILE_CONTENT), 0644) - if err != nil { - return err - } - } - return nil -} - // check sum for a Dependency. func check(dep pkg.Dependency, newDepPath string) bool { if dep.Sum == "" { diff --git a/pkg/cmd/cmd_flags.go b/pkg/cmd/cmd_flags.go index 0c377e0e..12bbb9d7 100644 --- a/pkg/cmd/cmd_flags.go +++ b/pkg/cmd/cmd_flags.go @@ -13,3 +13,4 @@ const FLAG_DISABLE_NONE = "disable_none" const FLAG_ARGUMENT = "argument" const FLAG_OVERRIDES = "overrides" const FLAG_SORT_KEYS = "sort_keys" +const FLAG_QUIET = "quiet" diff --git a/pkg/cmd/cmd_init.go b/pkg/cmd/cmd_init.go index 9e6ba340..d7979a9b 100644 --- a/pkg/cmd/cmd_init.go +++ b/pkg/cmd/cmd_init.go @@ -3,6 +3,7 @@ package cmd import ( + "fmt" "os" "path/filepath" @@ -68,13 +69,12 @@ func NewInitCmd(kpmcli *client.KpmClient) *cli.Command { } err = kpmcli.InitEmptyPkg(&kclPkg) - if err == nil { - reporter.Report("kpm: package '", pkgName, "' init finished") - } else { - reporter.ExitWithReport(err) + if err != nil { + return err } - return err + reporter.ReportMsgTo(fmt.Sprintf("kpm: package '%s' init finished", pkgName), kpmcli.GetLogWriter()) + return nil }, } } diff --git a/pkg/cmd/cmd_login.go b/pkg/cmd/cmd_login.go index a43e0f35..849e4d7b 100644 --- a/pkg/cmd/cmd_login.go +++ b/pkg/cmd/cmd_login.go @@ -3,6 +3,8 @@ package cmd import ( + "fmt" + "github.com/urfave/cli/v2" "kcl-lang.io/kpm/pkg/client" "kcl-lang.io/kpm/pkg/reporter" @@ -31,8 +33,11 @@ func NewLoginCmd(kpmcli *client.KpmClient) *cli.Command { }, Action: func(c *cli.Context) error { if c.NArg() == 0 { - reporter.Report("kpm: registry must be specified.") - reporter.ExitWithReport("kpm: run 'kpm registry help' for more information.") + return reporter.NewErrorEvent( + reporter.InvalidCmd, + fmt.Errorf("registry must be specified"), + "run 'kpm login help' for more information", + ) } registry := c.Args().First() @@ -45,7 +50,7 @@ func NewLoginCmd(kpmcli *client.KpmClient) *cli.Command { if err != nil { return err } - + reporter.ReportMsgTo("Login Succeeded", kpmcli.GetLogWriter()) return nil }, } diff --git a/pkg/cmd/cmd_logout.go b/pkg/cmd/cmd_logout.go index 09a0646b..23aece52 100644 --- a/pkg/cmd/cmd_logout.go +++ b/pkg/cmd/cmd_logout.go @@ -3,6 +3,8 @@ package cmd import ( + "fmt" + "github.com/urfave/cli/v2" "kcl-lang.io/kpm/pkg/client" "kcl-lang.io/kpm/pkg/reporter" @@ -16,14 +18,17 @@ func NewLogoutCmd(kpmcli *client.KpmClient) *cli.Command { Usage: "logout from a registry", Action: func(c *cli.Context) error { if c.NArg() == 0 { - reporter.Report("kpm: registry must be specified.") - reporter.ExitWithReport("kpm: run 'kpm registry help' for more information.") + return reporter.NewErrorEvent( + reporter.InvalidCmd, + fmt.Errorf("registry must be specified"), + "run 'kpm logout help' for more information", + ) } err := kpmcli.LogoutOci(c.Args().First()) if err != nil { return err } - + reporter.ReportMsgTo("kpm: Logout Succeeded", kpmcli.GetLogWriter()) return nil }, } diff --git a/pkg/cmd/cmd_pkg.go b/pkg/cmd/cmd_pkg.go index 644dfdf9..7b53fbce 100644 --- a/pkg/cmd/cmd_pkg.go +++ b/pkg/cmd/cmd_pkg.go @@ -3,6 +3,7 @@ package cmd import ( + "fmt" "os" "path/filepath" @@ -37,8 +38,11 @@ func NewPkgCmd(kpmcli *client.KpmClient) *cli.Command { tarPath := c.String("target") if len(tarPath) == 0 { - reporter.Report("kpm: The directory where the tar is generated is required.") - reporter.ExitWithReport("kpm: run 'kpm pkg help' for more information.") + return reporter.NewErrorEvent( + reporter.InvalidCmd, + fmt.Errorf("the directory where the tar is generated is required"), + "run 'kpm pkg help' for more information", + ) } pwd, err := os.Getwd() diff --git a/pkg/cmd/cmd_push.go b/pkg/cmd/cmd_push.go index fa3dd117..14810c04 100644 --- a/pkg/cmd/cmd_push.go +++ b/pkg/cmd/cmd_push.go @@ -150,9 +150,11 @@ func pushPackage(ociUrl string, kclPkg *pkg.KclPkg, vendorMode bool, kpmcli *cli if len(ociUrl) == 0 { ociUrl, err = genDefaultOciUrlForKclPkg(kclPkg, kpmcli) if err != nil || len(ociUrl) == 0 { - reporter.Report("kpm: failed to generate default oci url for current package.") - reporter.Report("kpm: run 'kpm push help' for more information.") - return errors.FailedPushToOci + return reporter.NewErrorEvent( + reporter.InvalidCmd, + fmt.Errorf("failed to generate default oci url for current package"), + "run 'kpm push help' for more information", + ) } } @@ -166,7 +168,7 @@ func pushPackage(ociUrl string, kclPkg *pkg.KclPkg, vendorMode bool, kpmcli *cli ) } - reporter.Report("kpm: package '" + kclPkg.GetPkgName() + "' will be pushed.") + reporter.ReportMsgTo(fmt.Sprintf("kpm: package '%s' will be pushed", kclPkg.GetPkgName()), kpmcli.GetLogWriter()) // 4. Push it. err = kpmcli.PushToOci(tarPath, ociOpts) if err != (*reporter.KpmEvent)(nil) { diff --git a/pkg/cmd/cmd_run.go b/pkg/cmd/cmd_run.go index ac95ee3c..694f14cb 100644 --- a/pkg/cmd/cmd_run.go +++ b/pkg/cmd/cmd_run.go @@ -4,12 +4,14 @@ package cmd import ( "fmt" + "os" "github.com/urfave/cli/v2" "kcl-lang.io/kcl-go/pkg/kcl" "kcl-lang.io/kpm/pkg/api" "kcl-lang.io/kpm/pkg/client" "kcl-lang.io/kpm/pkg/opt" + "kcl-lang.io/kpm/pkg/reporter" "kcl-lang.io/kpm/pkg/runner" ) @@ -87,7 +89,15 @@ func KpmRun(c *cli.Context, kpmcli *client.KpmClient) error { // 'kpm run' compile the current package undor '$pwd'. if runEntry.IsEmpty() { - compileResult, err := api.RunCurrentPkg(kclOpts) + pwd, err := os.Getwd() + kclOpts.SetPkgPath(pwd) + + if err != nil { + return reporter.NewErrorEvent( + reporter.Bug, err, "internal bugs, please contact us to fix it.", + ) + } + compileResult, err := kpmcli.CompileWithOpts(kclOpts) if err != nil { return err } diff --git a/pkg/oci/oci.go b/pkg/oci/oci.go index 6c5cb817..4a443b78 100644 --- a/pkg/oci/oci.go +++ b/pkg/oci/oci.go @@ -48,7 +48,6 @@ func Login(hostname, username, password string, setting *settings.Settings) erro return errors.FailedLogin } - reporter.Report("kpm: Login Succeeded") return nil } @@ -67,7 +66,6 @@ func Logout(hostname string, setting *settings.Settings) error { return errors.FailedLogout } - reporter.Report("kpm: Logout Succeeded") return nil } @@ -243,8 +241,8 @@ func (ociClient *OciClient) Push(localPath, tag string) *reporter.KpmEvent { return reporter.NewErrorEvent(reporter.FailedPush, err, fmt.Sprintf("failed to push '%s'", ociClient.repo.Reference)) } - reporter.Report("kpm: pushed [registry]", ociClient.repo.Reference) - reporter.Report("kpm: digest:", desc.Digest) + reporter.ReportMsgTo(fmt.Sprintf("kpm: pushed [registry] %s", ociClient.repo.Reference), ociClient.logWriter) + reporter.ReportMsgTo(fmt.Sprintf("kpm: digest: %s", desc.Digest), ociClient.logWriter) return nil } diff --git a/pkg/opt/opt.go b/pkg/opt/opt.go index 8cd45731..f87cbf1a 100644 --- a/pkg/opt/opt.go +++ b/pkg/opt/opt.go @@ -36,6 +36,11 @@ func (opts *CompileOptions) AddEntry(entry string) { opts.entries = append(opts.entries, entry) } +// SetLogWriter will set the log writer of the compiler. +func (opts *CompileOptions) SetLogWriter(writer io.Writer) { + opts.writer = writer +} + // Entrirs will return the entries of the compiler. func (opts *CompileOptions) Entries() []string { return opts.entries @@ -76,6 +81,11 @@ func (opts *CompileOptions) SetPkgPath(pkgPath string) { opts.Merge(kcl.WithWorkDir(pkgPath)) } +// LogWriter will return the log writer of the compiler. +func (opts *CompileOptions) LogWriter() io.Writer { + return opts.writer +} + // Input options of 'kpm init'. type InitOptions struct { Name string diff --git a/pkg/package/modfile.go b/pkg/package/modfile.go index 3f65e427..2331eee7 100644 --- a/pkg/package/modfile.go +++ b/pkg/package/modfile.go @@ -264,15 +264,13 @@ func (deps *Dependencies) loadLockFile(filepath string) error { } if err != nil { - reporter.Report("kpm: failed to load", filepath) - return err + return reporter.NewErrorEvent(reporter.FailedLoadKclModLock, err, fmt.Sprintf("failed to load '%s'", filepath)) } err = deps.UnmarshalLockTOML(string(data)) if err != nil { - reporter.Report("kpm: failed to load", filepath) - return err + return reporter.NewErrorEvent(reporter.FailedLoadKclModLock, err, fmt.Sprintf("failed to load '%s'", filepath)) } return nil diff --git a/pkg/package/package.go b/pkg/package/package.go index a37d288e..ade14c6d 100644 --- a/pkg/package/package.go +++ b/pkg/package/package.go @@ -6,6 +6,7 @@ import ( "strings" "kcl-lang.io/kcl-go/pkg/kcl" + "kcl-lang.io/kpm/pkg/constants" errors "kcl-lang.io/kpm/pkg/errors" "kcl-lang.io/kpm/pkg/opt" "kcl-lang.io/kpm/pkg/reporter" @@ -108,6 +109,12 @@ func (kclPkg *KclPkg) LockDepsVersion() error { return utils.StoreToFile(fullPath, lockToml) } +// CreateDefauleMain will create a default main.k file in the current kcl package. +func (kclPkg *KclPkg) CreateDefauleMain() error { + mainKPath := filepath.Join(kclPkg.HomePath, constants.DEFAULT_KCL_FILE_NAME) + return utils.StoreToFile(mainKPath, constants.DEFAULT_KCL_FILE_CONTENT) +} + // check sum for a Dependency. func check(dep Dependency, newDepPath string) bool { if dep.Sum == "" { diff --git a/pkg/package/toml.go b/pkg/package/toml.go index 54354bbf..c0938223 100644 --- a/pkg/package/toml.go +++ b/pkg/package/toml.go @@ -354,16 +354,14 @@ func (local *Local) UnmarshalModTOML(data interface{}) error { func (dep *Dependencies) MarshalLockTOML() (string, error) { buf := new(bytes.Buffer) if err := toml.NewEncoder(buf).Encode(dep); err != nil { - reporter.Report("kpm: failed to lock dependencies version.") - return "", err + return "", reporter.NewErrorEvent(reporter.FailedLoadKclModLock, err, "failed to lock dependencies version") } return buf.String(), nil } func (dep *Dependencies) UnmarshalLockTOML(data string) error { if _, err := toml.NewDecoder(strings.NewReader(data)).Decode(dep); err != nil { - reporter.Report("kpm: failed to load kcl.mod.lock.") - return err + return reporter.NewErrorEvent(reporter.FailedLoadKclModLock, err, "failed to load kcl.mod.lock") } return nil diff --git a/pkg/reporter/reporter.go b/pkg/reporter/reporter.go index 27d017fd..ce8d667e 100644 --- a/pkg/reporter/reporter.go +++ b/pkg/reporter/reporter.go @@ -65,6 +65,9 @@ const ( InvalidKclPkg FailedUntarKclPkg FailedLoadKclMod + FailedLoadKclModLock + FailedCreateFile + FileExists CheckSumMismatch CalSumFailed InvalidKpmHomeInCurrentPkg @@ -97,6 +100,7 @@ const ( DependencyNotFound KclModNotFound CompileFailed + FailedParseVersion ) // KpmEvent is the event used to show kpm logs to users. @@ -168,5 +172,13 @@ func ReportEventToStderr(event *KpmEvent) { // ReportEvent reports the event to users to stdout. func ReportEventTo(event *KpmEvent, w io.Writer) { - fmt.Fprintf(w, "%v", event.Event()) + if w != nil { + fmt.Fprintf(w, "%v", event.Event()) + } +} + +func ReportMsgTo(msg string, w io.Writer) { + if w != nil { + fmt.Fprintf(w, "%s\n", msg) + } } diff --git a/pkg/semver/semver.go b/pkg/semver/semver.go index 4377cc30..450bf8f9 100644 --- a/pkg/semver/semver.go +++ b/pkg/semver/semver.go @@ -1,6 +1,8 @@ package semver import ( + "fmt" + "github.com/hashicorp/go-version" "kcl-lang.io/kpm/pkg/errors" "kcl-lang.io/kpm/pkg/reporter" @@ -11,8 +13,7 @@ func LatestVersion(versions []string) (string, error) { for _, v := range versions { ver, err := version.NewVersion(v) if err != nil { - reporter.Report("kpm: failed to parse version", v, err) - continue + return "", reporter.NewErrorEvent(reporter.FailedParseVersion, err, fmt.Sprintf("failed to parse version %s", v)) } if latest == nil || ver.GreaterThan(latest) { latest = ver diff --git a/pkg/semver/semver_test.go b/pkg/semver/semver_test.go index 58a45cfd..04bf8f5e 100644 --- a/pkg/semver/semver_test.go +++ b/pkg/semver/semver_test.go @@ -17,12 +17,12 @@ func TestLatestVersion(t *testing.T) { assert.Equal(t, latest, "") latest, err = LatestVersion([]string{"invalid_version"}) - assert.Equal(t, err, errors.InvalidVersionFormat) + assert.Equal(t, err.Error(), "kpm: failed to parse version invalid_version\nkpm: Malformed version: invalid_version\n") assert.Equal(t, latest, "") latest, err = LatestVersion([]string{"1.2.3", "1.4.0", "1.3.5", "invalid_version"}) - assert.Equal(t, err, nil) - assert.Equal(t, latest, "1.4.0") + assert.Equal(t, err.Error(), "kpm: failed to parse version invalid_version\nkpm: Malformed version: invalid_version\n") + assert.Equal(t, latest, "") } func TestTheLatestTagWithMissingVersion(t *testing.T) { diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 9593070f..6511ad19 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -96,15 +96,12 @@ func ParseRepoNameFromGitUrl(gitUrl string) string { func CreateFileIfNotExist(filePath string, storeFunc func() error) error { _, err := os.Stat(filePath) if os.IsNotExist(err) { - reporter.Report("kpm: creating new :", filePath) err := storeFunc() if err != nil { - reporter.Report("kpm: failed to create: ,", filePath) - return err + return reporter.NewErrorEvent(reporter.FailedCreateFile, err, fmt.Sprintf("failed to create '%s'", filePath)) } } else { - reporter.Report("kpm: '" + filePath + "' already exists") - return err + return reporter.NewErrorEvent(reporter.FileExists, err, fmt.Sprintf("'%s' already exists", filePath)) } return nil } diff --git a/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_again/test_suite.stderr b/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_again/test_suite.stderr index 2e5310e4..7ee567d4 100644 --- a/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_again/test_suite.stderr +++ b/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_again/test_suite.stderr @@ -1,2 +1 @@ -kpm: package 'kcl1' will be pushed. kpm: package version '0.0.1' already exists \ No newline at end of file diff --git a/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_again/test_suite.stdout b/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_again/test_suite.stdout index e69de29b..5de249c3 100644 --- a/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_again/test_suite.stdout +++ b/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_again/test_suite.stdout @@ -0,0 +1 @@ +kpm: package 'kcl1' will be pushed \ No newline at end of file diff --git a/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_reg_not_exist/test_suite.stderr b/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_reg_not_exist/test_suite.stderr index 68e04602..3536d0da 100644 --- a/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_reg_not_exist/test_suite.stderr +++ b/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_reg_not_exist/test_suite.stderr @@ -1,2 +1 @@ -kpm: package 'kcl1' will be pushed. kpm: failed to access 'not_exist_reg/not_exist_repo' diff --git a/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_reg_not_exist/test_suite.stdout b/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_reg_not_exist/test_suite.stdout index e69de29b..871c3f63 100644 --- a/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_reg_not_exist/test_suite.stdout +++ b/test/e2e/test_suites/kpm/exec_inside_pkg/push_kcl1_reg_not_exist/test_suite.stdout @@ -0,0 +1 @@ +kpm: package 'kcl1' will be pushed diff --git a/test/e2e/test_suites/kpm/exec_outside_pkg/init_with_no_args/test_suite.stderr b/test/e2e/test_suites/kpm/exec_outside_pkg/init_with_no_args/test_suite.stderr index 5a8cf34b..e69de29b 100644 --- a/test/e2e/test_suites/kpm/exec_outside_pkg/init_with_no_args/test_suite.stderr +++ b/test/e2e/test_suites/kpm/exec_outside_pkg/init_with_no_args/test_suite.stderr @@ -1 +0,0 @@ -kpm: package ' test_kpm_workspace ' init finished diff --git a/test/e2e/test_suites/kpm/exec_outside_pkg/init_with_no_args/test_suite.stdout b/test/e2e/test_suites/kpm/exec_outside_pkg/init_with_no_args/test_suite.stdout index e69de29b..c997fe71 100644 --- a/test/e2e/test_suites/kpm/exec_outside_pkg/init_with_no_args/test_suite.stdout +++ b/test/e2e/test_suites/kpm/exec_outside_pkg/init_with_no_args/test_suite.stdout @@ -0,0 +1,4 @@ +kpm: creating new :/kcl.mod +kpm: creating new :/kcl.mod.lock +kpm: creating new :/main.k +kpm: package 'test_kpm_workspace' init finished \ No newline at end of file diff --git a/test/e2e/test_suites/kpm/exec_outside_pkg/login_with_no_args/test_suite.stderr b/test/e2e/test_suites/kpm/exec_outside_pkg/login_with_no_args/test_suite.stderr index b739c587..3aa703a7 100644 --- a/test/e2e/test_suites/kpm/exec_outside_pkg/login_with_no_args/test_suite.stderr +++ b/test/e2e/test_suites/kpm/exec_outside_pkg/login_with_no_args/test_suite.stderr @@ -1,2 +1,2 @@ -kpm: registry must be specified. -kpm: run 'kpm registry help' for more information. +kpm: run 'kpm login help' for more information +kpm: registry must be specified \ No newline at end of file diff --git a/test/e2e/test_suites/kpm/exec_outside_pkg/logout_reg_without_args/test_suite.stderr b/test/e2e/test_suites/kpm/exec_outside_pkg/logout_reg_without_args/test_suite.stderr index b739c587..6185640f 100644 --- a/test/e2e/test_suites/kpm/exec_outside_pkg/logout_reg_without_args/test_suite.stderr +++ b/test/e2e/test_suites/kpm/exec_outside_pkg/logout_reg_without_args/test_suite.stderr @@ -1,2 +1,2 @@ -kpm: registry must be specified. -kpm: run 'kpm registry help' for more information. +kpm: run 'kpm logout help' for more information +kpm: registry must be specified \ No newline at end of file diff --git a/test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.env b/test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.env new file mode 100644 index 00000000..4c789529 --- /dev/null +++ b/test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.env @@ -0,0 +1,2 @@ +KPM_HOME="" +KCLVM_VENDOR_HOME="" \ No newline at end of file diff --git a/test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.input b/test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.input new file mode 100644 index 00000000..b69acba6 --- /dev/null +++ b/test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.input @@ -0,0 +1 @@ +kpm --quiet run \ No newline at end of file diff --git a/test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.stderr b/test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.stderr new file mode 100644 index 00000000..e69de29b diff --git a/test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.stdout b/test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.stdout new file mode 100644 index 00000000..fb7aabdf --- /dev/null +++ b/test/e2e/test_suites/kpm/kpm_run/test_kpm_run_quiet/test_suite.stdout @@ -0,0 +1,76 @@ +helloworld: + workload: + containers: + nginx: + image: nginx:v1 + command: + - /bin/sh + - -c + - echo hi + args: + - /bin/sh + - -c + - echo hi + env: + env1: VALUE + env2: secret://sec-name/key + workingDir: /tmp + resources: + cpu: '2' + memory: 4Gi + readinessProbe: + probeHandler: + url: http://localhost:80 + initialDelaySeconds: 10 + secrets: + basic-auth: + type: basic + data: + username: admin + password: '******' + replicas: 2 + type: Deployment + ports: + - port: 80 + targetPort: 8080 + protocol: TCP + public: true + monitoring: + interval: 30s + timeout: 15s + path: /metrics + port: web + scheme: http +helloworldcollaset: + workload: + containers: + nginx: + image: nginx:v1 + command: + - /bin/sh + - -c + - echo hi + args: + - /bin/sh + - -c + - echo hi + workingDir: /tmp + replicas: 2 + type: CollaSet + ports: + - port: 80 + protocol: TCP + public: false + opsRule: + maxUnavailable: 30% +helloworldjob: + workload: + containers: + busybox: + image: busybox:1.28 + command: + - /bin/sh + - -c + - echo hello + replicas: 2 + schedule: 0 * * * * diff --git a/test/e2e/test_suites/kpm/workflows/init_and_run/1.init_an_empty_pkg/test_suite.stderr b/test/e2e/test_suites/kpm/workflows/init_and_run/1.init_an_empty_pkg/test_suite.stderr index 5fc8ff4b..e69de29b 100644 --- a/test/e2e/test_suites/kpm/workflows/init_and_run/1.init_an_empty_pkg/test_suite.stderr +++ b/test/e2e/test_suites/kpm/workflows/init_and_run/1.init_an_empty_pkg/test_suite.stderr @@ -1,3 +0,0 @@ -kpm: creating new : /kcl.mod -kpm: creating new : /kcl.mod.lock -kpm: package ' test_kpm_workspace ' init finished diff --git a/test/e2e/test_suites/kpm/workflows/init_and_run/1.init_an_empty_pkg/test_suite.stdout b/test/e2e/test_suites/kpm/workflows/init_and_run/1.init_an_empty_pkg/test_suite.stdout index e69de29b..c997fe71 100644 --- a/test/e2e/test_suites/kpm/workflows/init_and_run/1.init_an_empty_pkg/test_suite.stdout +++ b/test/e2e/test_suites/kpm/workflows/init_and_run/1.init_an_empty_pkg/test_suite.stdout @@ -0,0 +1,4 @@ +kpm: creating new :/kcl.mod +kpm: creating new :/kcl.mod.lock +kpm: creating new :/main.k +kpm: package 'test_kpm_workspace' init finished \ No newline at end of file diff --git a/test/e2e/test_suites/test_data/test_kpm_run_quiet/kcl.mod b/test/e2e/test_suites/test_data/test_kpm_run_quiet/kcl.mod new file mode 100644 index 00000000..bac3e1f3 --- /dev/null +++ b/test/e2e/test_suites/test_data/test_kpm_run_quiet/kcl.mod @@ -0,0 +1,7 @@ +[package] +name = "test_kpm_run_quiet" +edition = "0.0.1" +version = "0.0.1" + +[dependencies] +catalog = { git = "https://github.com/KusionStack/catalog.git", tag = "0.1.0" } diff --git a/test/e2e/test_suites/test_data/test_kpm_run_quiet/kcl.mod.lock b/test/e2e/test_suites/test_data/test_kpm_run_quiet/kcl.mod.lock new file mode 100644 index 00000000..faa7c9c7 --- /dev/null +++ b/test/e2e/test_suites/test_data/test_kpm_run_quiet/kcl.mod.lock @@ -0,0 +1,8 @@ +[dependencies] + [dependencies.catalog] + name = "catalog" + full_name = "catalog_0.1.0" + version = "0.1.0" + sum = "9nAzXsUVVbIJieEc+8x97Sb7AxfdU7RyEm5mNYLTP3M=" + url = "https://github.com/KusionStack/catalog.git" + git_tag = "0.1.0" diff --git a/test/e2e/test_suites/test_data/test_kpm_run_quiet/main.k b/test/e2e/test_suites/test_data/test_kpm_run_quiet/main.k new file mode 100644 index 00000000..2b6d07e5 --- /dev/null +++ b/test/e2e/test_suites/test_data/test_kpm_run_quiet/main.k @@ -0,0 +1,108 @@ +import catalog.models.schema.v1 as ac +import catalog.models.schema.v1.trait as t +import catalog.models.schema.v1.workload as wl +import catalog.models.schema.v1.workload.container as c +import catalog.models.schema.v1.workload.container.probe as p +import catalog.models.schema.v1.workload.secret as sec +import catalog.models.schema.v1.workload.network as n +import catalog.models.schema.v1.monitoring as m + +# base.k declares reusable configurations for all stacks. +helloworld: ac.AppConfiguration { + workload: wl.Service { + containers: { + "nginx": c.Container { + image: "nginx:v1" + # Run the following command as defined + command: ["/bin/sh", "-c", "echo hi"] + # Extra arguments append to command defined above + args: ["/bin/sh", "-c", "echo hi"] + env: { + # An environment variable of name "env1" and value "VALUE" will be set + "env1": "VALUE" + # An environment variable of name "env2" and value of the key "key" in the + # secret named "sec-name" will be set. + "env2": "secret://sec-name/key" + } + # Run the command "/bin/sh -c echo hi", as defined above, in the directory "/tmp" + workingDir: "/tmp" + resources: { + "cpu": "2" + "memory": "4Gi" + } + # Configure a HTTP readiness probe + readinessProbe: p.Probe { + probeHandler: p.Http { + url: "http://localhost:80" + } + initialDelaySeconds: 10 + } + } + } + secrets: { + "basic-auth": sec.Secret { + $type: "basic" + data: { + "username": "admin" + "password": "******" + } + } + } + replicas: 2 + ports: [ + n.Port { + port: 80 + targetPort: 8080 + protocol: "TCP" + public: True + } + ] + } + # Add the monitoring configuration backed by Prometheus + monitoring: m.Prometheus{ + interval: "30s" + timeout: "15s" + path: "/metrics" + port: "web" + scheme: "http" + } +} + +helloworldcollaset: ac.AppConfiguration { + workload: wl.Service { + type: "CollaSet" + containers: { + "nginx": c.Container { + image: "nginx:v1" + # Run the following command as defined + command: ["/bin/sh", "-c", "echo hi"] + # Extra arguments append to command defined above + args: ["/bin/sh", "-c", "echo hi"] + # Run the command "/bin/sh -c echo hi", as defined above, in the directory "/tmp" + workingDir: "/tmp" + } + } + ports: [ + n.Port { + port: 80 + } + ] + } + opsRule: t.OpsRule { + maxUnavailable: "30%" + } +} + +helloworldjob: ac.AppConfiguration { + workload: wl.Job { + containers: { + "busybox": c.Container { + image: "busybox:1.28" + # Run the following command as defined + command: ["/bin/sh", "-c", "echo hello"] + } + } + # Run every hour. + schedule: "0 * * * *" + } +} \ No newline at end of file