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-10-21 20:58:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/harbor-cli (Old) and /work/SRC/openSUSE:Factory/.harbor-cli.new.2252680 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "harbor-cli" Wed Oct 21 20:58:00 2026 rev:21 rq:1386680 version:0.0.27 Changes: -------- --- /work/SRC/openSUSE:Factory/harbor-cli/harbor-cli.changes 2026-08-28 19:50:27.244418604 +0200 +++ /work/SRC/openSUSE:Factory/.harbor-cli.new.2252680/harbor-cli.changes 2026-10-21 20:59:44.962672737 +0200 @@ -1,0 +2,25 @@ +Wed Oct 21 05:05:10 UTC 2026 - Johannes Kastl <[email protected]> + +- Update to version 0.0.27: + * build(deps): bump github.com/stretchr/testify from 1.11.1 to + 1.12.1 (#1093) + * build(deps): bump github.com/sirupsen/logrus from 1.9.4 to + 1.10.2 (#1094) + * build(deps): bump github.com/charmbracelet/x/ansi from 0.11.7 + to 0.11.8 (#1086) + * build(deps): bump golang.org/x/text from 0.40.0 to 0.41.0 + (#1087) + * build(deps): bump go.yaml.in/yaml/v4 from 4.0.0-rc.4 to + 4.0.0-rc.6 (#1088) + * fix(api): encode nested repository names in API paths (#1114) + * fix: TUI picker to set Aborted when user cancels (#1051) + * tests: Add unit test for API type structures (#616) + * fix(typos): Adherence to Go guidlines and typos (#983) + * fix: abort delete when project selection fails (#1104) + * build(deps): bump github.com/go-openapi/strfmt from 0.26.2 to + 0.27.0 (#977) + * build(deps): bump dagger/dagger-for-github from 7.0.6 to 8.4.1 + (#968) + * Update harbor-cli manifest + +------------------------------------------------------------------- Old: ---- harbor-cli-0.0.26.obscpio New: ---- harbor-cli-0.0.27.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ harbor-cli.spec ++++++ --- /var/tmp/diff_new_pack.ozrnmU/_old 2026-10-21 20:59:46.078719530 +0200 +++ /var/tmp/diff_new_pack.ozrnmU/_new 2026-10-21 20:59:46.079719572 +0200 @@ -19,7 +19,7 @@ %define executable_name harbor Name: harbor-cli -Version: 0.0.26 +Version: 0.0.27 Release: 0 Summary: CLI for the Harbor cloud native registry License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.ozrnmU/_old 2026-10-21 20:59:46.120721291 +0200 +++ /var/tmp/diff_new_pack.ozrnmU/_new 2026-10-21 20:59:46.124721459 +0200 @@ -3,7 +3,7 @@ <param name="url">https://github.com/goharbor/harbor-cli.git</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">refs/tags/v0.0.26</param> + <param name="revision">refs/tags/v0.0.27</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.ozrnmU/_old 2026-10-21 20:59:46.148722465 +0200 +++ /var/tmp/diff_new_pack.ozrnmU/_new 2026-10-21 20:59:46.153722675 +0200 @@ -3,6 +3,6 @@ <param name="url">https://github.com/goharbor/harbor-cli</param> <param name="changesrevision">19e9a10c142ab3bb44e234f8862981a423cfc37c</param></service><service name="tar_scm"> <param name="url">https://github.com/goharbor/harbor-cli.git</param> - <param name="changesrevision">8c20d16b2f19adaa1c3b5fa7a6113c09938f65bd</param></service></servicedata> + <param name="changesrevision">1af93ace562d69b2293fa71733d4a4f5bb3c1503</param></service></servicedata> (No newline at EOF) ++++++ harbor-cli-0.0.26.obscpio -> harbor-cli-0.0.27.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/bucket/harbor-cli.json new/harbor-cli-0.0.27/bucket/harbor-cli.json --- old/harbor-cli-0.0.26/bucket/harbor-cli.json 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/bucket/harbor-cli.json 2026-10-20 15:28:52.000000000 +0200 @@ -1,5 +1,5 @@ { - "version": "0.0.25", + "version": "0.0.26", "description": "A command-line interface for Harbor container registry.", "homepage": "https://github.com/goharbor/harbor-cli", "license": "Apache-2.0", @@ -8,13 +8,13 @@ }, "architecture": { "64bit": { - "url": "https://github.com/goharbor/harbor-cli/releases/download/v0.0.25/harbor-cli_0.0.25_windows_amd64.zip", - "hash": "3ab1671a00a18bcd96da7c4e0e5cea577b54e1fb1a2de6036848c28d6f53d9e2", + "url": "https://github.com/goharbor/harbor-cli/releases/download/v0.0.26/harbor-cli_0.0.26_windows_amd64.zip", + "hash": "3d50b8dd6eb6b59ccb617b4fe13136e805148c0d68eeefeab6639ad0d068b7c0", "bin": "harbor-cli.exe" }, "arm64": { - "url": "https://github.com/goharbor/harbor-cli/releases/download/v0.0.25/harbor-cli_0.0.25_windows_arm64.zip", - "hash": "ea1f911147e5b286c4d3b036c1d812b51c48bbe0436bee78de49ab75350700ec", + "url": "https://github.com/goharbor/harbor-cli/releases/download/v0.0.26/harbor-cli_0.0.26_windows_arm64.zip", + "hash": "d1afb4b25c8efcd304c64e104171ec1bd2bbf806275bfa0bda58e03af20384f8", "bin": "harbor-cli.exe" } }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/artifact/delete.go new/harbor-cli-0.0.27/cmd/harbor/root/artifact/delete.go --- old/harbor-cli-0.0.26/cmd/harbor/root/artifact/delete.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/artifact/delete.go 2026-10-20 15:28:52.000000000 +0200 @@ -19,7 +19,6 @@ "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" ) @@ -39,7 +38,7 @@ } else { projectName, err = prompt.GetProjectNameFromUser() if err != nil { - log.Errorf("failed to get project name: %v", utils.ParseHarborErrorMsg(err)) + return fmt.Errorf("failed to get project name: %v", utils.ParseHarborErrorMsg(err)) } repoName = prompt.GetRepoNameFromUser(projectName) reference = prompt.GetReferenceFromUser(repoName, projectName) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/artifact/delete_test.go new/harbor-cli-0.0.27/cmd/harbor/root/artifact/delete_test.go --- old/harbor-cli-0.0.26/cmd/harbor/root/artifact/delete_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/harbor-cli-0.0.27/cmd/harbor/root/artifact/delete_test.go 2026-10-20 15:28:52.000000000 +0200 @@ -0,0 +1,40 @@ +// Copyright Project Harbor Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package artifact_test + +import ( + "bytes" + "testing" + + "github.com/goharbor/harbor-cli/cmd/harbor/root/artifact" + helpers "github.com/goharbor/harbor-cli/test/helper" + "github.com/stretchr/testify/assert" +) + +func TestDeleteArtifactCommand_ProjectSelectionFailure(t *testing.T) { + helpers.SetMockKeyring(t) + data := helpers.Initialize(t, t.TempDir()) + defer helpers.ConfigCleanup(t, data) + + cmd := artifact.DeleteArtifactCommand() + + var buf bytes.Buffer + cmd.SetOut(&buf) + cmd.SetErr(&buf) + cmd.SetArgs([]string{}) + + err := cmd.Execute() + assert.Error(t, err) + assert.Contains(t, err.Error(), "failed to get project name") +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/artifact/label/list.go new/harbor-cli-0.0.27/cmd/harbor/root/artifact/label/list.go --- old/harbor-cli-0.0.26/cmd/harbor/root/artifact/label/list.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/artifact/label/list.go 2026-10-20 15:28:52.000000000 +0200 @@ -70,7 +70,7 @@ if len(args) > 0 { return fmt.Errorf("Invalid artifact reference format: %s", args[0]) } else { - return fmt.Errorf("Invalid artifact reference format: no arguments provided") + return fmt.Errorf("invalid artifact reference format: no arguments provided") } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/project/list.go new/harbor-cli-0.0.27/cmd/harbor/root/project/list.go --- old/harbor-cli-0.0.26/cmd/harbor/root/project/list.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/project/list.go 2026-10-20 15:28:52.000000000 +0200 @@ -49,7 +49,7 @@ } if private && public { - return fmt.Errorf("Cannot specify both --private and --public flags") + return fmt.Errorf("cannot specify both --private and --public flags") } var listFunc func(...api.ListFlags) (project.ListProjectsOK, error) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/project/member/update.go new/harbor-cli-0.0.27/cmd/harbor/root/project/member/update.go --- old/harbor-cli-0.0.26/cmd/harbor/root/project/member/update.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/project/member/update.go 2026-10-20 15:28:52.000000000 +0200 @@ -57,7 +57,7 @@ opts.ID = prompt.GetMemberIDFromUser(opts.ProjectNameOrID, memberName) if opts.ID == 0 { - return fmt.Errorf("No members found in project") + return fmt.Errorf("no members found in project") } } else { opts.ID, err = api.GetUsersIdByName(memberName) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/robot/create.go new/harbor-cli-0.0.27/cmd/harbor/root/robot/create.go --- old/harbor-cli-0.0.26/cmd/harbor/root/robot/create.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/robot/create.go 2026-10-20 15:28:52.000000000 +0200 @@ -347,7 +347,7 @@ if err != nil { errorCode := utils.ParseHarborErrorCode(err) if errorCode == "403" { - return fmt.Errorf("Permission denied: (Project) Admin privileges are required to execute this command.") + return fmt.Errorf("permission denied: (Project) Admin privileges are required to execute this command.") } else { return fmt.Errorf("failed to create robot: %v", utils.ParseHarborErrorMsg(err)) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/robot/delete.go new/harbor-cli-0.0.27/cmd/harbor/root/robot/delete.go --- old/harbor-cli-0.0.26/cmd/harbor/root/robot/delete.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/robot/delete.go 2026-10-20 15:28:52.000000000 +0200 @@ -62,7 +62,7 @@ if err != nil { errorCode := utils.ParseHarborErrorCode(err) if errorCode == "403" { - return fmt.Errorf("Permission denied: (Project) Admin privileges are required to execute this command.") + return fmt.Errorf("permission denied: (Project) Admin privileges are required to execute this command.") } else { return fmt.Errorf("failed to get robot: %v", utils.ParseHarborErrorMsg(err)) } @@ -78,7 +78,7 @@ if err != nil { errorCode := utils.ParseHarborErrorCode(err) if errorCode == "403" { - return fmt.Errorf("Permission denied: (Project) Admin privileges are required to execute this command.") + return fmt.Errorf("permission denied: (Project) Admin privileges are required to execute this command.") } else { return fmt.Errorf("failed to delete robot: %v", utils.ParseHarborErrorMsg(err)) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/robot/list.go new/harbor-cli-0.0.27/cmd/harbor/root/robot/list.go --- old/harbor-cli-0.0.26/cmd/harbor/root/robot/list.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/robot/list.go 2026-10-20 15:28:52.000000000 +0200 @@ -78,7 +78,7 @@ if err != nil { errorCode := utils.ParseHarborErrorCode(err) if errorCode == "403" { - return fmt.Errorf("Permission denied: (Project) Admin privileges are required to execute this command.") + return fmt.Errorf("permission denied: (Project) Admin privileges are required to execute this command.") } else { return fmt.Errorf("failed to list robots: %v", utils.ParseHarborErrorMsg(err)) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/robot/view.go new/harbor-cli-0.0.27/cmd/harbor/root/robot/view.go --- old/harbor-cli-0.0.26/cmd/harbor/root/robot/view.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/robot/view.go 2026-10-20 15:28:52.000000000 +0200 @@ -80,7 +80,7 @@ if err != nil { errorCode := utils.ParseHarborErrorCode(err) if errorCode == "403" { - return fmt.Errorf("Permission denied: (Project) Admin privileges are required to execute this command.") + return fmt.Errorf("permission denied: (Project) Admin privileges are required to execute this command.") } else { return fmt.Errorf("failed to get robot: %v", utils.ParseHarborErrorMsg(err)) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/tag/retention/delete.go new/harbor-cli-0.0.27/cmd/harbor/root/tag/retention/delete.go --- old/harbor-cli-0.0.26/cmd/harbor/root/tag/retention/delete.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/tag/retention/delete.go 2026-10-20 15:28:52.000000000 +0200 @@ -45,7 +45,7 @@ Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { if projectID != -1 && projectName != "" { - return fmt.Errorf("Cannot specify both --project-id and --project-name flags") + return fmt.Errorf("cannot specify both --project-id and --project-name flags") } if projectID == -1 && projectName == "" { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/tag/retention/list.go new/harbor-cli-0.0.27/cmd/harbor/root/tag/retention/list.go --- old/harbor-cli-0.0.26/cmd/harbor/root/tag/retention/list.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/tag/retention/list.go 2026-10-20 15:28:52.000000000 +0200 @@ -55,7 +55,7 @@ Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { if projectID != -1 && projectName != "" { - return fmt.Errorf("Cannot specify both --project-id and --project-name flags") + return fmt.Errorf("cannot specify both --project-id and --project-name flags") } if projectID == -1 && projectName == "" { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/user/create.go new/harbor-cli-0.0.27/cmd/harbor/root/user/create.go --- old/harbor-cli-0.0.26/cmd/harbor/root/user/create.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/user/create.go 2026-10-20 15:28:52.000000000 +0200 @@ -58,7 +58,7 @@ if err != nil { if isUnauthorizedError(err) { - return fmt.Errorf("Permission denied: Admin privileges are required to execute this command.") + return fmt.Errorf("permission denied: Admin privileges are required to execute this command.") } else { return fmt.Errorf("failed to create user: %v", err) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/user/delete.go new/harbor-cli-0.0.27/cmd/harbor/root/user/delete.go --- old/harbor-cli-0.0.26/cmd/harbor/root/user/delete.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/user/delete.go 2026-10-20 15:28:52.000000000 +0200 @@ -72,7 +72,7 @@ } if err := api.DeleteUser(userID); err != nil { if isUnauthorizedError(err) { - return fmt.Errorf("Permission denied: Admin privileges are required to execute this command.") + return fmt.Errorf("permission denied: Admin privileges are required to execute this command.") } else { return fmt.Errorf("failed to delete user: %v", err) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/user/elevate.go new/harbor-cli-0.0.27/cmd/harbor/root/user/elevate.go --- old/harbor-cli-0.0.26/cmd/harbor/root/user/elevate.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/user/elevate.go 2026-10-20 15:28:52.000000000 +0200 @@ -60,7 +60,7 @@ return err } if !confirm { - err = errors.New("User did not confirm elevation. Aborting command.") + err = errors.New("user did not confirm elevation. Aborting command.") log.Error(err.Error()) return err } @@ -68,7 +68,7 @@ err = elevateUserAPI(userId) if err != nil { if isUnauthorizedError(err) { - err = errors.New("Permission denied: Admin privileges are required to execute this command.") + err = errors.New("permission denied: Admin privileges are required to execute this command.") } else { err = fmt.Errorf("failed to elevate user: %v", err) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/cmd/harbor/root/user/list.go new/harbor-cli-0.0.27/cmd/harbor/root/user/list.go --- old/harbor-cli-0.0.26/cmd/harbor/root/user/list.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/cmd/harbor/root/user/list.go 2026-10-20 15:28:52.000000000 +0200 @@ -47,7 +47,7 @@ response, err := api.ListUsers(opts) if err != nil { if isUnauthorizedError(err) { - return fmt.Errorf("Permission denied: Admin privileges are required to execute this command.") + return fmt.Errorf("permission denied: Admin privileges are required to execute this command.") } return fmt.Errorf("failed to list users: %v", err) } @@ -63,7 +63,7 @@ response, err := api.ListUsers(opts) if err != nil { if isUnauthorizedError(err) { - return fmt.Errorf("Permission denied: Admin privileges are required to execute this command.") + return fmt.Errorf("permission denied: Admin privileges are required to execute this command.") } return fmt.Errorf("failed to list users: %v", err) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/go.mod new/harbor-cli-0.0.27/go.mod --- old/harbor-cli-0.0.26/go.mod 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/go.mod 2026-10-20 15:28:52.000000000 +0200 @@ -8,16 +8,16 @@ github.com/charmbracelet/bubbletea v1.3.10 github.com/charmbracelet/huh v1.0.0 github.com/charmbracelet/lipgloss v1.1.0 - github.com/charmbracelet/x/ansi v0.11.7 + github.com/charmbracelet/x/ansi v0.11.8 github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 github.com/sahilm/fuzzy v0.1.3 - github.com/sirupsen/logrus v1.9.4 + github.com/sirupsen/logrus v1.10.2 github.com/spf13/cobra v1.10.2 github.com/spf13/viper v1.21.0 - github.com/stretchr/testify v1.11.1 + github.com/stretchr/testify v1.12.1 github.com/zalando/go-keyring v0.2.8 - go.yaml.in/yaml/v4 v4.0.0-rc.4 - golang.org/x/term v0.44.0 + go.yaml.in/yaml/v4 v4.0.0-rc.6 + golang.org/x/term v0.45.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -41,14 +41,13 @@ github.com/lucasb-eyer/go-colorful v1.4.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-localereader v0.0.1 // indirect - github.com/mattn/go-runewidth v0.0.23 // indirect + github.com/mattn/go-runewidth v0.0.24 // indirect github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/termenv v0.16.0 // indirect github.com/oklog/ulid/v2 v2.1.1 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.11.0 // indirect @@ -59,10 +58,10 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/otel/sdk v1.35.0 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect + go.yaml.in/yaml/v3 v3.0.5 // indirect golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect - golang.org/x/net v0.53.0 // indirect - golang.org/x/sync v0.20.0 // indirect + golang.org/x/net v0.57.0 // indirect + golang.org/x/sync v0.22.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -70,13 +69,13 @@ github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/analysis v0.23.0 // indirect - github.com/go-openapi/errors v0.22.7 // indirect + github.com/go-openapi/errors v0.22.8 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/loads v0.22.0 // indirect github.com/go-openapi/runtime v0.28.0 // indirect github.com/go-openapi/spec v0.21.0 // indirect - github.com/go-openapi/strfmt v0.26.2 + github.com/go-openapi/strfmt v0.27.0 github.com/go-openapi/swag v0.23.0 // indirect github.com/go-openapi/validate v0.24.0 // indirect github.com/goharbor/go-client v0.213.1 @@ -89,8 +88,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.46.0 // indirect - golang.org/x/text v0.37.0 + golang.org/x/sys v0.47.0 // indirect + golang.org/x/text v0.41.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.26/go.sum new/harbor-cli-0.0.27/go.sum --- old/harbor-cli-0.0.26/go.sum 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/go.sum 2026-10-20 15:28:52.000000000 +0200 @@ -18,8 +18,8 @@ github.com/charmbracelet/huh v1.0.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.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI= -github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ= +github.com/charmbracelet/x/ansi v0.11.8 h1:JMFwp0CgDC2+jcOB162HH5k7I3FVbgFSMMYg7dSPBQQ= +github.com/charmbracelet/x/ansi v0.11.8/go.mod h1:ZNN+3mXny/516oTQPLMPIBeSINvNJJQ8uQXDgbeJxY0= 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= @@ -64,8 +64,8 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU= github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo= -github.com/go-openapi/errors v0.22.7 h1:JLFBGC0Apwdzw3484MmBqspjPbwa2SHvpDm0u5aGhUA= -github.com/go-openapi/errors v0.22.7/go.mod h1://QW6SD9OsWtH6gHllUCddOXDL0tk0ZGNYHwsw4sW3w= +github.com/go-openapi/errors v0.22.8 h1:oP7sW7TWc3wFFjrzzj0nI83H2qMBkNjNfSd+XRejk/I= +github.com/go-openapi/errors v0.22.8/go.mod h1:BuUoHcYrU6E7V9gfj1I5wLQqgtIHnup/alXZ8KdgQ0w= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= @@ -76,12 +76,12 @@ github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc= github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= -github.com/go-openapi/strfmt v0.26.2 h1:ysjheCh4i1rmFEo2LanhELDNucNzfWTZhUDKgWWPaFM= -github.com/go-openapi/strfmt v0.26.2/go.mod h1:fXh1e449cyUn2NYuz+wb3wARBUdMl7qPEZwX00nqivY= +github.com/go-openapi/strfmt v0.27.0 h1:kbcTeaD9TXuXD0hhMXzuYa1sdTo6+dWGvwjW93E80IM= +github.com/go-openapi/strfmt v0.27.0/go.mod h1:s/qhDqfY72irigXUGJmtgid2Rm+3tnz3k8hZaRmvWYc= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-openapi/testify/v2 v2.4.2 h1:tiByHpvE9uHrrKjOszax7ZvKB7QOgizBWGBLuq0ePx4= -github.com/go-openapi/testify/v2 v2.4.2/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= +github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug= +github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58= github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ= github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= @@ -114,8 +114,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= -github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw= -github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/mattn/go-runewidth v0.0.24 h1:cpokDiIn0MGnhdHwuWnJBITySJ20QyNGnY2kR/ay2DU= +github.com/mattn/go-runewidth v0.0.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= @@ -132,8 +132,6 @@ github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= @@ -144,8 +142,8 @@ github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= github.com/sahilm/fuzzy v0.1.3 h1:juByESSS32nVD81vr6tHmKmA/8zde7gE+x5CLxrzXPU= github.com/sahilm/fuzzy v0.1.3/go.mod h1:au6//VbVSqu6DFrkL2CfjlJ5iURpNCPeE+1GwY3XsT8= -github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= -github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= +github.com/sirupsen/logrus v1.10.2 h1:G2SED73/qrAu6YwbdxOD6peLkCBI3z7L+ykJFTXJBBo= +github.com/sirupsen/logrus v1.10.2/go.mod h1:SLEg8TqYulVKKfIGHldVp2K2aYz2DKSVBq4g/H5bR7Q= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= @@ -160,11 +158,11 @@ github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= +github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= +github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= @@ -181,24 +179,25 @@ go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= -go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -go.yaml.in/yaml/v4 v4.0.0-rc.4 h1:UP4+v6fFrBIb1l934bDl//mmnoIZEDK0idg1+AIvX5U= -go.yaml.in/yaml/v4 v4.0.0-rc.4/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= +go.yaml.in/yaml/v4 v4.0.0-rc.6 h1:1h7H1ohdUh93/FyE4YaDa1Zh64K6VVbjF4K6WUxMtH4= +go.yaml.in/yaml/v4 v4.0.0-rc.6/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo= golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= -golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= +golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= +golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= +golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= 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.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= -golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= -golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= -golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= -golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= +golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= +golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= +golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= 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.26/pkg/api/artifact_handler.go new/harbor-cli-0.0.27/pkg/api/artifact_handler.go --- old/harbor-cli-0.0.26/pkg/api/artifact_handler.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/pkg/api/artifact_handler.go 2026-10-20 15:28:52.000000000 +0200 @@ -32,7 +32,7 @@ _, err = client.Artifact.DeleteArtifact(ctx, &artifact.DeleteArtifactParams{ ProjectName: projectName, - RepositoryName: repoName, + RepositoryName: encodeRepoName(repoName), Reference: reference, }) if err != nil { @@ -54,7 +54,7 @@ response, err = client.Artifact.GetArtifact(ctx, &artifact.GetArtifactParams{ ProjectName: projectName, - RepositoryName: repoName, + RepositoryName: encodeRepoName(repoName), Reference: reference, WithLabel: &withLabels, }) @@ -79,7 +79,7 @@ } response, err := client.Artifact.ListArtifacts(ctx, &artifact.ListArtifactsParams{ ProjectName: projectName, - RepositoryName: repoName, + RepositoryName: encodeRepoName(repoName), Page: &listFlags.Page, PageSize: &listFlags.PageSize, Q: &listFlags.Q, @@ -101,7 +101,7 @@ _, err = client.Scan.ScanArtifact(ctx, &scan.ScanArtifactParams{ ProjectName: projectName, - RepositoryName: repoName, + RepositoryName: encodeRepoName(repoName), Reference: reference, }) if err != nil { @@ -122,7 +122,7 @@ _, err = client.Scan.StopScanArtifact(ctx, &scan.StopScanArtifactParams{ ProjectName: projectName, - RepositoryName: repoName, + RepositoryName: encodeRepoName(repoName), Reference: reference, }) if err != nil { @@ -143,7 +143,7 @@ _, err = client.Artifact.DeleteTag(ctx, &artifact.DeleteTagParams{ ProjectName: projectName, - RepositoryName: repoName, + RepositoryName: encodeRepoName(repoName), Reference: reference, TagName: tag, }) @@ -165,7 +165,7 @@ resp, err := client.Artifact.ListTags(ctx, &artifact.ListTagsParams{ ProjectName: projectName, - RepositoryName: repoName, + RepositoryName: encodeRepoName(repoName), Reference: reference, }) @@ -185,7 +185,7 @@ } _, err = client.Artifact.CreateTag(ctx, &artifact.CreateTagParams{ ProjectName: projectName, - RepositoryName: repoName, + RepositoryName: encodeRepoName(repoName), Reference: reference, Tag: &models.Tag{ Name: tagName, @@ -209,7 +209,7 @@ response, err = client.Artifact.AddLabel(ctx, &artifact.AddLabelParams{ ProjectName: projectName, - RepositoryName: repoName, + RepositoryName: encodeRepoName(repoName), Reference: reference, Label: label, }) @@ -232,7 +232,7 @@ response, err = client.Artifact.RemoveLabel(ctx, &artifact.RemoveLabelParams{ ProjectName: projectName, - RepositoryName: repoName, + RepositoryName: encodeRepoName(repoName), Reference: reference, LabelID: labelID, }) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/pkg/api/quota_handler.go new/harbor-cli-0.0.27/pkg/api/quota_handler.go --- old/harbor-cli-0.0.26/pkg/api/quota_handler.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/pkg/api/quota_handler.go 2026-10-20 15:28:52.000000000 +0200 @@ -133,5 +133,5 @@ id, _ := refMap["id"] return fmt.Sprintf("%v", id), nil } - return "", fmt.Errorf("Error: Ref is not of expected type") + return "", fmt.Errorf("error: Ref is not of expected type") } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/pkg/api/repository_handler.go new/harbor-cli-0.0.27/pkg/api/repository_handler.go --- old/harbor-cli-0.0.26/pkg/api/repository_handler.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/pkg/api/repository_handler.go 2026-10-20 15:28:52.000000000 +0200 @@ -15,6 +15,7 @@ import ( "fmt" + "net/url" "github.com/goharbor/go-client/pkg/sdk/v2.0/client/repository" "github.com/goharbor/go-client/pkg/sdk/v2.0/client/search" @@ -22,6 +23,13 @@ "github.com/goharbor/harbor-cli/pkg/utils" ) +// encodeRepoName prepares a repository name for the repository_name path +// parameter. Harbor expects a slash in it to be encoded twice +// (a/b -> a%2Fb -> a%252Fb) and the client only encodes path parameters once. +func encodeRepoName(repoName string) string { + return url.PathEscape(repoName) +} + func RepoDelete(projectNameOrID, repoName string, useProjectID bool) error { ctx, client, err := utils.ContextWithClient() if err != nil { @@ -36,7 +44,7 @@ } projectName = project.Payload.Name } - _, err = client.Repository.DeleteRepository(ctx, &repository.DeleteRepositoryParams{ProjectName: projectName, RepositoryName: repoName}) + _, err = client.Repository.DeleteRepository(ctx, &repository.DeleteRepositoryParams{ProjectName: projectName, RepositoryName: encodeRepoName(repoName)}) if err != nil { return err @@ -53,7 +61,7 @@ return response, err } - response, err = client.Repository.GetRepository(ctx, &repository.GetRepositoryParams{ProjectName: projectName, RepositoryName: repoName}) + response, err = client.Repository.GetRepository(ctx, &repository.GetRepositoryParams{ProjectName: projectName, RepositoryName: encodeRepoName(repoName)}) if err != nil { return response, err @@ -129,7 +137,7 @@ _, err = client.Repository.UpdateRepository(ctx, &repository.UpdateRepositoryParams{ ProjectName: projectName, - RepositoryName: repoName, + RepositoryName: encodeRepoName(repoName), Repository: repo, }) if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/pkg/api/repository_handler_test.go new/harbor-cli-0.0.27/pkg/api/repository_handler_test.go --- old/harbor-cli-0.0.26/pkg/api/repository_handler_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/harbor-cli-0.0.27/pkg/api/repository_handler_test.go 2026-10-20 15:28:52.000000000 +0200 @@ -0,0 +1,127 @@ +// Copyright Project Harbor Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package api + +import ( + "net/http" + "net/http/httptest" + "sync" + "testing" + + "github.com/goharbor/go-client/pkg/harbor" + "github.com/goharbor/harbor-cli/pkg/utils" + "github.com/stretchr/testify/assert" +) + +// useTestServer points the shared Harbor client at a local server that +// records the escaped request path and answers with the given body. The +// returned function reads the last recorded path. +func useTestServer(t *testing.T, body string) func() string { + t.Helper() + + var mu sync.Mutex + var gotPath string + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + mu.Lock() + gotPath = r.URL.EscapedPath() + mu.Unlock() + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(body)) + })) + + utils.ClientOnce = sync.Once{} + utils.ClientOnce.Do(func() {}) + utils.ClientInstance = utils.GetClientByConfig(&harbor.ClientSetConfig{URL: srv.URL}) + utils.ClientErr = nil + + t.Cleanup(func() { + srv.Close() + utils.ClientOnce = sync.Once{} + utils.ClientInstance = nil + utils.ClientErr = nil + }) + + return func() string { + mu.Lock() + defer mu.Unlock() + return gotPath + } +} + +// Harbor expects a slash in repository_name to be encoded twice +// (a/b -> a%2Fb -> a%252Fb), otherwise the request does not reach the +// repository handler when Harbor runs behind its nginx proxy. +func TestRepositoryNameIsEncodedInPath(t *testing.T) { + tests := []struct { + name string + body string + call func() error + wantPath string + }{ + { + name: "list artifacts of nested repository", + body: "[]", + call: func() error { + _, err := ListArtifact("library", "team/app") + return err + }, + wantPath: "/api/v2.0/projects/library/repositories/team%252Fapp/artifacts", + }, + { + name: "view artifact of nested repository", + body: "{}", + call: func() error { + _, err := ViewArtifact("library", "team/app", "latest", false) + return err + }, + wantPath: "/api/v2.0/projects/library/repositories/team%252Fapp/artifacts/latest", + }, + { + name: "list tags of nested repository", + body: "[]", + call: func() error { + _, err := ListTags("library", "team/app", "latest") + return err + }, + wantPath: "/api/v2.0/projects/library/repositories/team%252Fapp/artifacts/latest/tags", + }, + { + name: "view nested repository", + body: "{}", + call: func() error { + _, err := RepoView("library", "team/app") + return err + }, + wantPath: "/api/v2.0/projects/library/repositories/team%252Fapp", + }, + { + name: "list artifacts of single-level repository", + body: "[]", + call: func() error { + _, err := ListArtifact("library", "nginx") + return err + }, + wantPath: "/api/v2.0/projects/library/repositories/nginx/artifacts", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotPath := useTestServer(t, tt.body) + + assert.NoError(t, tt.call()) + assert.Equal(t, tt.wantPath, gotPath()) + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/pkg/api/retention_handler.go new/harbor-cli-0.0.27/pkg/api/retention_handler.go --- old/harbor-cli-0.0.26/pkg/api/retention_handler.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/pkg/api/retention_handler.go 2026-10-20 15:28:52.000000000 +0200 @@ -114,7 +114,7 @@ } if response.Payload.Metadata == nil || response.Payload.Metadata.RetentionID == nil { - return "", errors.New("No retention policy exists for this project") + return "", errors.New("no retention policy exists for this project") } retentionid := *response.Payload.Metadata.RetentionID diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/pkg/api/types_test.go new/harbor-cli-0.0.27/pkg/api/types_test.go --- old/harbor-cli-0.0.26/pkg/api/types_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/harbor-cli-0.0.27/pkg/api/types_test.go 2026-10-20 15:28:52.000000000 +0200 @@ -0,0 +1,139 @@ +// Copyright Project Harbor Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package api_test + +import ( + "testing" + + "github.com/goharbor/harbor-cli/pkg/api" + "github.com/stretchr/testify/assert" +) + +// TestListFlags validates the ListFlags structure for proper pagination defaults +func TestListFlags(t *testing.T) { + t.Run("default values", func(t *testing.T) { + var flags api.ListFlags + + assert.Equal(t, int64(0), flags.ProjectID) + assert.Equal(t, int64(0), flags.Page) + assert.Equal(t, int64(0), flags.PageSize) + assert.Equal(t, "", flags.Scope) + assert.Equal(t, "", flags.Name) + assert.Equal(t, "", flags.Q) + assert.Equal(t, "", flags.Sort) + assert.False(t, flags.Public) + }) + + t.Run("custom pagination", func(t *testing.T) { + flags := api.ListFlags{ + ProjectID: 10, + Page: 1, + PageSize: 50, + Scope: "project", + Name: "test", + Q: "admin", + Sort: "name", + Public: true, + } + + assert.Equal(t, int64(10), flags.ProjectID) + assert.Equal(t, int64(1), flags.Page) + assert.Equal(t, int64(50), flags.PageSize) + assert.Equal(t, "project", flags.Scope) + assert.Equal(t, "test", flags.Name) + assert.Equal(t, "admin", flags.Q) + assert.Equal(t, "name", flags.Sort) + assert.True(t, flags.Public) + }) +} + +// TestListMemberOptions validates member listing options structure +func TestListMemberOptions(t *testing.T) { + t.Run("valid member options", func(t *testing.T) { + opts := api.ListMemberOptions{ + XIsResourceName: true, + ProjectNameOrID: "library", + EntityName: "testuser", + Page: 1, + PageSize: 10, + } + + assert.True(t, opts.XIsResourceName) + assert.Equal(t, "library", opts.ProjectNameOrID) + assert.Equal(t, "testuser", opts.EntityName) + assert.Equal(t, int64(1), opts.Page) + assert.Equal(t, int64(10), opts.PageSize) + }) + + t.Run("project by ID vs name", func(t *testing.T) { + byName := api.ListMemberOptions{ + XIsResourceName: true, + ProjectNameOrID: "my-project", + } + + byID := api.ListMemberOptions{ + XIsResourceName: false, + ProjectNameOrID: "123", + } + + assert.True(t, byName.XIsResourceName) + assert.Equal(t, "my-project", byName.ProjectNameOrID) + assert.False(t, byID.XIsResourceName) + assert.Equal(t, "123", byID.ProjectNameOrID) + }) +} + +// TestUpdateMemberOptions validates member update options structure +func TestUpdateMemberOptions(t *testing.T) { + t.Run("valid update options", func(t *testing.T) { + opts := api.UpdateMemberOptions{ + XIsResourceName: true, + ProjectNameOrID: "library", + ID: 123, + RoleID: nil, + } + + assert.True(t, opts.XIsResourceName) + assert.Equal(t, "library", opts.ProjectNameOrID) + assert.Equal(t, int64(123), opts.ID) + assert.Nil(t, opts.RoleID) + }) +} + +// TestGetMemberOptions validates member retrieval options structure +func TestGetMemberOptions(t *testing.T) { + t.Run("get member by ID", func(t *testing.T) { + opts := api.GetMemberOptions{ + XIsResourceName: false, + ProjectNameOrID: "42", + ID: 100, + } + + assert.False(t, opts.XIsResourceName) + assert.Equal(t, "42", opts.ProjectNameOrID) + assert.Equal(t, int64(100), opts.ID) + }) + + t.Run("get member by name", func(t *testing.T) { + opts := api.GetMemberOptions{ + XIsResourceName: true, + ProjectNameOrID: "test-project", + ID: 200, + } + + assert.True(t, opts.XIsResourceName) + assert.Equal(t, "test-project", opts.ProjectNameOrID) + assert.Equal(t, int64(200), opts.ID) + }) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/pkg/views/base/selection/model.go new/harbor-cli-0.0.27/pkg/views/base/selection/model.go --- old/harbor-cli-0.0.26/pkg/views/base/selection/model.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/pkg/views/base/selection/model.go 2026-10-20 15:28:52.000000000 +0200 @@ -83,6 +83,15 @@ case tea.KeyMsg: switch keypress := msg.String(); keypress { + case "ctrl+c": + m.Aborted = true + return m, tea.Quit + case "q", "esc": + if m.List.FilterState() == list.Filtering { + break // let the list handle it (esc exits filter mode, q types "q") + } + m.Aborted = true + return m, tea.Quit case "enter": if m.List.FilterState() != list.Filtering { i, ok := m.List.SelectedItem().(Item) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/pkg/views/member/create/view.go new/harbor-cli-0.0.27/pkg/views/member/create/view.go --- old/harbor-cli-0.0.26/pkg/views/member/create/view.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/pkg/views/member/create/view.go 2026-10-20 15:28:52.000000000 +0200 @@ -88,7 +88,7 @@ Value(&createView.MemberUser.Username). Validate(func(str string) error { if str == "" { - return errors.New("Username cannot be empty.") + return errors.New("username cannot be empty.") } if !utils.ValidateUserName(str) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.26/pkg/views/quota/list/view.go new/harbor-cli-0.0.27/pkg/views/quota/list/view.go --- old/harbor-cli-0.0.26/pkg/views/quota/list/view.go 2026-08-18 15:36:47.000000000 +0200 +++ new/harbor-cli-0.0.27/pkg/views/quota/list/view.go 2026-10-20 15:28:52.000000000 +0200 @@ -40,7 +40,7 @@ ownerName, _ := refMap["owner_name"].(string) return projectName, ownerName, nil } - return "", "", fmt.Errorf("Error: Ref is not of expected type") + return "", "", fmt.Errorf("error: Ref is not of expected type") } // Function to convert bytes to human-readable storage format ++++++ harbor-cli.obsinfo ++++++ --- /var/tmp/diff_new_pack.ozrnmU/_old 2026-10-21 20:59:46.645743304 +0200 +++ /var/tmp/diff_new_pack.ozrnmU/_new 2026-10-21 20:59:46.651743556 +0200 @@ -1,5 +1,5 @@ name: harbor-cli -version: 0.0.26 -mtime: 1787060207 -commit: 8c20d16b2f19adaa1c3b5fa7a6113c09938f65bd +version: 0.0.27 +mtime: 1792502932 +commit: 1af93ace562d69b2293fa71733d4a4f5bb3c1503 ++++++ vendor.tar.gz ++++++ ++++ 67931 lines of diff (skipped)
