Example #1
0
        private async Task <DeploymentResource> CreateDeploymentTask(ProjectResource project, ReleaseResource release, DeploymentPromotionTarget promotionTarget, ReferenceCollection specificMachineIds, TenantResource tenant = null)
        {
            var preview = await Repository.Releases.GetPreview(promotionTarget).ConfigureAwait(false);

            // Validate skipped steps
            var skip = new ReferenceCollection();

            foreach (var step in SkipStepNames)
            {
                var stepToExecute =
                    preview.StepsToExecute.SingleOrDefault(s => string.Equals(s.ActionName, step, StringComparison.CurrentCultureIgnoreCase));
                if (stepToExecute == null)
                {
                    Log.Warning("No step/action named '{Step:l}' could be found when deploying to environment '{Environment:l}', so the step cannot be skipped.", step, promotionTarget.Name);
                }
                else
                {
                    Log.Debug("Skipping step: {Step:l}", stepToExecute.ActionName);
                    skip.Add(stepToExecute.ActionId);
                }
            }

            // Validate form values supplied
            if (preview.Form != null && preview.Form.Elements != null && preview.Form.Values != null)
            {
                foreach (var element in preview.Form.Elements)
                {
                    var variableInput = element.Control as VariableValue;
                    if (variableInput == null)
                    {
                        continue;
                    }

                    var value = variables.Get(variableInput.Label) ?? variables.Get(variableInput.Name);

                    if (string.IsNullOrWhiteSpace(value) && element.IsValueRequired)
                    {
                        throw new ArgumentException("Please provide a variable for the prompted value " + variableInput.Label);
                    }

                    preview.Form.Values[element.Name] = value;
                }
            }

            // Log step with no machines
            foreach (var previewStep in preview.StepsToExecute)
            {
                if (previewStep.HasNoApplicableMachines)
                {
                    Log.Warning("Warning: there are no applicable machines roles used by step {Step:l}", previewStep.ActionName);
                }
            }

            var deployment = await Repository.Deployments.Create(new DeploymentResource
            {
                TenantId                 = tenant?.Id,
                EnvironmentId            = promotionTarget.Id,
                SkipActions              = skip,
                ReleaseId                = release.Id,
                ForcePackageDownload     = ForcePackageDownload,
                UseGuidedFailure         = UseGuidedFailure.GetValueOrDefault(preview.UseGuidedFailureModeByDefault),
                SpecificMachineIds       = specificMachineIds,
                ForcePackageRedeployment = ForcePackageRedeployment,
                FormValues               = (preview.Form ?? new Form()).Values,
                QueueTime                = DeployAt == null ? null : (DateTimeOffset?)DeployAt.Value
            })
                             .ConfigureAwait(false);

            Log.Information("Deploying {Project:l} {Release:} to: {PromotionTarget:l} {Tenant:l}(Guided Failure: {GuidedFailure:l})", project.Name, release.Version, promotionTarget.Name,
                            tenant == null ? string.Empty : $"for {tenant.Name} ",
                            deployment.UseGuidedFailure ? "Enabled" : "Not Enabled");

            return(deployment);
        }
        public void DeployRelease(ProjectResource project, ReleaseResource release, List <string> environments)
        {
            if (environments.Count == 0)
            {
                return;
            }

            var deployments     = new List <DeploymentResource>();
            var deploymentTasks = new List <TaskResource>();

            var releaseTemplate = Repository.Releases.GetTemplate(release);

            var promotingEnvironments =
                (from environment in environments.Distinct(StringComparer.CurrentCultureIgnoreCase)
                 let promote = releaseTemplate.PromoteTo.FirstOrDefault(p => string.Equals(p.Name, environment))
                               select new { Name = environment, Promote = promote }).ToList();

            var unknownEnvironments = promotingEnvironments.Where(p => p.Promote == null).ToList();

            if (unknownEnvironments.Count > 0)
            {
                throw new CommandException(string.Format("Release '{0}' of project '{1}' cannot be deployed to {2} not in the list of environments that this release can be deployed to. This may be because a) the environment does not exist, b) the name is misspelled, c) you don't have permission to deploy to this environment, or d) the environment is not in the list of environments defined by the project group.",
                                                         release.Version,
                                                         project.Name,
                                                         unknownEnvironments.Count == 1 ? "environment '" + unknownEnvironments[0].Name + "' because the environment is"
                    : "environments " + string.Join(", ", unknownEnvironments.Select(e => "'" + e.Name + "'")) + " because the environments are"
                                                         ));
            }

            var specificMachineIds = new ReferenceCollection();

            if (SpecificMachineNames.Any())
            {
                var machines = Repository.Machines.FindByNames(SpecificMachineNames);
                var missing  = SpecificMachineNames.Except(machines.Select(m => m.Name), StringComparer.OrdinalIgnoreCase).ToList();
                if (missing.Any())
                {
                    throw new CommandException("The following specific machines could not be found: " + missing.ReadableJoin());
                }

                specificMachineIds.AddRange(machines.Select(m => m.Id));
            }

            foreach (var environment in promotingEnvironments)
            {
                var promote = environment.Promote;
                var preview = Repository.Releases.GetPreview(promote);

                var skip = new ReferenceCollection();
                foreach (var step in SkipStepNames)
                {
                    var stepToExecute = preview.StepsToExecute.SingleOrDefault(s => string.Equals(s.ActionName, step, StringComparison.CurrentCultureIgnoreCase));
                    if (stepToExecute == null)
                    {
                        Log.WarnFormat("No step/action named '{0}' could be found when deploying to environment '{1}', so the step cannot be skipped.", step, environment);
                    }
                    else
                    {
                        Log.DebugFormat("Skipping step: {0}", stepToExecute.ActionName);
                        skip.Add(stepToExecute.ActionId);
                    }
                }

                var deployment = Repository.Deployments.Create(new DeploymentResource
                {
                    EnvironmentId            = promote.Id,
                    SkipActions              = skip,
                    ReleaseId                = release.Id,
                    ForcePackageDownload     = ForcePackageDownload,
                    UseGuidedFailure         = UseGuidedFailure.GetValueOrDefault(preview.UseGuidedFailureModeByDefault),
                    SpecificMachineIds       = specificMachineIds,
                    ForcePackageRedeployment = ForcePackageRedeployment
                });

                Log.InfoFormat("Deploying {0} {1} to: {2} (Guided Failure: {3})", project.Name, release.Version, environment.Name, deployment.UseGuidedFailure ? "Enabled" : "Not Enabled");

                foreach (var previewStep in preview.StepsToExecute)
                {
                    if (previewStep.HasNoApplicableMachines)
                    {
                        Log.Warn("Warning: there are no applicable machines roles used by step " + previewStep.ActionName + " step");
                    }
                }

                deployments.Add(deployment);
                deploymentTasks.Add(Repository.Tasks.Get(deployment.TaskId));
            }

            if (WaitForDeployment)
            {
                WaitForDeploymentToComplete(deploymentTasks, deployments, project, release);
            }
        }