| 127 | } |
| 128 | |
| 129 | func releaseDeploy(octopus *client.Client, space *spaces.Space, input any) error { |
| 130 | params, ok := input.(*TaskOptionsDeployRelease) |
| 131 | if !ok { |
| 132 | return errors.New("invalid input type; expecting TaskOptionsDeployRelease") |
| 133 | } |
| 134 | if space == nil { |
| 135 | return errors.New("space must be specified") |
| 136 | } |
| 137 | |
| 138 | // we have the provided project name; go look it up |
| 139 | if params.ProjectName == "" { |
| 140 | return errors.New("project must be specified") |
| 141 | } |
| 142 | if params.ReleaseVersion == "" { |
| 143 | return errors.New("release version must be specified") |
| 144 | } |
| 145 | if len(params.Environments) == 0 { |
| 146 | return errors.New("environment(s) must be specified") |
| 147 | } |
| 148 | |
| 149 | // common properties |
| 150 | abstractCmd := deployments.CreateExecutionAbstractCommandV1{ |
| 151 | SpaceID: space.ID, |
| 152 | ProjectIDOrName: params.ProjectName, |
| 153 | ForcePackageDownload: params.ForcePackageDownload, |
| 154 | SpecificMachineNames: params.DeploymentTargets, |
| 155 | ExcludedMachineNames: params.ExcludeTargets, |
| 156 | SkipStepNames: params.ExcludedSteps, |
| 157 | RunAt: params.ScheduledStartTime, |
| 158 | NoRunAfter: params.ScheduledExpiryTime, |
| 159 | Variables: params.Variables, |
| 160 | DeploymentFreezeNames: params.DeploymentFreezeNames, |
| 161 | DeploymentFreezeOverrideReason: params.DeploymentFreezeOverrideReason, |
| 162 | } |
| 163 | |
| 164 | b, err := strconv.ParseBool(params.GuidedFailureMode) |
| 165 | if err == nil { |
| 166 | abstractCmd.UseGuidedFailure = &b |
| 167 | } else { |
| 168 | // else they must have specified nothing, or perhaps "default". Sanity check it's not garbage |
| 169 | if params.GuidedFailureMode != "" && !strings.EqualFold("default", params.GuidedFailureMode) { |
| 170 | return fmt.Errorf("'%s' is not a valid value for guided failure mode", params.GuidedFailureMode) |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | // If either tenants or tenantTags are specified then it must be a tenanted deployment. |
| 175 | // Otherwise it must be untenanted. |
| 176 | // If the server has a tenanted deployment and both TenantNames+Tags are empty, the request fails, |
| 177 | // which makes this a safe thing to build our logic on. |
| 178 | isTenanted := len(params.Tenants) > 0 || len(params.TenantTags) > 0 |
| 179 | |
| 180 | if isTenanted { |
| 181 | if len(params.Environments) > 1 { |
| 182 | return fmt.Errorf("tenanted deployments can only specify one environment") |
| 183 | } |
| 184 | tenantedCommand := deployments.NewCreateDeploymentTenantedCommandV1(space.ID, params.ProjectName) |
| 185 | tenantedCommand.ReleaseVersion = params.ReleaseVersion |
| 186 | tenantedCommand.EnvironmentName = params.Environments[0] |