Skip to content

Commit 4379059

Browse files
committed
extract common logic
1 parent ba14f86 commit 4379059

File tree

5 files changed

+185
-76
lines changed

5 files changed

+185
-76
lines changed

apptrust/commands/version/promote_app_version_cmd.go

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
1616
coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config"
1717
"github.com/jfrog/jfrog-client-go/utils/errorutils"
18+
"github.com/jfrog/jfrog-client-go/utils/log"
1819
)
1920

2021
type promoteAppVersionCommand struct {
@@ -48,10 +49,18 @@ func (pv *promoteAppVersionCommand) prepareAndRunCommand(ctx *components.Context
4849
return pluginsCommon.WrongNumberOfArgumentsHandler(ctx)
4950
}
5051

51-
// Extract from arguments
5252
pv.applicationKey = ctx.Arguments[0]
5353
pv.version = ctx.Arguments[1]
5454

55+
if err := ValidateAppVersionParams(pv.applicationKey, pv.version); err != nil {
56+
return err
57+
}
58+
59+
log.Info("Preparing to promote application version",
60+
"applicationKey", pv.applicationKey,
61+
"version", pv.version,
62+
"targetStage", ctx.Arguments[2])
63+
5564
// Extract sync flag value
5665
pv.sync = ctx.GetBoolTFlagValue(commands.SyncFlag)
5766

@@ -64,35 +73,23 @@ func (pv *promoteAppVersionCommand) prepareAndRunCommand(ctx *components.Context
6473
if errorutils.CheckError(err) != nil {
6574
return err
6675
}
76+
77+
log.Debug("Executing promote command",
78+
"sync", pv.sync,
79+
"promotionType", pv.requestPayload.PromotionType)
80+
6781
return commonCLiCommands.Exec(pv)
6882
}
6983

7084
func (pv *promoteAppVersionCommand) buildRequestPayload(ctx *components.Context) (*model.PromoteAppVersionRequest, error) {
7185
stage := ctx.Arguments[2]
7286

73-
var includedRepos []string
74-
var excludedRepos []string
75-
76-
if includeReposStr := ctx.GetStringFlagValue(commands.IncludeReposFlag); includeReposStr != "" {
77-
includedRepos = utils.ParseSliceFlag(includeReposStr)
78-
}
79-
80-
if excludeReposStr := ctx.GetStringFlagValue(commands.ExcludeReposFlag); excludeReposStr != "" {
81-
excludedRepos = utils.ParseSliceFlag(excludeReposStr)
82-
}
83-
84-
// Validate promotion type flag
85-
promotionType := ctx.GetStringFlagValue(commands.PromotionTypeFlag)
86-
validatedPromotionType, err := utils.ValidateEnumFlag(commands.PromotionTypeFlag, promotionType, model.PromotionTypeCopy, model.PromotionTypeValues)
87+
validatedPromotionType, err := ProcessPromotionTypeFlag(ctx, model.PromotionTypeCopy)
8788
if err != nil {
8889
return nil, err
8990
}
9091

91-
// If dry-run is true, override with dry_run
92-
dryRun := ctx.GetBoolFlagValue(commands.DryRunFlag)
93-
if dryRun {
94-
validatedPromotionType = model.PromotionTypeDryRun
95-
}
92+
includedRepos, excludedRepos := ProcessRepositoryFlags(ctx)
9693

9794
return &model.PromoteAppVersionRequest{
9895
Stage: stage,

apptrust/commands/version/release_app_version_cmd.go

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
1616
coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config"
1717
"github.com/jfrog/jfrog-client-go/utils/errorutils"
18+
"github.com/jfrog/jfrog-client-go/utils/log"
1819
)
1920

2021
type releaseAppVersionCommand struct {
@@ -48,11 +49,17 @@ func (rv *releaseAppVersionCommand) prepareAndRunCommand(ctx *components.Context
4849
return pluginsCommon.WrongNumberOfArgumentsHandler(ctx)
4950
}
5051

51-
// Extract from arguments
5252
rv.applicationKey = ctx.Arguments[0]
5353
rv.version = ctx.Arguments[1]
5454

55-
// Extract sync flag value
55+
if err := ValidateAppVersionParams(rv.applicationKey, rv.version); err != nil {
56+
return err
57+
}
58+
59+
log.Info("Preparing to release application version",
60+
"applicationKey", rv.applicationKey,
61+
"version", rv.version)
62+
5663
rv.sync = ctx.GetBoolTFlagValue(commands.SyncFlag)
5764

5865
serverDetails, err := utils.ServerDetailsByFlags(ctx)
@@ -64,48 +71,27 @@ func (rv *releaseAppVersionCommand) prepareAndRunCommand(ctx *components.Context
6471
if errorutils.CheckError(err) != nil {
6572
return err
6673
}
74+
75+
log.Debug("Executing release command",
76+
"sync", rv.sync,
77+
"promotionType", rv.requestPayload.PromotionType)
78+
6779
return commonCLiCommands.Exec(rv)
6880
}
6981

7082
func (rv *releaseAppVersionCommand) buildRequestPayload(ctx *components.Context) (*model.ReleaseAppVersionRequest, error) {
71-
var includedRepos []string
72-
var excludedRepos []string
73-
var artifactProps map[string]string
74-
75-
if includeReposStr := ctx.GetStringFlagValue(commands.IncludeReposFlag); includeReposStr != "" {
76-
includedRepos = utils.ParseSliceFlag(includeReposStr)
77-
}
78-
79-
if excludeReposStr := ctx.GetStringFlagValue(commands.ExcludeReposFlag); excludeReposStr != "" {
80-
excludedRepos = utils.ParseSliceFlag(excludeReposStr)
81-
}
82-
83-
if propsStr := ctx.GetStringFlagValue(commands.PropsFlag); propsStr != "" {
84-
var err error
85-
artifactProps, err = utils.ParseMapFlag(propsStr)
86-
if err != nil {
87-
return nil, errorutils.CheckErrorf("failed to parse properties: %s", err.Error())
88-
}
83+
validatedPromotionType, err := ProcessPromotionTypeFlag(ctx, model.PromotionTypeCopy)
84+
if err != nil {
85+
return nil, err
8986
}
9087

91-
// Validate promotion type flag
92-
promotionType := ctx.GetStringFlagValue(commands.PromotionTypeFlag)
93-
94-
// For validation, we need to add the dry_run option
95-
allowedValues := append([]string{}, model.PromotionTypeValues...)
96-
allowedValues = append(allowedValues, model.PromotionTypeDryRun)
88+
includedRepos, excludedRepos := ProcessRepositoryFlags(ctx)
9789

98-
validatedPromotionType, err := utils.ValidateEnumFlag(commands.PromotionTypeFlag, promotionType, model.PromotionTypeCopy, allowedValues)
90+
artifactProps, err := ProcessPropertiesFlag(ctx)
9991
if err != nil {
10092
return nil, err
10193
}
10294

103-
// If dry-run is true, override with dry_run
104-
dryRun := ctx.GetBoolFlagValue(commands.DryRunFlag)
105-
if dryRun {
106-
validatedPromotionType = model.PromotionTypeDryRun
107-
}
108-
10995
return &model.ReleaseAppVersionRequest{
11096
PromotionType: validatedPromotionType,
11197
IncludedRepositoryKeys: includedRepos,
@@ -118,7 +104,7 @@ func GetReleaseAppVersionCommand(appContext app.Context) components.Command {
118104
cmd := &releaseAppVersionCommand{versionService: appContext.GetVersionService()}
119105
return components.Command{
120106
Name: commands.VersionRelease,
121-
Description: "Release application version.",
107+
Description: "Release application version. Initiates the release process for an application version, moving it to the release stage.",
122108
Category: common.CategoryVersion,
123109
Aliases: []string{"vr"},
124110
Arguments: []components.Argument{
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package version
2+
3+
import (
4+
"github.com/jfrog/jfrog-cli-application/apptrust/commands"
5+
"github.com/jfrog/jfrog-cli-application/apptrust/commands/utils"
6+
"github.com/jfrog/jfrog-cli-application/apptrust/model"
7+
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
8+
"github.com/jfrog/jfrog-client-go/utils/errorutils"
9+
"github.com/jfrog/jfrog-client-go/utils/log"
10+
)
11+
12+
// Common functions used by multiple version-related commands
13+
14+
// ValidateAppVersionParams validates the application key and version parameters
15+
func ValidateAppVersionParams(applicationKey, version string) error {
16+
if applicationKey == "" {
17+
return errorutils.CheckErrorf("application key cannot be empty")
18+
}
19+
20+
if version == "" {
21+
return errorutils.CheckErrorf("version cannot be empty")
22+
}
23+
24+
return nil
25+
}
26+
27+
// ProcessPromotionTypeFlag processes and validates the promotion type flag and dry-run flag
28+
// Returns the validated promotion type value
29+
func ProcessPromotionTypeFlag(ctx *components.Context, defaultType string) (string, error) {
30+
// Validate promotion type flag
31+
promotionType := ctx.GetStringFlagValue(commands.PromotionTypeFlag)
32+
33+
// For validation, we need to add the dry_run option to the allowed values
34+
allowedValues := append([]string{}, model.PromotionTypeValues...)
35+
allowedValues = append(allowedValues, model.PromotionTypeDryRun)
36+
37+
validatedPromotionType, err := utils.ValidateEnumFlag(commands.PromotionTypeFlag, promotionType, defaultType, allowedValues)
38+
if err != nil {
39+
return "", err
40+
}
41+
42+
// If dry-run is true, override with dry_run
43+
dryRun := ctx.GetBoolFlagValue(commands.DryRunFlag)
44+
if dryRun {
45+
log.Debug("Dry run requested, setting promotion type to dry_run")
46+
validatedPromotionType = model.PromotionTypeDryRun
47+
}
48+
49+
return validatedPromotionType, nil
50+
}
51+
52+
// ProcessRepositoryFlags processes the include/exclude repos flags
53+
// Returns the included and excluded repository keys
54+
func ProcessRepositoryFlags(ctx *components.Context) ([]string, []string) {
55+
var includedRepos []string
56+
var excludedRepos []string
57+
58+
if includeReposStr := ctx.GetStringFlagValue(commands.IncludeReposFlag); includeReposStr != "" {
59+
includedRepos = utils.ParseSliceFlag(includeReposStr)
60+
log.Debug("Included repositories:", includedRepos)
61+
}
62+
63+
if excludeReposStr := ctx.GetStringFlagValue(commands.ExcludeReposFlag); excludeReposStr != "" {
64+
excludedRepos = utils.ParseSliceFlag(excludeReposStr)
65+
log.Debug("Excluded repositories:", excludedRepos)
66+
}
67+
68+
return includedRepos, excludedRepos
69+
}
70+
71+
// ProcessPropertiesFlag processes the properties flag and returns a map of property key-values
72+
func ProcessPropertiesFlag(ctx *components.Context) (map[string]string, error) {
73+
if propsStr := ctx.GetStringFlagValue(commands.PropsFlag); propsStr != "" {
74+
artifactProps, err := utils.ParseMapFlag(propsStr)
75+
if err != nil {
76+
return nil, errorutils.CheckErrorf("failed to parse properties: %s", err.Error())
77+
}
78+
log.Debug("Artifact properties:", artifactProps)
79+
return artifactProps, nil
80+
}
81+
return nil, nil
82+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package versions
2+
3+
// Constants for API endpoints
4+
const (
5+
// VersionEndpointPattern is the base endpoint pattern for version operations
6+
VersionEndpointPattern = "/v1/applications/%s/versions/%s/%s"
7+
)
8+
9+
// Error message constants
10+
const (
11+
// ErrorPromoteAppVersion is the error message for promote failures
12+
ErrorPromoteAppVersion = "failed to promote app version"
13+
14+
// ErrorReleaseAppVersion is the error message for release failures
15+
ErrorReleaseAppVersion = "failed to release app version"
16+
17+
// ErrorDeleteAppVersion is the error message for delete failures
18+
ErrorDeleteAppVersion = "failed to delete app version"
19+
20+
// ErrorCreateAppVersion is the error message for create failures
21+
ErrorCreateAppVersion = "failed to create app version"
22+
)

apptrust/service/versions/version_service.go

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/jfrog/jfrog-cli-application/apptrust/service"
1010

1111
"github.com/jfrog/jfrog-cli-application/apptrust/model"
12+
"github.com/jfrog/jfrog-client-go/utils/log"
1213
)
1314

1415
type VersionService interface {
@@ -39,46 +40,67 @@ func (vs *versionService) CreateAppVersion(ctx service.Context, request *model.C
3940
}
4041

4142
func (vs *versionService) PromoteAppVersion(ctx service.Context, applicationKey, version string, request *model.PromoteAppVersionRequest, sync bool) error {
42-
endpoint := fmt.Sprintf("/v1/applications/%s/versions/%s/promote", applicationKey, version)
43-
response, responseBody, err := ctx.GetHttpClient().Post(endpoint, request, map[string]string{"async": strconv.FormatBool(!sync)})
44-
if err != nil {
45-
return err
46-
}
47-
48-
if response.StatusCode >= 400 {
49-
return fmt.Errorf("failed to promote app version. Status code: %d. \n%s",
50-
response.StatusCode, responseBody)
51-
}
52-
53-
return nil
43+
return vs.requestOperation(ctx, applicationKey, version, "promote", request, sync)
5444
}
5545

5646
func (vs *versionService) ReleaseAppVersion(ctx service.Context, applicationKey, version string, request *model.ReleaseAppVersionRequest, sync bool) error {
57-
endpoint := fmt.Sprintf("/v1/applications/%s/versions/%s/release", applicationKey, version)
58-
response, responseBody, err := ctx.GetHttpClient().Post(endpoint, request, map[string]string{"async": strconv.FormatBool(!sync)})
47+
return vs.requestOperation(ctx, applicationKey, version, "release", request, sync)
48+
}
49+
50+
func (vs *versionService) DeleteAppVersion(ctx service.Context, applicationKey, version string) error {
51+
url := fmt.Sprintf("/v1/applications/%s/versions/%s", applicationKey, version)
52+
response, responseBody, err := ctx.GetHttpClient().Delete(url, nil)
5953
if err != nil {
6054
return err
6155
}
6256

63-
if response.StatusCode >= 400 {
64-
return fmt.Errorf("failed to release app version. Status code: %d. \n%s",
57+
if response.StatusCode != 204 {
58+
return fmt.Errorf("failed to delete app version. Status code: %d.\n%s",
6559
response.StatusCode, responseBody)
6660
}
6761

6862
return nil
6963
}
7064

71-
func (vs *versionService) DeleteAppVersion(ctx service.Context, applicationKey, version string) error {
72-
url := fmt.Sprintf("/v1/applications/%s/versions/%s", applicationKey, version)
73-
response, responseBody, err := ctx.GetHttpClient().Delete(url, nil)
65+
// Common methods
66+
67+
// requestOperation is a generic method for performing version operations via POST requests
68+
// It handles both promote and release operations
69+
func (vs *versionService) requestOperation(ctx service.Context, applicationKey, version, operation string, payload interface{}, sync bool) error {
70+
endpoint := fmt.Sprintf(VersionEndpointPattern, applicationKey, version, operation)
71+
72+
// Log operation details
73+
log.Debug(fmt.Sprintf("Performing %s operation", operation),
74+
"applicationKey", applicationKey,
75+
"version", version,
76+
"sync", sync,
77+
"endpoint", endpoint)
78+
79+
response, responseBody, err := ctx.GetHttpClient().Post(endpoint, payload, map[string]string{"async": strconv.FormatBool(!sync)})
7480
if err != nil {
7581
return err
7682
}
7783

78-
if response.StatusCode != 204 {
79-
return fmt.Errorf("failed to delete app version. Status code: %d.\n%s",
80-
response.StatusCode, responseBody)
84+
if response.StatusCode >= 400 {
85+
// Get appropriate error message based on operation
86+
var errorMessage string
87+
switch operation {
88+
case "promote":
89+
errorMessage = ErrorPromoteAppVersion
90+
case "release":
91+
errorMessage = ErrorReleaseAppVersion
92+
default:
93+
errorMessage = fmt.Sprintf("failed to %s app version", operation)
94+
}
95+
96+
return fmt.Errorf("%s. Status code: %d. \n%s",
97+
errorMessage, response.StatusCode, responseBody)
8198
}
8299

100+
log.Debug(fmt.Sprintf("%s operation successful", operation),
101+
"applicationKey", applicationKey,
102+
"version", version,
103+
"statusCode", response.StatusCode)
104+
83105
return nil
84106
}

0 commit comments

Comments
 (0)