Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package harbor-cli for openSUSE:Factory checked in at 2026-03-05 17:17:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/harbor-cli (Old) and /work/SRC/openSUSE:Factory/.harbor-cli.new.561 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "harbor-cli" Thu Mar 5 17:17:06 2026 rev:13 rq:1336645 version:0.0.18 Changes: -------- --- /work/SRC/openSUSE:Factory/harbor-cli/harbor-cli.changes 2026-02-11 18:49:13.434325742 +0100 +++ /work/SRC/openSUSE:Factory/.harbor-cli.new.561/harbor-cli.changes 2026-03-05 17:24:32.930038266 +0100 @@ -1,0 +2,16 @@ +Wed Mar 04 06:14:31 UTC 2026 - Johannes Kastl <[email protected]> + +- Update to version 0.0.18: + * fix: project view --id flag not working (#639) + * ci(lint): Add gosec lint exclusion rules (#715) + * build(deps): bump golang.org/x/term from 0.39.0 to 0.40.0 + (#705) + * build(deps): bump github.com/charmbracelet/bubbles from 0.21.1 + to 1.0.0 (#704) + * build(deps): bump golang.org/x/text from 0.33.0 to 0.34.0 + (#706) + * fix : add url validation to all commands (#607) + * fix: reject negative page-size values in list commands (#631) + * fix: make comment field optional in user create command (#629) + +------------------------------------------------------------------- Old: ---- harbor-cli-0.0.17.obscpio New: ---- harbor-cli-0.0.18.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ harbor-cli.spec ++++++ --- /var/tmp/diff_new_pack.EyuIgN/_old 2026-03-05 17:24:33.946079379 +0100 +++ /var/tmp/diff_new_pack.EyuIgN/_new 2026-03-05 17:24:33.946079379 +0100 @@ -19,7 +19,7 @@ %define executable_name harbor Name: harbor-cli -Version: 0.0.17 +Version: 0.0.18 Release: 0 Summary: CLI for the Harbor cloud native registry License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.EyuIgN/_old 2026-03-05 17:24:33.986080997 +0100 +++ /var/tmp/diff_new_pack.EyuIgN/_new 2026-03-05 17:24:33.998081483 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/goharbor/harbor-cli</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v0.0.17</param> + <param name="revision">v0.0.18</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.EyuIgN/_old 2026-03-05 17:24:34.030082778 +0100 +++ /var/tmp/diff_new_pack.EyuIgN/_new 2026-03-05 17:24:34.034082940 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/goharbor/harbor-cli</param> - <param name="changesrevision">dae683f89db201e45542098528309541702ef64f</param></service></servicedata> + <param name="changesrevision">03ce614891616c6587ad6da1b5e3c0d51c0deaf2</param></service></servicedata> (No newline at EOF) ++++++ harbor-cli-0.0.17.obscpio -> harbor-cli-0.0.18.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/.golangci.yaml new/harbor-cli-0.0.18/.golangci.yaml --- old/harbor-cli-0.0.17/.golangci.yaml 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/.golangci.yaml 2026-03-03 15:36:07.000000000 +0100 @@ -30,6 +30,13 @@ - third_party$ - builtin$ - examples$ + rules: + - linters: + - gosec + text: "G117:" + - path: test + linters: + - gosec formatters: enable: - gofmt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/artifact/list.go new/harbor-cli-0.0.18/cmd/harbor/root/artifact/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/artifact/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/artifact/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -43,6 +43,10 @@ Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { return fmt.Errorf("page size should be less than or equal to 100") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/instance/create.go new/harbor-cli-0.0.18/cmd/harbor/root/instance/create.go --- old/harbor-cli-0.0.17/cmd/harbor/root/instance/create.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/instance/create.go 2026-03-03 15:36:07.000000000 +0100 @@ -14,9 +14,11 @@ package instance import ( + "fmt" + "github.com/goharbor/harbor-cli/pkg/api" + "github.com/goharbor/harbor-cli/pkg/utils" "github.com/goharbor/harbor-cli/pkg/views/instance/create" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -31,7 +33,7 @@ You will need to provide the instance's name, vendor, endpoint, and optionally other details such as authentication and security options.`, Example: ` harbor-cli instance create --name my-instance --provider Dragonfly --url http://dragonfly.local --description "My preheat provider instance" --enable=true`, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var err error createView := &create.CreateView{ Name: opts.Name, @@ -45,14 +47,20 @@ } if opts.Name != "" && opts.Vendor != "" && opts.Endpoint != "" { + formattedEndpoint := utils.FormatUrl(opts.Endpoint) + if err := utils.ValidateURL(formattedEndpoint); err != nil { + return err + } + opts.Endpoint = formattedEndpoint err = api.CreateInstance(opts) } else { err = createInstanceView(createView) } if err != nil { - log.Errorf("failed to create instance: %v", err) + return fmt.Errorf("failed to create instance: %v", err) } + return nil }, } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/instance/list.go new/harbor-cli-0.0.18/cmd/harbor/root/instance/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/instance/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/instance/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -14,6 +14,8 @@ package instance import ( + "fmt" + "github.com/goharbor/harbor-cli/pkg/api" "github.com/goharbor/harbor-cli/pkg/utils" "github.com/goharbor/harbor-cli/pkg/views/instance/list" @@ -33,7 +35,14 @@ This command provides an easy way to view all instances along with their details.`, Example: ` harbor-cli instance list --page 1 --page-size 10 harbor-cli instance list --query "name=my-instance" --sort "asc"`, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { + return fmt.Errorf("page size should be less than or equal to 100") + } + instance, err := api.ListInstance(opts) if err != nil { @@ -48,6 +57,7 @@ } else { list.ListInstance(instance.Payload) } + return nil }, } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/labels/list.go new/harbor-cli-0.0.18/cmd/harbor/root/labels/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/labels/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/labels/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -39,6 +39,10 @@ Short: "list labels", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { return fmt.Errorf("page size should be less than or equal to 100") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/login.go new/harbor-cli-0.0.18/cmd/harbor/root/login.go --- old/harbor-cli-0.0.17/cmd/harbor/root/login.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/login.go 2026-03-03 15:36:07.000000000 +0100 @@ -50,7 +50,7 @@ if passwordStdin { fmt.Print("Password: ") - passwordBytes, err := term.ReadPassword(int(os.Stdin.Fd())) + passwordBytes, err := term.ReadPassword(int(os.Stdin.Fd())) // #nosec G115 - fd fits in int on all supported platforms if err != nil { return fmt.Errorf("failed to read password from stdin: %v", err) } @@ -130,7 +130,7 @@ } err := utils.ValidateURL(opts.Server) if err != nil { - return fmt.Errorf("invalid server URL: %s", err) + return fmt.Errorf("invalid server URL: %w", err) } client := utils.GetClientByConfig(clientConfig) ctx := context.Background() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/logs.go new/harbor-cli-0.0.18/cmd/harbor/root/logs.go --- old/harbor-cli-0.0.17/cmd/harbor/root/logs.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/logs.go 2026-03-03 15:36:07.000000000 +0100 @@ -48,6 +48,12 @@ harbor-cli logs --output-format json`, RunE: func(cmd *cobra.Command, args []string) error { + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { + return fmt.Errorf("page size should be less than or equal to 100") + } if refreshInterval != "" && !follow { fmt.Println("The --refresh-interval flag is only applicable when using --follow. It will be ignored.") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/project/list.go new/harbor-cli-0.0.18/cmd/harbor/root/project/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/project/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/project/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -45,6 +45,10 @@ RunE: func(cmd *cobra.Command, args []string) error { log.Debug("Starting project list command") + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { return fmt.Errorf("page size should be less than or equal to 100") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/project/logs.go new/harbor-cli-0.0.18/cmd/harbor/root/project/logs.go --- old/harbor-cli-0.0.17/cmd/harbor/root/project/logs.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/project/logs.go 2026-03-03 15:36:07.000000000 +0100 @@ -35,6 +35,13 @@ Short: "get project logs", Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { + return fmt.Errorf("page size should be less than or equal to 100") + } + log.Debug("Starting execution of 'logs' command") var err error var resp *proj.GetLogExtsOK @@ -53,12 +60,14 @@ } log.Debugf("Checking if project '%s' exists...", projectName) - projectExists, err := api.CheckProject(projectName) + _, err = api.GetProject(projectName, false) if err != nil { - return fmt.Errorf("failed to find project: %v ", utils.ParseHarborErrorMsg(err)) - } else if !projectExists { - return fmt.Errorf("project %s does not exist", projectName) + if utils.ParseHarborErrorCode(err) == "404" { + return fmt.Errorf("project %s does not exist", projectName) + } + return fmt.Errorf("failed to verify project: %v", utils.ParseHarborErrorMsg(err)) } + log.Debugf("Fetching logs for project: %s", projectName) resp, err = api.LogsProject(projectName) if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/project/member/create.go new/harbor-cli-0.0.18/cmd/harbor/root/project/member/create.go --- old/harbor-cli-0.0.17/cmd/harbor/root/project/member/create.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/project/member/create.go 2026-03-03 15:36:07.000000000 +0100 @@ -22,6 +22,7 @@ "github.com/goharbor/harbor-cli/pkg/api" "github.com/goharbor/harbor-cli/pkg/prompt" + "github.com/goharbor/harbor-cli/pkg/utils" "github.com/goharbor/harbor-cli/pkg/views/member/create" "github.com/spf13/cobra" @@ -43,16 +44,14 @@ var err error if len(args) > 0 { - ok, checkErr := api.CheckProject(args[0]) // verifying project name + _, checkErr := api.GetProject(args[0], isID) if checkErr != nil { - return fmt.Errorf("failed to verify project name: %v", checkErr) - } - - if ok { - opts.ProjectName = args[0] - } else { - return fmt.Errorf("invalid project name: %s", args[0]) + if utils.ParseHarborErrorCode(checkErr) == "404" { + return fmt.Errorf("project %s does not exist", args[0]) + } + return fmt.Errorf("failed to verify project: %v", utils.ParseHarborErrorMsg(checkErr)) } + opts.ProjectName = args[0] } else { opts.ProjectName, err = prompt.GetProjectNameFromUser() if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/project/member/delete.go new/harbor-cli-0.0.18/cmd/harbor/root/project/member/delete.go --- old/harbor-cli-0.0.17/cmd/harbor/root/project/member/delete.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/project/member/delete.go 2026-03-03 15:36:07.000000000 +0100 @@ -18,6 +18,7 @@ "github.com/goharbor/harbor-cli/pkg/api" "github.com/goharbor/harbor-cli/pkg/prompt" + "github.com/goharbor/harbor-cli/pkg/utils" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -40,16 +41,14 @@ var err error if len(args) > 0 { - ok, checkErr := api.CheckProject(args[0]) // verifying project name + _, checkErr := api.GetProject(args[0], isID) if checkErr != nil { - return fmt.Errorf("failed to verify project name: %v", checkErr) - } - - if ok { - project = args[0] - } else { - return fmt.Errorf("invalid project name: %s", args[0]) + if utils.ParseHarborErrorCode(checkErr) == "404" { + return fmt.Errorf("project %s does not exist", args[0]) + } + return fmt.Errorf("failed to verify project: %v", utils.ParseHarborErrorMsg(checkErr)) } + project = args[0] } else { project, err = prompt.GetProjectNameFromUser() if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/project/member/list.go new/harbor-cli-0.0.18/cmd/harbor/root/project/member/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/project/member/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/project/member/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -40,6 +40,13 @@ Example: " harbor project member list my-project", Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { + return fmt.Errorf("page size should be less than or equal to 100") + } + var err error if len(args) > 0 { opts.ProjectNameOrID = args[0] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/project/robot/list.go new/harbor-cli-0.0.18/cmd/harbor/root/project/robot/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/project/robot/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/project/robot/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -14,6 +14,7 @@ package robot import ( + "fmt" "strconv" "github.com/goharbor/harbor-cli/pkg/api" @@ -69,6 +70,13 @@ harbor-cli project robot list`, Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { + return fmt.Errorf("page size should be less than or equal to 100") + } + if len(args) > 0 { project, err := api.GetProject(args[0], false) if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/project/view.go new/harbor-cli-0.0.18/cmd/harbor/root/project/view.go --- old/harbor-cli-0.0.17/cmd/harbor/root/project/view.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/project/view.go 2026-03-03 15:36:07.000000000 +0100 @@ -48,16 +48,12 @@ } } - log.Debugf("Checking existence of project: %s", projectName) - projectExists, err := api.CheckProject(projectName) - if err != nil { - return fmt.Errorf("failed to find project: %v ", utils.ParseHarborErrorMsg(err)) - } else if !projectExists { - return fmt.Errorf("project %s does not exist", projectName) - } - log.Debugf("Project %s exists", projectName) - project, err = api.GetProject(projectName, false) + log.Debugf("Fetching project: %s", projectName) + project, err = api.GetProject(projectName, isID) if err != nil { + if utils.ParseHarborErrorCode(err) == "404" { + return fmt.Errorf("project %s does not exist", projectName) + } return fmt.Errorf("failed to get project: %v", utils.ParseHarborErrorMsg(err)) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/quota/list.go new/harbor-cli-0.0.18/cmd/harbor/root/quota/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/quota/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/quota/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -31,6 +31,11 @@ Short: "list quotas", Long: "list quotas specified for each project", Run: func(cmd *cobra.Command, args []string) { + if opts.PageSize < 0 { + log.Errorf("page size must be greater than or equal to 0") + return + } + if opts.PageSize > 100 { log.Errorf("page size should be less than or equal to 100") return diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/registry/create.go new/harbor-cli-0.0.18/cmd/harbor/root/registry/create.go --- old/harbor-cli-0.0.17/cmd/harbor/root/registry/create.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/registry/create.go 2026-03-03 15:36:07.000000000 +0100 @@ -14,9 +14,11 @@ package registry import ( + "fmt" + "github.com/goharbor/harbor-cli/pkg/api" + "github.com/goharbor/harbor-cli/pkg/utils" "github.com/goharbor/harbor-cli/pkg/views/registry/create" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -28,7 +30,7 @@ Short: "create registry", Example: "harbor registry create", Args: cobra.ExactArgs(0), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var err error createView := &api.CreateRegView{ Name: opts.Name, @@ -44,14 +46,21 @@ } if opts.Name != "" && opts.Type != "" && opts.URL != "" { + formattedUrl := utils.FormatUrl(opts.URL) + err = utils.ValidateURL(formattedUrl) + if err != nil { + return err + } + opts.URL = formattedUrl err = api.CreateRegistry(opts) } else { err = createRegistryView(createView) } if err != nil { - log.Errorf("failed to create registry: %v", err) + return fmt.Errorf("failed to create registry: %v", err) } + return nil }, } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/registry/list.go new/harbor-cli-0.0.18/cmd/harbor/root/registry/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/registry/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/registry/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -33,6 +33,10 @@ Short: "list registry", Args: cobra.ExactArgs(0), RunE: func(cmd *cobra.Command, args []string) error { + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { return fmt.Errorf("page size should be less than or equal to 100") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/registry/update.go new/harbor-cli-0.0.18/cmd/harbor/root/registry/update.go --- old/harbor-cli-0.0.17/cmd/harbor/root/registry/update.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/registry/update.go 2026-03-03 15:36:07.000000000 +0100 @@ -14,11 +14,13 @@ package registry import ( + "fmt" + "github.com/goharbor/go-client/pkg/sdk/v2.0/models" "github.com/goharbor/harbor-cli/pkg/api" "github.com/goharbor/harbor-cli/pkg/prompt" + "github.com/goharbor/harbor-cli/pkg/utils" "github.com/goharbor/harbor-cli/pkg/views/registry/update" - log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -31,15 +33,14 @@ Use: "update [registry_name]", Short: "update registry", Args: cobra.MaximumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var err error var registryId int64 if len(args) > 0 { registryId, err = api.GetRegistryIdByName(args[0]) if err != nil { - log.Errorf("failed to get registry id: %v", err) - return + return fmt.Errorf("failed to get registry id: %v", err) } } else { registryId = prompt.GetRegistryNameFromUser() @@ -47,12 +48,10 @@ existingRegistry, err := api.GetRegistryResponse(registryId) if err != nil { - log.Errorf("failed to get registry with ID %d: %v", registryId, err) - return + return fmt.Errorf("failed to get registry with ID %d: %v", registryId, err) } if existingRegistry == nil { - log.Errorf("registry is not found") - return + return fmt.Errorf("registry is not found") } updateView := &models.Registry{ @@ -79,7 +78,11 @@ updateView.Description = opts.Description } if flags.Changed("url") { - updateView.URL = opts.URL + formattedUrl := utils.FormatUrl(opts.URL) + if err := utils.ValidateURL(formattedUrl); err != nil { + return err + } + updateView.URL = formattedUrl } if flags.Changed("insecure") { updateView.Insecure = opts.Insecure @@ -97,9 +100,9 @@ update.UpdateRegistryView(updateView) err = api.UpdateRegistry(updateView, registryId) if err != nil { - log.Errorf("failed to update registry: %v", err) - return + return fmt.Errorf("failed to update registry: %v", err) } + return nil }, } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/replication/executions/list.go new/harbor-cli-0.0.18/cmd/harbor/root/replication/executions/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/replication/executions/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/replication/executions/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -50,6 +50,10 @@ rpolicyID = prompt.GetReplicationPolicyFromUser() } + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { return fmt.Errorf("page size should be less than or equal to 100") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/replication/policies/list.go new/harbor-cli-0.0.18/cmd/harbor/root/replication/policies/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/replication/policies/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/replication/policies/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -33,6 +33,10 @@ RunE: func(cmd *cobra.Command, args []string) error { log.Debug("Starting replications list command") + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { return fmt.Errorf("page size should be less than or equal to 100") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/repository/list.go new/harbor-cli-0.0.18/cmd/harbor/root/repository/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/repository/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/repository/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -36,6 +36,10 @@ Long: `Get information of all repositories in a project`, Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { return fmt.Errorf("page size should be less than or equal to 100") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/robot/list.go new/harbor-cli-0.0.18/cmd/harbor/root/robot/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/robot/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/robot/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -14,6 +14,8 @@ package robot import ( + "fmt" + "github.com/goharbor/harbor-cli/pkg/api" "github.com/goharbor/harbor-cli/pkg/utils" "github.com/goharbor/harbor-cli/pkg/views/robot/list" @@ -61,7 +63,14 @@ # Get robot details in JSON format harbor-cli robot list --output-format json`, Args: cobra.MaximumNArgs(0), - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { + return fmt.Errorf("page size should be less than or equal to 100") + } + robots, err := api.ListRobot(opts) if err != nil { log.Errorf("failed to get robots list: %v", utils.ParseHarborErrorMsg(err)) @@ -76,6 +85,7 @@ } else { list.ListRobots(robots.Payload) } + return nil }, } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/scanner/create.go new/harbor-cli-0.0.18/cmd/harbor/root/scanner/create.go --- old/harbor-cli-0.0.17/cmd/harbor/root/scanner/create.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/scanner/create.go 2026-03-03 15:36:07.000000000 +0100 @@ -17,6 +17,7 @@ "fmt" "github.com/goharbor/harbor-cli/pkg/api" + "github.com/goharbor/harbor-cli/pkg/utils" "github.com/goharbor/harbor-cli/pkg/views/scanner/create" "github.com/spf13/cobra" ) @@ -32,6 +33,13 @@ RunE: func(cmd *cobra.Command, args []string) error { if opts.Name == "" || opts.Auth == "" || opts.URL == "" { create.CreateScannerView(&opts) + } else { + // Validate URL when provided via flags + formattedUrl := utils.FormatUrl(opts.URL) + if err := utils.ValidateURL(formattedUrl); err != nil { + return err + } + opts.URL = formattedUrl } if ping { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/scanner/update.go new/harbor-cli-0.0.18/cmd/harbor/root/scanner/update.go --- old/harbor-cli-0.0.17/cmd/harbor/root/scanner/update.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/scanner/update.go 2026-03-03 15:36:07.000000000 +0100 @@ -20,6 +20,7 @@ "github.com/goharbor/go-client/pkg/sdk/v2.0/models" "github.com/goharbor/harbor-cli/pkg/api" "github.com/goharbor/harbor-cli/pkg/prompt" + "github.com/goharbor/harbor-cli/pkg/utils" "github.com/goharbor/harbor-cli/pkg/views/scanner/create" "github.com/goharbor/harbor-cli/pkg/views/scanner/update" log "github.com/sirupsen/logrus" @@ -93,7 +94,11 @@ updateView.AccessCredential = opts.AccessCredential } if flags.Changed("url") { - updateView.URL = strfmt.URI(opts.URL) + formattedUrl := utils.FormatUrl(opts.URL) + if err := utils.ValidateURL(formattedUrl); err != nil { + return err + } + updateView.URL = strfmt.URI(formattedUrl) } if flags.Changed("disabled") { updateView.Disabled = &opts.Disabled diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/schedule/list.go new/harbor-cli-0.0.18/cmd/harbor/root/schedule/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/schedule/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/schedule/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -30,6 +30,10 @@ Use: "list", Short: "show all schedule jobs in Harbor", RunE: func(cmd *cobra.Command, args []string) error { + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { return fmt.Errorf("page size should be less than or equal to 100") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/user/create.go new/harbor-cli-0.0.18/cmd/harbor/root/user/create.go --- old/harbor-cli-0.0.17/cmd/harbor/root/user/create.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/user/create.go 2026-03-03 15:36:07.000000000 +0100 @@ -40,7 +40,7 @@ Username: opts.Username, } - if opts.Email != "" && opts.Realname != "" && opts.Comment != "" && opts.Password != "" && opts.Username != "" { + if opts.Email != "" && opts.Realname != "" && opts.Password != "" && opts.Username != "" { err = api.CreateUser(opts) } else { err = createUserView(createView) @@ -61,7 +61,7 @@ flags := cmd.Flags() flags.StringVarP(&opts.Email, "email", "", "", "Email") flags.StringVarP(&opts.Realname, "realname", "", "", "Realname") - flags.StringVarP(&opts.Comment, "comment", "", "", "Comment") + flags.StringVarP(&opts.Comment, "comment", "", "", "Comment (optional)") flags.StringVarP(&opts.Password, "password", "", "", "Password") flags.StringVarP(&opts.Username, "username", "", "", "Username") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/user/list.go new/harbor-cli-0.0.18/cmd/harbor/root/user/list.go --- old/harbor-cli-0.0.17/cmd/harbor/root/user/list.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/user/list.go 2026-03-03 15:36:07.000000000 +0100 @@ -35,6 +35,10 @@ Args: cobra.ExactArgs(0), Aliases: []string{"ls"}, RunE: func(cmd *cobra.Command, args []string) error { + if opts.PageSize < 0 { + return fmt.Errorf("page size must be greater than or equal to 0") + } + if opts.PageSize > 100 { return fmt.Errorf("page size should be less than or equal to 100") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/cmd/harbor/root/webhook/edit.go new/harbor-cli-0.0.18/cmd/harbor/root/webhook/edit.go --- old/harbor-cli-0.0.17/cmd/harbor/root/webhook/edit.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/cmd/harbor/root/webhook/edit.go 2026-03-03 15:36:07.000000000 +0100 @@ -19,6 +19,7 @@ "github.com/goharbor/go-client/pkg/sdk/v2.0/models" "github.com/goharbor/harbor-cli/pkg/api" "github.com/goharbor/harbor-cli/pkg/prompt" + "github.com/goharbor/harbor-cli/pkg/utils" "github.com/goharbor/harbor-cli/pkg/views/webhook/edit" "github.com/spf13/cobra" ) @@ -84,6 +85,9 @@ opts.NotifyType != "" && len(opts.EventType) != 0 && opts.EndpointURL != "" { + if err := utils.ValidateURL(opts.EndpointURL); err != nil { + return err + } err = api.UpdateWebhook(&opts) } else { err = editWebhookView(editView) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/doc/cli-docs/harbor-user-create.md new/harbor-cli-0.0.18/doc/cli-docs/harbor-user-create.md --- old/harbor-cli-0.0.17/doc/cli-docs/harbor-user-create.md 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/doc/cli-docs/harbor-user-create.md 2026-03-03 15:36:07.000000000 +0100 @@ -15,7 +15,7 @@ ### Options ```sh - --comment string Comment + --comment string Comment (optional) --email string Email -h, --help help for create --password string Password diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/doc/man-docs/man1/harbor-user-create.1 new/harbor-cli-0.0.18/doc/man-docs/man1/harbor-user-create.1 --- old/harbor-cli-0.0.17/doc/man-docs/man1/harbor-user-create.1 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/doc/man-docs/man1/harbor-user-create.1 2026-03-03 15:36:07.000000000 +0100 @@ -15,7 +15,7 @@ .SH OPTIONS \fB--comment\fP="" - Comment + Comment (optional) .PP \fB--email\fP="" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/go.mod new/harbor-cli-0.0.18/go.mod --- old/harbor-cli-0.0.17/go.mod 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/go.mod 2026-03-03 15:36:07.000000000 +0100 @@ -4,7 +4,7 @@ require ( github.com/atotto/clipboard v0.1.4 - github.com/charmbracelet/bubbles v0.21.1 + github.com/charmbracelet/bubbles v1.0.0 github.com/charmbracelet/bubbletea v1.3.10 github.com/charmbracelet/huh v0.8.0 github.com/charmbracelet/lipgloss v1.1.0 @@ -15,7 +15,7 @@ github.com/stretchr/testify v1.11.1 github.com/zalando/go-keyring v0.2.6 go.yaml.in/yaml/v4 v4.0.0-rc.3 - golang.org/x/term v0.39.0 + golang.org/x/term v0.40.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -24,7 +24,7 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/catppuccin/go v0.3.0 // indirect github.com/charmbracelet/colorprofile v0.4.1 // indirect - github.com/charmbracelet/x/ansi v0.11.5 // indirect + github.com/charmbracelet/x/ansi v0.11.6 // indirect github.com/charmbracelet/x/cellbuf v0.0.15 // indirect github.com/charmbracelet/x/exp/strings v0.0.0-20241222104055-e1130b311607 // indirect github.com/charmbracelet/x/term v0.2.2 // indirect @@ -91,8 +91,8 @@ go.opentelemetry.io/otel v1.35.0 // indirect go.opentelemetry.io/otel/metric v1.35.0 // indirect go.opentelemetry.io/otel/trace v1.35.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 + golang.org/x/sys v0.41.0 // indirect + golang.org/x/text v0.34.0 ) replace go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc => go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240518090000-14441aefdf88 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/go.sum new/harbor-cli-0.0.18/go.sum --- old/harbor-cli-0.0.17/go.sum 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/go.sum 2026-03-03 15:36:07.000000000 +0100 @@ -10,8 +10,8 @@ github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E= github.com/catppuccin/go v0.3.0 h1:d+0/YicIq+hSTo5oPuRi5kOpqkVA5tAsU6dNhvRu+aY= github.com/catppuccin/go v0.3.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= -github.com/charmbracelet/bubbles v0.21.1 h1:nj0decPiixaZeL9diI4uzzQTkkz1kYY8+jgzCZXSmW0= -github.com/charmbracelet/bubbles v0.21.1/go.mod h1:HHvIYRCpbkCJw2yo0vNX1O5loCwSr9/mWS8GYSg50Sk= +github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc= +github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E= github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk= @@ -20,8 +20,8 @@ github.com/charmbracelet/huh v0.8.0/go.mod h1:5YVc+SlZ1IhQALxRPpkGwwEKftN/+OlJlnJYlDRFqN4= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= -github.com/charmbracelet/x/ansi v0.11.5 h1:NBWeBpj/lJPE3Q5l+Lusa4+mH6v7487OP8K0r1IhRg4= -github.com/charmbracelet/x/ansi v0.11.5/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ= +github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8= +github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ= github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI= github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q= github.com/charmbracelet/x/conpty v0.1.0 h1:4zc8KaIcbiL4mghEON8D72agYtSeIgq8FSThSPQIb+U= @@ -198,12 +198,12 @@ golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= +golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/pkg/api/project_handler.go new/harbor-cli-0.0.18/pkg/api/project_handler.go --- old/harbor-cli-0.0.17/pkg/api/project_handler.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/pkg/api/project_handler.go 2026-03-03 15:36:07.000000000 +0100 @@ -203,23 +203,3 @@ return response, nil } - -func CheckProject(projectName string) (bool, error) { - ctx, client, err := utils.ContextWithClient() - if err != nil { - return false, err - } - - response, err := client.Project.HeadProject(ctx, &project.HeadProjectParams{ - ProjectName: projectName, - Context: ctx, - }) - if err != nil { - if utils.ParseHarborErrorCode(err) == "404" { - return false, nil - } - return false, err - } - - return response.IsSuccess(), nil -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/pkg/utils/error.go new/harbor-cli-0.0.18/pkg/utils/error.go --- old/harbor-cli-0.0.17/pkg/utils/error.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/pkg/utils/error.go 2026-03-03 15:36:07.000000000 +0100 @@ -17,6 +17,7 @@ "encoding/json" "fmt" "reflect" + "regexp" "strings" ) @@ -53,7 +54,10 @@ } func ParseHarborErrorCode(err error) string { - parts := strings.Split(err.Error(), "]") + errStr := err.Error() + + // Try format: [METHOD /path][CODE] - e.g., [GET /projects][404] + parts := strings.Split(errStr, "]") if len(parts) >= 2 { codePart := strings.TrimSpace(parts[1]) if strings.HasPrefix(codePart, "[") && len(codePart) == 4 { @@ -61,5 +65,12 @@ return code } } + + // Try format: (status CODE) - e.g., (status 404) + re := regexp.MustCompile(`\(status\s+(\d{3})\)`) + if matches := re.FindStringSubmatch(errStr); len(matches) > 1 { + return matches[1] + } + return "" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/pkg/utils/helper.go new/harbor-cli-0.0.18/pkg/utils/helper.go --- old/harbor-cli-0.0.17/pkg/utils/helper.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/pkg/utils/helper.go 2026-03-03 15:36:07.000000000 +0100 @@ -170,6 +170,8 @@ return re.MatchString(rn) } +// ValidateURL checks if the URL has valid format, non-empty host, and host is a valid IP or domain. +// Domain regex: labels must start/end with alphanumeric, can contain hyphens, max 63 chars, TLD min 2 letters. func ValidateURL(rawURL string) error { var domainNameRegex = regexp.MustCompile(`^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$`) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/pkg/utils/helper_test.go new/harbor-cli-0.0.18/pkg/utils/helper_test.go --- old/harbor-cli-0.0.17/pkg/utils/helper_test.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/pkg/utils/helper_test.go 2026-03-03 15:36:07.000000000 +0100 @@ -129,6 +129,40 @@ assert.False(t, utils.ValidateRegistryName("-bad")) } +func TestValidateURL(t *testing.T) { + tests := []struct { + name string + input string + wantErr bool + }{ + // valid URLs + {"valid https domain", "https://demo.goharbor.io", false}, + {"valid http domain", "http://registry.example.com", false}, + {"valid domain with port", "https://harbor.local:8443", false}, + {"valid domain with path", "https://example.com/v2", false}, + {"valid IPv4", "http://192.168.1.1", false}, + {"valid IPv4 with port", "http://192.168.1.1:8080", false}, + {"valid IPv6", "http://[::1]", false}, + + // invalid URLs + {"empty string", "", true}, + {"no host", "https://", true}, + {"bare path", "/just/a/path", true}, + {"invalid domain double dot", "https://invalid..domain", true}, + {"domain starting with hyphen", "https://-invalid.com", true}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := utils.ValidateURL(tc.input) + if tc.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +} + func TestPrintFormat(t *testing.T) { // capture stdout var buf bytes.Buffer diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/pkg/views/context/list/view.go new/harbor-cli-0.0.18/pkg/views/context/list/view.go --- old/harbor-cli-0.0.17/pkg/views/context/list/view.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/pkg/views/context/list/view.go 2026-03-03 15:36:07.000000000 +0100 @@ -36,7 +36,7 @@ rows := selectActiveContext(contexts, currentCredential) var opts []tea.ProgramOption - if !term.IsTerminal(int(os.Stdout.Fd())) { + if !term.IsTerminal(int(os.Stdout.Fd())) { // #nosec G115 - fd fits in int on all supported platforms opts = append(opts, tea.WithoutRenderer(), tea.WithInput(nil)) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/pkg/views/instance/create/view.go new/harbor-cli-0.0.18/pkg/views/instance/create/view.go --- old/harbor-cli-0.0.17/pkg/views/instance/create/view.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/pkg/views/instance/create/view.go 2026-03-03 15:36:07.000000000 +0100 @@ -59,8 +59,8 @@ Title("Name"). Value(&createView.Name). Validate(func(str string) error { - if str == "" { - return errors.New("name cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("name cannot be empty or only spaces") } return nil }), @@ -74,8 +74,15 @@ Title("Endpoint"). Value(&createView.Endpoint). Validate(func(str string) error { - err := utils.ValidateURL(str) - return err + if strings.TrimSpace(str) == "" { + return errors.New("endpoint cannot be empty or only spaces") + } + formattedUrl := utils.FormatUrl(str) + if err := utils.ValidateURL(formattedUrl); err != nil { + return err + } + createView.Endpoint = formattedUrl + return nil }), huh.NewConfirm(). Title("Enable"). @@ -133,8 +140,8 @@ Title("Token"). Value(&token). Validate(func(str string) error { - if str == "" { - return errors.New("token cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("token cannot be empty or only spaces") } return nil }), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/pkg/views/registry/create/view.go new/harbor-cli-0.0.18/pkg/views/registry/create/view.go --- old/harbor-cli-0.0.17/pkg/views/registry/create/view.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/pkg/views/registry/create/view.go 2026-03-03 15:36:07.000000000 +0100 @@ -15,7 +15,6 @@ import ( "errors" - "net/url" "strconv" "strings" @@ -64,8 +63,8 @@ Value(&createView.Type). Options(registrySelectOptions...). Validate(func(str string) error { - if str == "" { - return errors.New("registry provider cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("registry provider cannot be empty or only spaces") } return nil }), @@ -93,9 +92,11 @@ return errors.New("url cannot be empty or only spaces") } formattedUrl := utils.FormatUrl(str) - if _, err := url.ParseRequestURI(formattedUrl); err != nil { - return errors.New("please enter the correct url format") + if err := utils.ValidateURL(formattedUrl); err != nil { + return err } + // Update the bound value to the normalized URL after successful validation. + createView.URL = formattedUrl return nil }), huh.NewInput(). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/pkg/views/registry/update/view.go new/harbor-cli-0.0.18/pkg/views/registry/update/view.go --- old/harbor-cli-0.0.17/pkg/views/registry/update/view.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/pkg/views/registry/update/view.go 2026-03-03 15:36:07.000000000 +0100 @@ -15,9 +15,11 @@ import ( "errors" + "strings" "github.com/charmbracelet/huh" "github.com/goharbor/go-client/pkg/sdk/v2.0/models" + "github.com/goharbor/harbor-cli/pkg/utils" log "github.com/sirupsen/logrus" ) @@ -29,8 +31,8 @@ Title("Provider"). Value(&updateView.Type). Validate(func(str string) error { - if str == "" { - return errors.New("provider cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("provider cannot be empty or only spaces") } return nil }), @@ -38,8 +40,8 @@ Title("Name"). Value(&updateView.Name). Validate(func(str string) error { - if str == "" { - return errors.New("name cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("name cannot be empty or only spaces") } return nil }), @@ -50,9 +52,14 @@ Title("URL"). Value(&updateView.URL). Validate(func(str string) error { - if str == "" { - return errors.New("url cannot be empty") + if strings.TrimSpace(str) == "" { + return errors.New("url cannot be empty or only spaces") } + formattedUrl := utils.FormatUrl(str) + if err := utils.ValidateURL(formattedUrl); err != nil { + return err + } + updateView.URL = formattedUrl return nil }), huh.NewInput(). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/pkg/views/scanner/update/view.go new/harbor-cli-0.0.18/pkg/views/scanner/update/view.go --- old/harbor-cli-0.0.17/pkg/views/scanner/update/view.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/pkg/views/scanner/update/view.go 2026-03-03 15:36:07.000000000 +0100 @@ -15,6 +15,7 @@ import ( "errors" + "strings" "github.com/charmbracelet/huh" "github.com/go-openapi/strfmt" @@ -105,7 +106,16 @@ huh.NewInput(). Title("Scanner Adapter URL"). Value(&url). - Validate(huh.ValidateNotEmpty()), + Validate(func(str string) error { + if strings.TrimSpace(str) == "" { + return errors.New("url cannot be empty") + } + formattedUrl := utils.FormatUrl(str) + if err := utils.ValidateURL(formattedUrl); err != nil { + return err + } + return nil + }), huh.NewSelect[bool](). Title("Disable ?"). Options( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/pkg/views/user/create/view.go new/harbor-cli-0.0.18/pkg/views/user/create/view.go --- old/harbor-cli-0.0.17/pkg/views/user/create/view.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/pkg/views/user/create/view.go 2026-03-03 15:36:07.000000000 +0100 @@ -99,7 +99,7 @@ return nil }), huh.NewInput(). - Title("Comment"). + Title("Comment (optional)"). Value(&createView.Comment), ), ).WithTheme(theme).Run() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.17/pkg/views/webhook/edit/view.go new/harbor-cli-0.0.18/pkg/views/webhook/edit/view.go --- old/harbor-cli-0.0.17/pkg/views/webhook/edit/view.go 2026-02-10 16:12:59.000000000 +0100 +++ new/harbor-cli-0.0.18/pkg/views/webhook/edit/view.go 2026-03-03 15:36:07.000000000 +0100 @@ -15,6 +15,7 @@ import ( "errors" + "strings" "github.com/charmbracelet/huh" "github.com/goharbor/harbor-cli/pkg/utils" @@ -104,7 +105,15 @@ huh.NewInput().Title("Endpoint URL"). Value(&editView.EndpointURL). - Validate(utils.EmptyStringValidator("Endpoint URL")), + Validate(func(str string) error { + if strings.TrimSpace(str) == "" { + return errors.New("endpoint URL cannot be empty") + } + if err := utils.ValidateURL(str); err != nil { + return err + } + return nil + }), huh.NewInput(). Title("Auth Header"). ++++++ harbor-cli.obsinfo ++++++ --- /var/tmp/diff_new_pack.EyuIgN/_old 2026-03-05 17:24:34.762112400 +0100 +++ /var/tmp/diff_new_pack.EyuIgN/_new 2026-03-05 17:24:34.766112561 +0100 @@ -1,5 +1,5 @@ name: harbor-cli -version: 0.0.17 -mtime: 1770736379 -commit: dae683f89db201e45542098528309541702ef64f +version: 0.0.18 +mtime: 1772548567 +commit: 03ce614891616c6587ad6da1b5e3c0d51c0deaf2 ++++++ vendor.tar.gz ++++++ ++++ 76725 lines of diff (skipped)
