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-07-08 17:48:12 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/harbor-cli (Old) and /work/SRC/openSUSE:Factory/.harbor-cli.new.1982 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "harbor-cli" Wed Jul 8 17:48:12 2026 rev:18 rq:1364554 version:0.0.24 Changes: -------- --- /work/SRC/openSUSE:Factory/harbor-cli/harbor-cli.changes 2026-07-01 16:50:14.157407167 +0200 +++ /work/SRC/openSUSE:Factory/.harbor-cli.new.1982/harbor-cli.changes 2026-07-08 17:48:20.686081549 +0200 @@ -1,0 +2,13 @@ +Wed Jul 08 05:11:14 UTC 2026 - Johannes Kastl <[email protected]> + +- Update to version 0.0.24: + * docs: update Go and Windows build instructions in + CONTRIBUTING.md(#1028) + * fix(utils): Refactor CamelCaseToHR function (#861) + * fix(api): propagate errors from GetLabel instead of returning + nil (#1004) + * fix(info): prevent nil pointer panic when volumes payload is + absent (#1032) + * Update harbor-cli manifest + +------------------------------------------------------------------- Old: ---- harbor-cli-0.0.23.obscpio New: ---- harbor-cli-0.0.24.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ harbor-cli.spec ++++++ --- /var/tmp/diff_new_pack.ZonKLM/_old 2026-07-08 17:48:23.478178325 +0200 +++ /var/tmp/diff_new_pack.ZonKLM/_new 2026-07-08 17:48:23.478178325 +0200 @@ -19,7 +19,7 @@ %define executable_name harbor Name: harbor-cli -Version: 0.0.23 +Version: 0.0.24 Release: 0 Summary: CLI for the Harbor cloud native registry License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.ZonKLM/_old 2026-07-08 17:48:23.522179851 +0200 +++ /var/tmp/diff_new_pack.ZonKLM/_new 2026-07-08 17:48:23.526179990 +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.23</param> + <param name="revision">refs/tags/v0.0.24</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.ZonKLM/_old 2026-07-08 17:48:23.558181099 +0200 +++ /var/tmp/diff_new_pack.ZonKLM/_new 2026-07-08 17:48:23.562181238 +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">8555428e1e9005dc662147afc80c613e9855763a</param></service></servicedata> + <param name="changesrevision">61dd0ce3b252ff4a69f9beee8bbf4ea3d12ea38c</param></service></servicedata> (No newline at EOF) ++++++ harbor-cli-0.0.23.obscpio -> harbor-cli-0.0.24.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.23/CONTRIBUTING.md new/harbor-cli-0.0.24/CONTRIBUTING.md --- old/harbor-cli-0.0.23/CONTRIBUTING.md 2026-06-30 15:26:31.000000000 +0200 +++ new/harbor-cli-0.0.24/CONTRIBUTING.md 2026-07-07 15:46:05.000000000 +0200 @@ -34,7 +34,7 @@ ### Build from Source -Make sure [Go](https://go.dev/) is installed (≥ v1.24). +Make sure [Go](https://go.dev/) is installed (≥ v1.26.3), matching the version declared in `go.mod`. ```bash git clone https://github.com/goharbor/harbor-cli.git && cd harbor-cli @@ -42,6 +42,14 @@ ./harbor-cli --help ``` +On Windows, use PowerShell commands and build the executable with the `.exe` suffix: + +```powershell +git clone https://github.com/goharbor/harbor-cli.git; cd harbor-cli +go build -o bin/harbor-cli.exe cmd/harbor/main.go +.\bin\harbor-cli.exe --help +``` + Alternatively, use [Dagger](https://docs.dagger.io/) for isolated builds: ```bash diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.23/bucket/harbor-cli.json new/harbor-cli-0.0.24/bucket/harbor-cli.json --- old/harbor-cli-0.0.23/bucket/harbor-cli.json 2026-06-30 15:26:31.000000000 +0200 +++ new/harbor-cli-0.0.24/bucket/harbor-cli.json 2026-07-07 15:46:05.000000000 +0200 @@ -1,5 +1,5 @@ { - "version": "0.0.20", + "version": "0.0.23", "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.20/harbor-cli_0.0.20_windows_amd64.zip", - "hash": "eba4e5c07d9c22b0591de22c7fd295f913b15165a6fd90bd085d3e20eef596d8", + "url": "https://github.com/goharbor/harbor-cli/releases/download/v0.0.23/harbor-cli_0.0.23_windows_amd64.zip", + "hash": "87d6a5045fb0d492ca9fbd5f1c95ebcc3e9b6060d5d0a99abe21f792a769e18c", "bin": "harbor-cli.exe" }, "arm64": { - "url": "https://github.com/goharbor/harbor-cli/releases/download/v0.0.20/harbor-cli_0.0.20_windows_arm64.zip", - "hash": "eba4e5c07d9c22b0591de22c7fd295f913b15165a6fd90bd085d3e20eef596d8", + "url": "https://github.com/goharbor/harbor-cli/releases/download/v0.0.23/harbor-cli_0.0.23_windows_arm64.zip", + "hash": "8b093ffeabd2622fc58d3416bbd006febb732190465263bf8caed33bfe17578c", "bin": "harbor-cli.exe" } }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.23/cmd/harbor/root/artifact/label/add.go new/harbor-cli-0.0.24/cmd/harbor/root/artifact/label/add.go --- old/harbor-cli-0.0.23/cmd/harbor/root/artifact/label/add.go 2026-06-30 15:26:31.000000000 +0200 +++ new/harbor-cli-0.0.24/cmd/harbor/root/artifact/label/add.go 2026-07-07 15:46:05.000000000 +0200 @@ -88,7 +88,10 @@ } } - label := api.GetLabel(labelID) + label, err := api.GetLabel(labelID) + if err != nil { + return fmt.Errorf("failed to get label: %v", utils.ParseHarborErrorMsg(err)) + } if _, err := api.AddLabelArtifact(projectName, repoName, reference, label); err != nil { return fmt.Errorf("failed to add label to artifact: %v", utils.ParseHarborErrorMsg(err)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.23/cmd/harbor/root/labels/update.go new/harbor-cli-0.0.24/cmd/harbor/root/labels/update.go --- old/harbor-cli-0.0.23/cmd/harbor/root/labels/update.go 2026-06-30 15:26:31.000000000 +0200 +++ new/harbor-cli-0.0.24/cmd/harbor/root/labels/update.go 2026-07-07 15:46:05.000000000 +0200 @@ -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/label/update" "github.com/spf13/cobra" ) @@ -68,9 +69,9 @@ return fmt.Errorf("failed to parse label id: %v", err) } - existingLabel := api.GetLabel(labelId) - if existingLabel == nil { - return fmt.Errorf("label is not found") + existingLabel, err := api.GetLabel(labelId) + if err != nil { + return fmt.Errorf("failed to get label: %v", utils.ParseHarborErrorMsg(err)) } updateView := &models.Label{ Name: existingLabel.Name, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.23/pkg/api/label_handler.go new/harbor-cli-0.0.24/pkg/api/label_handler.go --- old/harbor-cli-0.0.23/pkg/api/label_handler.go 2026-06-30 15:26:31.000000000 +0200 +++ new/harbor-cli-0.0.24/pkg/api/label_handler.go 2026-07-07 15:46:05.000000000 +0200 @@ -107,17 +107,22 @@ return nil } -func GetLabel(labelid int64) *models.Label { +func GetLabel(labelid int64) (*models.Label, error) { ctx, client, err := utils.ContextWithClient() if err != nil { - return nil + return nil, err } response, err := client.Label.GetLabelByID(ctx, &label.GetLabelByIDParams{LabelID: labelid}) if err != nil { - return nil + return nil, err } - return response.GetPayload() + payload := response.GetPayload() + if payload == nil || payload.ID == 0 { + return nil, fmt.Errorf("label with id %d not found", labelid) + } + + return payload, nil } func GetLabelIdByName(labelName string, opts ListFlags) (int64, error) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.23/pkg/utils/helper.go new/harbor-cli-0.0.24/pkg/utils/helper.go --- old/harbor-cli-0.0.23/pkg/utils/helper.go 2026-06-30 15:26:31.000000000 +0200 +++ new/harbor-cli-0.0.24/pkg/utils/helper.go 2026-07-07 15:46:05.000000000 +0200 @@ -232,28 +232,32 @@ } } -// This function covert camelCase to Human Readable form +// CamelCaseToHR converts camelCase to Human Readable form. func CamelCaseToHR(s string) string { var result []string var word []rune + runes := []rune(s) - for i, r := range s { + for i, r := range runes { if unicode.IsUpper(r) && i > 0 { - result = append(result, string(word)) - word = []rune{r} - } else { - word = append(word, r) + prev := runes[i-1] + nextIsLower := i+1 < len(runes) && unicode.IsLower(runes[i+1]) + if prev != ' ' && (!unicode.IsUpper(prev) || nextIsLower) { + result = append(result, string(word)) + word = []rune{r} + continue + } } + word = append(word, r) } - result = append(result, string(word)) // Capitalize the first letter of each word - for i, word := range result { - if len(word) > 0 { - runes := []rune(word) - runes[0] = unicode.ToUpper(runes[0]) - result[i] = string(runes) + for i, wordStr := range result { + if len(wordStr) > 0 { + wRunes := []rune(wordStr) + wRunes[0] = unicode.ToUpper(wRunes[0]) + result[i] = string(wRunes) } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.23/pkg/utils/helper_test.go new/harbor-cli-0.0.24/pkg/utils/helper_test.go --- old/harbor-cli-0.0.23/pkg/utils/helper_test.go 2026-06-30 15:26:31.000000000 +0200 +++ new/harbor-cli-0.0.24/pkg/utils/helper_test.go 2026-07-07 15:46:05.000000000 +0200 @@ -220,3 +220,32 @@ err = utils.PrintFormat(obj, "xml") assert.Error(t, err) } + +func TestCamelCaseToHR(t *testing.T) { + tests := []struct { + name string + input string + expected string + }{ + {"basic camelCase", "camelCase", "Camel Case"}, + {"basic PascalCase", "PascalCase", "Pascal Case"}, + {"single word", "simple", "Simple"}, + {"existing spaces", "already Human Readable", "Already Human Readable"}, + {"uppercase acronym", "ID", "ID"}, + {"prefixed acronym", "UserID", "User ID"}, + {"complex acronym", "JSONData", "JSON Data"}, + {"all caps", "ALLCAPS", "ALLCAPS"}, + {"all lower", "alllower", "Alllower"}, + {"mixed case", "MixedUPPERAndLower", "Mixed UPPER And Lower"}, + {"lowercase prefix", "httpError", "Http Error"}, + {"uppercase acronym", "HTTPError", "HTTP Error"}, + {"empty string", "", ""}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := utils.CamelCaseToHR(tt.input) + assert.Equal(t, tt.expected, result) + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.23/pkg/utils/utils.go new/harbor-cli-0.0.24/pkg/utils/utils.go --- old/harbor-cli-0.0.23/pkg/utils/utils.go 2026-06-30 15:26:31.000000000 +0200 +++ new/harbor-cli-0.0.24/pkg/utils/utils.go 2026-07-07 15:46:05.000000000 +0200 @@ -208,14 +208,6 @@ return strings.Join(words, " ") } -func Capitalize(s string) string { - if s == "" { - return "" - } - return s - // trings.ToUpper(s[:1]) + s[1:] -} - // GetUserIdFromUser retrieves the user ID from the current user context using viper and the Harbor client. func GetUserIdFromUser() int64 { credentialName := viper.GetString("current-credential-name") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.23/pkg/views/info/list/view.go new/harbor-cli-0.0.24/pkg/views/info/list/view.go --- old/harbor-cli-0.0.23/pkg/views/info/list/view.go 2026-06-30 15:26:31.000000000 +0200 +++ new/harbor-cli-0.0.24/pkg/views/info/list/view.go 2026-07-07 15:46:05.000000000 +0200 @@ -71,13 +71,13 @@ SystemInfo: generalInfo, VolumeInfo: &Volumes{ Free: func() uint64 { - if volumes.Storage != nil && len(volumes.Storage) > 0 { + if volumes != nil && volumes.Storage != nil && len(volumes.Storage) > 0 { return volumes.Storage[0].Free } return 0 }(), Total: func() uint64 { - if volumes.Storage != nil && len(volumes.Storage) > 0 { + if volumes != nil && volumes.Storage != nil && len(volumes.Storage) > 0 { return volumes.Storage[0].Total } return 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/harbor-cli-0.0.23/pkg/views/info/list/view_test.go new/harbor-cli-0.0.24/pkg/views/info/list/view_test.go --- old/harbor-cli-0.0.23/pkg/views/info/list/view_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/harbor-cli-0.0.24/pkg/views/info/list/view_test.go 2026-07-07 15:46:05.000000000 +0200 @@ -0,0 +1,66 @@ +// 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 list + +import ( + "testing" + + "github.com/goharbor/go-client/pkg/sdk/v2.0/models" + "github.com/goharbor/harbor-cli/pkg/api" + "github.com/stretchr/testify/assert" +) + +func TestCreateSystemInfo_WithVolumes(t *testing.T) { + generalInfo := &models.GeneralInfo{} + stats := &models.Statistic{} + volumes := &models.SystemInfo{ + Storage: []*models.Storage{ + { + Free: 1000, + Total: 5000, + }, + }, + } + cliInfo := &api.CLIInfo{ + Username: "admin", + RegistryAddress: "localhost", + IsSysAdmin: true, + PreviouslyLoggedIn: []string{}, + } + + result := CreateSystemInfo(generalInfo, stats, volumes, cliInfo, "v1.0.0", "linux") + + assert.NotNil(t, result.VolumeInfo) + assert.Equal(t, uint64(1000), result.VolumeInfo.Free) + assert.Equal(t, uint64(5000), result.VolumeInfo.Total) +} + +func TestCreateSystemInfo_NilVolumes(t *testing.T) { + generalInfo := &models.GeneralInfo{} + stats := &models.Statistic{} + var volumes *models.SystemInfo // Simulate missing payload + + cliInfo := &api.CLIInfo{ + Username: "admin", + RegistryAddress: "localhost", + IsSysAdmin: true, + PreviouslyLoggedIn: []string{}, + } + + result := CreateSystemInfo(generalInfo, stats, volumes, cliInfo, "v1.0.0", "linux") + + assert.NotNil(t, result.VolumeInfo) + assert.Equal(t, uint64(0), result.VolumeInfo.Free) + assert.Equal(t, uint64(0), result.VolumeInfo.Total) +} ++++++ harbor-cli.obsinfo ++++++ --- /var/tmp/diff_new_pack.ZonKLM/_old 2026-07-08 17:48:24.554215622 +0200 +++ /var/tmp/diff_new_pack.ZonKLM/_new 2026-07-08 17:48:24.558215760 +0200 @@ -1,5 +1,5 @@ name: harbor-cli -version: 0.0.23 -mtime: 1782825991 -commit: 8555428e1e9005dc662147afc80c613e9855763a +version: 0.0.24 +mtime: 1783431965 +commit: 61dd0ce3b252ff4a69f9beee8bbf4ea3d12ea38c ++++++ vendor.tar.gz ++++++
