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)

Reply via email to