Skip to content

Commit a68e6aa

Browse files
committed
Add update version cmd
1 parent d7cdd81 commit a68e6aa

File tree

8 files changed

+646
-0
lines changed

8 files changed

+646
-0
lines changed

apptrust/commands/flags.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const (
1313
VersionPromote = "version-promote"
1414
VersionDelete = "version-delete"
1515
VersionRelease = "version-release"
16+
VersionUpdate = "version-update"
1617
PackageBind = "package-bind"
1718
PackageUnbind = "package-unbind"
1819
AppCreate = "app-create"
@@ -54,6 +55,8 @@ const (
5455
ReleaseBundlesFlag = "release-bundles"
5556
SourceVersionFlag = "source-version"
5657
PackagesFlag = "packages"
58+
PropertiesFlag = "properties"
59+
DeletePropertyFlag = "delete-property"
5760
)
5861

5962
// Flag keys mapped to their corresponding components.Flag definition.
@@ -92,6 +95,8 @@ var flagsMap = map[string]components.Flag{
9295
ReleaseBundlesFlag: components.NewStringFlag(ReleaseBundlesFlag, "List of release bundles in format 'name1:version1;name2:version2'", func(f *components.StringFlag) { f.Mandatory = false }),
9396
SourceVersionFlag: components.NewStringFlag(SourceVersionFlag, "Source versions in format 'app1:version1;app2:version2'", func(f *components.StringFlag) { f.Mandatory = false }),
9497
PackagesFlag: components.NewStringFlag(PackagesFlag, "List of packages in format 'name1;name2'", func(f *components.StringFlag) { f.Mandatory = false }),
98+
PropertiesFlag: components.NewStringFlag(PropertiesFlag, "Sets or updates a custom property for the application version in format 'key=value1[,value2,...]'", func(f *components.StringFlag) { f.Mandatory = false }),
99+
DeletePropertyFlag: components.NewStringFlag(DeletePropertyFlag, "Completely removes the specified property key and all its associated values from the application version", func(f *components.StringFlag) { f.Mandatory = false }),
95100
}
96101

97102
var commandFlags = map[string][]string{
@@ -140,6 +145,15 @@ var commandFlags = map[string][]string{
140145
accessToken,
141146
serverId,
142147
},
148+
VersionUpdate: {
149+
url,
150+
user,
151+
accessToken,
152+
serverId,
153+
TagFlag,
154+
PropertiesFlag,
155+
DeletePropertyFlag,
156+
},
143157

144158
PackageBind: {
145159
url,
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package version
2+
3+
//go:generate ${PROJECT_DIR}/scripts/mockgen.sh ${GOFILE}
4+
5+
import (
6+
"strings"
7+
8+
"github.com/jfrog/jfrog-cli-application/apptrust/app"
9+
"github.com/jfrog/jfrog-cli-application/apptrust/commands"
10+
"github.com/jfrog/jfrog-cli-application/apptrust/commands/utils"
11+
"github.com/jfrog/jfrog-cli-application/apptrust/common"
12+
"github.com/jfrog/jfrog-cli-application/apptrust/model"
13+
"github.com/jfrog/jfrog-cli-application/apptrust/service"
14+
"github.com/jfrog/jfrog-cli-application/apptrust/service/versions"
15+
commonCLiCommands "github.com/jfrog/jfrog-cli-core/v2/common/commands"
16+
pluginsCommon "github.com/jfrog/jfrog-cli-core/v2/plugins/common"
17+
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
18+
coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config"
19+
"github.com/jfrog/jfrog-client-go/utils/errorutils"
20+
)
21+
22+
type updateAppVersionCommand struct {
23+
versionService versions.VersionService
24+
serverDetails *coreConfig.ServerDetails
25+
applicationKey string
26+
version string
27+
requestPayload *model.UpdateAppVersionRequest
28+
}
29+
30+
func (uv *updateAppVersionCommand) Run() error {
31+
ctx, err := service.NewContext(*uv.serverDetails)
32+
if err != nil {
33+
return err
34+
}
35+
return uv.versionService.UpdateAppVersion(ctx, uv.applicationKey, uv.version, uv.requestPayload)
36+
}
37+
38+
func (uv *updateAppVersionCommand) ServerDetails() (*coreConfig.ServerDetails, error) {
39+
return uv.serverDetails, nil
40+
}
41+
42+
func (uv *updateAppVersionCommand) CommandName() string {
43+
return commands.VersionUpdate
44+
}
45+
46+
func (uv *updateAppVersionCommand) prepareAndRunCommand(ctx *components.Context) error {
47+
if len(ctx.Arguments) != 2 {
48+
return pluginsCommon.WrongNumberOfArgumentsHandler(ctx)
49+
}
50+
51+
uv.applicationKey = ctx.Arguments[0]
52+
uv.version = ctx.Arguments[1]
53+
54+
serverDetails, err := utils.ServerDetailsByFlags(ctx)
55+
if err != nil {
56+
return err
57+
}
58+
uv.serverDetails = serverDetails
59+
60+
uv.requestPayload, err = uv.buildRequestPayload(ctx)
61+
if errorutils.CheckError(err) != nil {
62+
return err
63+
}
64+
65+
return commonCLiCommands.Exec(uv)
66+
}
67+
68+
func (uv *updateAppVersionCommand) buildRequestPayload(ctx *components.Context) (*model.UpdateAppVersionRequest, error) {
69+
request := &model.UpdateAppVersionRequest{}
70+
71+
// Handle tag - no validation, just pass through
72+
if ctx.IsFlagSet(commands.TagFlag) {
73+
request.Tag = ctx.GetStringFlagValue(commands.TagFlag)
74+
}
75+
76+
// Handle properties - support multiple values per key
77+
if ctx.IsFlagSet(commands.PropertiesFlag) {
78+
properties, err := uv.parseProperties(ctx.GetStringFlagValue(commands.PropertiesFlag))
79+
if err != nil {
80+
return nil, err
81+
}
82+
request.Properties = properties
83+
}
84+
85+
// Handle delete properties
86+
if ctx.IsFlagSet(commands.DeletePropertyFlag) {
87+
deleteProps := utils.ParseSliceFlag(ctx.GetStringFlagValue(commands.DeletePropertyFlag))
88+
request.DeleteProperties = deleteProps
89+
}
90+
91+
return request, nil
92+
}
93+
94+
func (uv *updateAppVersionCommand) parseProperties(propertiesStr string) (map[string][]string, error) {
95+
// Format: "key1=value1[,value2,...];key2=value3[,value4,...]"
96+
if propertiesStr == "" {
97+
return nil, nil
98+
}
99+
100+
result := make(map[string][]string)
101+
pairs := strings.Split(propertiesStr, ";")
102+
103+
for _, pair := range pairs {
104+
keyValue := strings.SplitN(strings.TrimSpace(pair), "=", 2)
105+
if len(keyValue) != 2 {
106+
return nil, errorutils.CheckErrorf("invalid property format: '%s' (expected key=value1[,value2,...])", pair)
107+
}
108+
109+
key := strings.TrimSpace(keyValue[0])
110+
valuesStr := strings.TrimSpace(keyValue[1])
111+
112+
if key == "" {
113+
return nil, errorutils.CheckErrorf("property key cannot be empty")
114+
}
115+
116+
var values []string
117+
if valuesStr != "" {
118+
values = strings.Split(valuesStr, ",")
119+
for i, v := range values {
120+
values[i] = strings.TrimSpace(v)
121+
}
122+
}
123+
// Always set the key, even with empty values (to clear values)
124+
125+
result[key] = values
126+
}
127+
128+
return result, nil
129+
}
130+
131+
func GetUpdateAppVersionCommand(appContext app.Context) components.Command {
132+
cmd := &updateAppVersionCommand{versionService: appContext.GetVersionService()}
133+
return components.Command{
134+
Name: commands.VersionUpdate,
135+
Description: "Updates the user-defined annotations (tag and custom key-value properties) for a specified application version.",
136+
Category: common.CategoryVersion,
137+
Aliases: []string{"vu"},
138+
Arguments: []components.Argument{
139+
{
140+
Name: "app-key",
141+
Description: "The application key of the application for which the version is being updated.",
142+
Optional: false,
143+
},
144+
{
145+
Name: "version",
146+
Description: "The version number (in SemVer format) for the application version to update.",
147+
Optional: false,
148+
},
149+
},
150+
Flags: commands.GetCommandFlags(commands.VersionUpdate),
151+
Action: cmd.prepareAndRunCommand,
152+
}
153+
}

0 commit comments

Comments
 (0)