Skip to content

Commit 373d10d

Browse files
committed
feat: update logic
Signed-off-by: Chen Keinan <hen.keinan@gmail.com>
1 parent fae4691 commit 373d10d

2 files changed

Lines changed: 37 additions & 144 deletions

File tree

pkg/cmd/release/promote/promote.go

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ func NewCmdPromote(f factory.Factory) *cobra.Command {
9292
}
9393

9494
flags := cmd.Flags()
95-
// Reuse all flags from deploy
9695
flags.StringVarP(&promoteFlags.Project.Value, promoteFlags.Project.Name, "p", "", "Name or ID of the project to promote the release from")
9796
flags.StringArrayVarP(&promoteFlags.Environments.Value, promoteFlags.Environments.Name, "e", nil, "Promote to this environment (can be specified multiple times)")
9897
flags.StringArrayVarP(&promoteFlags.Tenants.Value, promoteFlags.Tenants.Name, "", nil, "Promote to this tenant (can be specified multiple times)")
@@ -152,24 +151,26 @@ func promoteRun(cmd *cobra.Command, f factory.Factory, flags *PromoteFlags) erro
152151
}
153152

154153
options := &executor.TaskOptionsPromoteRelease{
155-
ProjectName: flags.Project.Value,
156-
ReleaseVersion: flags.ReleaseVersion.Value,
157-
SourceEnvironment: flags.SourceEnvironment.Value,
158-
TargetEnvironments: flags.Environments.Value, // Use Environments from embedded DeployFlags
159-
Tenants: flags.Tenants.Value,
160-
TenantTags: flags.TenantTags.Value,
161-
ScheduledStartTime: flags.DeployAt.Value,
162-
ScheduledExpiryTime: flags.MaxQueueTime.Value,
163-
ExcludedSteps: flags.ExcludedSteps.Value,
164-
GuidedFailureMode: flags.GuidedFailureMode.Value,
165-
ForcePackageDownload: flags.ForcePackageDownload.Value,
166-
DeploymentTargets: flags.DeploymentTargets.Value,
167-
ExcludeTargets: flags.ExcludeTargets.Value,
168-
DeploymentFreezeNames: flags.DeploymentFreezeNames.Value,
169-
DeploymentFreezeOverrideReason: flags.DeploymentFreezeOverrideReason.Value,
170-
Variables: parsedVariables,
171-
UpdateVariables: flags.UpdateVariables.Value,
172-
LatestSuccessful: flags.LatestSuccessful.Value,
154+
TaskOptionsDeployRelease: executor.TaskOptionsDeployRelease{
155+
ProjectName: flags.Project.Value,
156+
ReleaseVersion: flags.ReleaseVersion.Value,
157+
Environments: flags.Environments.Value,
158+
Tenants: flags.Tenants.Value,
159+
TenantTags: flags.TenantTags.Value,
160+
ScheduledStartTime: flags.DeployAt.Value,
161+
ScheduledExpiryTime: flags.MaxQueueTime.Value,
162+
ExcludedSteps: flags.ExcludedSteps.Value,
163+
GuidedFailureMode: flags.GuidedFailureMode.Value,
164+
ForcePackageDownload: flags.ForcePackageDownload.Value,
165+
DeploymentTargets: flags.DeploymentTargets.Value,
166+
ExcludeTargets: flags.ExcludeTargets.Value,
167+
DeploymentFreezeNames: flags.DeploymentFreezeNames.Value,
168+
DeploymentFreezeOverrideReason: flags.DeploymentFreezeOverrideReason.Value,
169+
Variables: parsedVariables,
170+
UpdateVariables: flags.UpdateVariables.Value,
171+
},
172+
SourceEnvironment: flags.SourceEnvironment.Value,
173+
LatestSuccessful: flags.LatestSuccessful.Value,
173174
}
174175

175176
// special case for FlagForcePackageDownload bool so we can tell if it was set on the cmdline or missing
@@ -196,7 +197,7 @@ func promoteRun(cmd *cobra.Command, f factory.Factory, flags *PromoteFlags) erro
196197
resolvedFlags.Project.Value = options.ProjectName
197198
resolvedFlags.ReleaseVersion.Value = options.ReleaseVersion
198199
resolvedFlags.SourceEnvironment.Value = options.SourceEnvironment
199-
resolvedFlags.Environments.Value = options.TargetEnvironments // Map TargetEnvironments to Environments
200+
resolvedFlags.Environments.Value = options.Environments
200201
resolvedFlags.Tenants.Value = options.Tenants
201202
resolvedFlags.TenantTags.Value = options.TenantTags
202203
resolvedFlags.DeployAt.Value = options.ScheduledStartTime
@@ -431,7 +432,7 @@ func AskQuestions(octopus *octopusApiClient.Client, stdout io.Writer, asker ques
431432
}
432433
}
433434

434-
err = validateDeployment(isTenanted, options.TargetEnvironments)
435+
err = validateDeployment(isTenanted, options.Environments)
435436
if err != nil {
436437
return err
437438
}
@@ -461,14 +462,14 @@ func AskQuestions(octopus *octopusApiClient.Client, stdout io.Writer, asker ques
461462
if len(deploymentEnvironmentIDs) == 0 { // if the Q&A process earlier hasn't loaded environments already, we need to load them now
462463
switch selectedChannel.Type {
463464
case channels.ChannelTypeLifecycle:
464-
selectedEnvironments, err := executionscommon.FindEnvironments(octopus, options.TargetEnvironments)
465+
selectedEnvironments, err := executionscommon.FindEnvironments(octopus, options.Environments)
465466
if err != nil {
466467
return err
467468
}
468469

469470
deploymentEnvironmentIDs = util.SliceTransform(selectedEnvironments, func(env *environments.Environment) string { return env.ID })
470471
case channels.ChannelTypeEphemeral:
471-
deploymentEnvironmentIDs, err = findEphemeralEnvironmentIDs(octopus, space, options.TargetEnvironments)
472+
deploymentEnvironmentIDs, err = findEphemeralEnvironmentIDs(octopus, space, options.Environments)
472473

473474
if err != nil {
474475
return err
@@ -593,7 +594,7 @@ func AskQuestions(octopus *octopusApiClient.Client, stdout io.Writer, asker ques
593594

594595
if !isDeploymentTargetsSpecified {
595596
if len(deploymentEnvironmentIDs) == 0 { // if the Q&A process earlier hasn't loaded environments already, we need to load them now
596-
selectedEnvironments, err := executionscommon.FindEnvironments(octopus, options.TargetEnvironments)
597+
selectedEnvironments, err := executionscommon.FindEnvironments(octopus, options.Environments)
597598
if err != nil {
598599
return err
599600
}
@@ -645,7 +646,7 @@ func selectDeploymentEnvironmentsForEphemeralChannel(octopus *octopusApiClient.C
645646
var deploymentEnvironmentIds []string
646647
var selectedEnvironments []*ephemeralenvironments.EphemeralEnvironment
647648

648-
if len(options.TargetEnvironments) == 0 {
649+
if len(options.Environments) == 0 {
649650
allEphemeralEnvironments, err := ephemeralenvironments.GetAll(octopus, selectedRelease.SpaceID)
650651
if err != nil {
651652
return nil, err
@@ -677,10 +678,10 @@ func selectDeploymentEnvironmentsForEphemeralChannel(octopus *octopusApiClient.C
677678
return nil, err
678679
}
679680
deploymentEnvironmentIds = util.SliceTransform(selectedEnvironments, func(env *ephemeralenvironments.EphemeralEnvironment) string { return env.ID })
680-
options.TargetEnvironments = util.SliceTransform(selectedEnvironments, func(env *ephemeralenvironments.EphemeralEnvironment) string { return env.Name })
681+
options.Environments = util.SliceTransform(selectedEnvironments, func(env *ephemeralenvironments.EphemeralEnvironment) string { return env.Name })
681682
}
682683
} else {
683-
_, _ = fmt.Fprintf(stdout, "Environments %s\n", output.Cyan(strings.Join(options.TargetEnvironments, ",")))
684+
_, _ = fmt.Fprintf(stdout, "Environments %s\n", output.Cyan(strings.Join(options.Environments, ",")))
684685
}
685686

686687
return deploymentEnvironmentIds, nil
@@ -693,7 +694,7 @@ func selectDeploymentEnvironmentsForLifecycleChannel(octopus *octopusApiClient.C
693694

694695
if isTenanted {
695696
var selectedEnvironment *environments.Environment
696-
if len(options.TargetEnvironments) == 0 {
697+
if len(options.Environments) == 0 {
697698
deployableEnvironmentIDs, nextEnvironmentID, err := FindDeployableEnvironmentIDs(octopus, selectedRelease)
698699
if err != nil {
699700
return nil, err
@@ -702,9 +703,9 @@ func selectDeploymentEnvironmentsForLifecycleChannel(octopus *octopusApiClient.C
702703
if err != nil {
703704
return nil, err
704705
}
705-
options.TargetEnvironments = []string{selectedEnvironment.Name} // executions api allows env names, so let's use these instead so they look nice in generated automationcmd
706+
options.Environments = []string{selectedEnvironment.Name} // executions api allows env names, so let's use these instead so they look nice in generated automationcmd
706707
} else {
707-
selectedEnvironment, err = selectors.FindEnvironment(octopus, options.TargetEnvironments[0])
708+
selectedEnvironment, err = selectors.FindEnvironment(octopus, options.Environments[0])
708709
if err != nil {
709710
return nil, err
710711
}
@@ -731,7 +732,7 @@ func selectDeploymentEnvironmentsForLifecycleChannel(octopus *octopusApiClient.C
731732
}
732733
}
733734
} else {
734-
if len(options.TargetEnvironments) == 0 {
735+
if len(options.Environments) == 0 {
735736
deployableEnvironmentIDs, nextEnvironmentID, err := FindDeployableEnvironmentIDs(octopus, selectedRelease)
736737
if err != nil {
737738
return nil, err
@@ -741,10 +742,10 @@ func selectDeploymentEnvironmentsForLifecycleChannel(octopus *octopusApiClient.C
741742
return nil, err
742743
}
743744
deploymentEnvironmentIds = util.SliceTransform(selectedEnvironments, func(env *environments.Environment) string { return env.ID })
744-
options.TargetEnvironments = util.SliceTransform(selectedEnvironments, func(env *environments.Environment) string { return env.Name })
745+
options.Environments = util.SliceTransform(selectedEnvironments, func(env *environments.Environment) string { return env.Name })
745746
} else {
746-
if len(options.TargetEnvironments) > 0 {
747-
_, _ = fmt.Fprintf(stdout, "Environments %s\n", output.Cyan(strings.Join(options.TargetEnvironments, ",")))
747+
if len(options.Environments) > 0 {
748+
_, _ = fmt.Fprintf(stdout, "Environments %s\n", output.Cyan(strings.Join(options.Environments, ",")))
748749
}
749750
}
750751
}

pkg/executor/release.go

Lines changed: 2 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -217,38 +217,9 @@ func releaseDeploy(octopus *client.Client, space *spaces.Space, input any) error
217217
// ----- Promote Release --------------------------------------
218218

219219
type TaskOptionsPromoteRelease struct {
220-
ProjectName string // required
220+
TaskOptionsDeployRelease
221221
SourceEnvironment string // the source environment to promote from
222-
ReleaseVersion string // the release to deploy
223-
TargetEnvironments []string // multiple for untenanted deployment, only one entry for tenanted deployment
224-
Tenants []string
225-
TenantTags []string
226-
ScheduledStartTime string
227-
ScheduledExpiryTime string
228-
ExcludedSteps []string
229-
GuidedFailureMode string // ["", "true", "false", "default"]. Note default and "" are the same, the only difference is whether interactive mode prompts you
230-
ForcePackageDownload bool
231-
DeploymentTargets []string
232-
ExcludeTargets []string
233-
Variables map[string]string
234-
UpdateVariables bool
235222
LatestSuccessful bool
236-
DeploymentFreezeNames []string
237-
DeploymentFreezeOverrideReason string
238-
239-
// extra behaviour commands
240-
241-
// true if the value was specified on the command line (because ForcePackageDownload is bool, we can't distinguish 'false' from 'missing')
242-
ForcePackageDownloadWasSpecified bool
243-
244-
// so the automation command can mask sensitive variable output
245-
SensitiveVariableNames []string
246-
247-
// printing a link to the release (to check deployment status) requires the release ID, not version.
248-
// the interactive process looks this up, so we can cache it here to avoid a second lookup when generating
249-
// the link for the browser. It isn't neccessary though
250-
ReleaseID string
251-
252223
// After we send the request to the server, the response is stored here
253224
Response *deployments.CreateDeploymentResponseV1
254225
}
@@ -258,87 +229,8 @@ func releasePromote(octopus *client.Client, space *spaces.Space, input any) erro
258229
if !ok {
259230
return errors.New("invalid input type; expecting TaskOptionsPromoteRelease")
260231
}
261-
if space == nil {
262-
return errors.New("space must be specified")
263-
}
264-
265-
// we have the provided project name; go look it up
266-
if params.ProjectName == "" {
267-
return errors.New("project must be specified")
268-
}
269-
if params.ReleaseVersion == "" {
270-
return errors.New("release version must be specified")
271-
}
272-
if len(params.TargetEnvironments) == 0 {
273-
return errors.New("environment(s) must be specified")
274-
}
275232
if params.SourceEnvironment == "" {
276233
return errors.New("source environment must be specified")
277234
}
278-
279-
// common properties
280-
abstractCmd := deployments.CreateExecutionAbstractCommandV1{
281-
SpaceID: space.ID,
282-
ProjectIDOrName: params.ProjectName,
283-
ForcePackageDownload: params.ForcePackageDownload,
284-
SpecificMachineNames: params.DeploymentTargets,
285-
ExcludedMachineNames: params.ExcludeTargets,
286-
SkipStepNames: params.ExcludedSteps,
287-
RunAt: params.ScheduledStartTime,
288-
NoRunAfter: params.ScheduledExpiryTime,
289-
Variables: params.Variables,
290-
DeploymentFreezeNames: params.DeploymentFreezeNames,
291-
DeploymentFreezeOverrideReason: params.DeploymentFreezeOverrideReason,
292-
}
293-
294-
b, err := strconv.ParseBool(params.GuidedFailureMode)
295-
if err == nil {
296-
abstractCmd.UseGuidedFailure = &b
297-
} else {
298-
// else they must have specified nothing, or perhaps "default". Sanity check it's not garbage
299-
if params.GuidedFailureMode != "" && !strings.EqualFold("default", params.GuidedFailureMode) {
300-
return fmt.Errorf("'%s' is not a valid value for guided failure mode", params.GuidedFailureMode)
301-
}
302-
}
303-
// If either tenants or tenantTags are specified then it must be a tenanted deployment.
304-
// Otherwise it must be untenanted.
305-
// If the server has a tenanted deployment and both TenantNames+Tags are empty, the request fails,
306-
// which makes this a safe thing to build our logic on.
307-
isTenanted := len(params.Tenants) > 0 || len(params.TenantTags) > 0
308-
309-
if isTenanted {
310-
if len(params.TargetEnvironments) > 1 {
311-
return fmt.Errorf("tenanted deployments can only specify one environment")
312-
}
313-
tenantedCommand := deployments.NewCreateDeploymentTenantedCommandV1(space.ID, params.ProjectName)
314-
tenantedCommand.ReleaseVersion = params.ReleaseVersion
315-
tenantedCommand.EnvironmentName = params.TargetEnvironments[0]
316-
tenantedCommand.Tenants = params.Tenants
317-
tenantedCommand.TenantTags = params.TenantTags
318-
tenantedCommand.ForcePackageRedeployment = params.ForcePackageDownload
319-
tenantedCommand.UpdateVariableSnapshot = params.UpdateVariables
320-
tenantedCommand.UpdateVariableSnapshot = params.UpdateVariables
321-
tenantedCommand.CreateExecutionAbstractCommandV1 = abstractCmd
322-
323-
createDeploymentResponse, err := deployments.CreateDeploymentTenantedV1(octopus, tenantedCommand)
324-
if err != nil {
325-
return err
326-
}
327-
params.Response = createDeploymentResponse
328-
} else {
329-
untenantedCommand := deployments.NewCreateDeploymentUntenantedCommandV1(space.ID, params.ProjectName)
330-
untenantedCommand.ReleaseVersion = params.ReleaseVersion
331-
untenantedCommand.EnvironmentNames = params.TargetEnvironments
332-
untenantedCommand.ForcePackageRedeployment = params.ForcePackageDownload
333-
untenantedCommand.UpdateVariableSnapshot = params.UpdateVariables
334-
untenantedCommand.CreateExecutionAbstractCommandV1 = abstractCmd
335-
336-
createDeploymentResponse, err := deployments.CreateDeploymentUntenantedV1(octopus, untenantedCommand)
337-
if err != nil {
338-
return err
339-
}
340-
params.Response = createDeploymentResponse
341-
}
342-
343-
return nil
235+
return releaseDeploy(octopus, space, &params.TaskOptionsDeployRelease)
344236
}

0 commit comments

Comments
 (0)