Inheritance: ReleaseSummaryResource
Ejemplo n.º 1
0
        public void Init()
        {
            _ps = Utilities.CreatePowerShell(CmdletName, typeof(GetDeployment));

            var octoRepo = Utilities.AddOctopusRepo(_ps.Runspace.SessionStateProxy.PSVariable);

            // Create a project
            var projectResource = new ProjectResource {Name = "Octopus"};
            octoRepo.Setup(o => o.Projects.FindByName("Octopus")).Returns(projectResource);
            octoRepo.Setup(o => o.Projects.FindByName("Gibberish")).Returns((ProjectResource) null);

            // Create a Release
            var release = new ReleaseResource { Id = "Releases-1", Links = new LinkCollection()};

            release.Links.Add("Deployments", "/api/releases/releases-1/deployments");
            octoRepo.Setup(o => o.Projects.GetReleaseByVersion(projectResource, "1.0.0")).Returns(release);
            octoRepo.Setup(o => o.Projects.GetReleaseByVersion(projectResource, "Gibberish")).Returns((ReleaseResource) null);

            // Create Deployments
            var deployments = new ResourceCollection<DeploymentResource>(new List<DeploymentResource>
            {
                new DeploymentResource {Id = "deployments-1"}
            }, new LinkCollection());
            octoRepo.Setup(o => o.Releases.GetDeployments(release, 0)).Returns(deployments);
            octoRepo.Setup(o => o.Releases.Get("Releases-1")).Returns(release);
        }
        public void SetUp()
        {
            createAutoDeployOverrideCommand = new CreateAutoDeployOverrideCommand(RepositoryFactory, Log, FileSystem, ClientFactory);

            environment = new EnvironmentResource { Name = "Production", Id = "Environments-001" };
            project = new ProjectResource("Projects-1", "OctoFx", "OctoFx");
            release = new ReleaseResource("1.2.0", "Projects-1", "Channels-1");
            octopusTenant = new TenantResource
            {
                Id = "Tenants-1",
                Name = "Octopus",
                ProjectEnvironments = { ["Projects-1"] = new ReferenceCollection("Environments-001") }
            };

            Repository.Environments.FindByName("Production").Returns(
                environment
            );

            Repository.Projects.FindByName("OctoFx").Returns(
                project
            );

            Repository.Projects.GetReleaseByVersion(Arg.Any<ProjectResource>(), "1.2.0").Returns(
                release
            );

            Repository.Tenants.FindByNames(Arg.Any<IEnumerable<string>>()).Returns(
                new List<TenantResource>
                {
                    octopusTenant
                }
            );
            Repository.Tenants.FindAll(null, Arg.Any<string[]>()).Returns(
                new List<TenantResource>
                {
                    octopusTenant
                }
            );

            Repository.Projects.When(x => x.Modify(Arg.Any<ProjectResource>()))
                .Do(x => savedProject = x.Args()[0] as ProjectResource);
        }
        public void SetUp()
        {
            deployReleaseCommand = new DeployReleaseCommand(RepositoryFactory, Log, FileSystem);

            var project = new ProjectResource();
            var release = new ReleaseResource { Version = "1.0.0" };
            var releases = new ResourceCollection<ReleaseResource>(new[] { release }, new LinkCollection());
            var deploymentPromotionTarget = new DeploymentPromotionTarget { Name = "TestEnvironment" };
            var promotionTargets = new List<DeploymentPromotionTarget> { deploymentPromotionTarget };
            var deploymentTemplate = new DeploymentTemplateResource { PromoteTo = promotionTargets };
            var deploymentPreviewResource = new DeploymentPreviewResource { StepsToExecute = new List<DeploymentTemplateStep>() };
            var deployment = new DeploymentResource { TaskId = "1" };
            taskResource = new TaskResource();

            Repository.Projects.FindByName(ProjectName).Returns(project);
            Repository.Projects.GetReleases(project).Returns(releases);
            Repository.Releases.GetPreview(deploymentPromotionTarget).Returns(deploymentPreviewResource);
            Repository.Releases.GetTemplate(release).Returns(deploymentTemplate);
            Repository.Deployments.Create(Arg.Any<DeploymentResource>()).Returns(deployment);
            Repository.Tasks.Get(deployment.TaskId).Returns(taskResource);
        }
        public void Run()
        {
            try
            {
                var project = client.repository.Projects.FindByName(instance.Branch);

                var releases = client.repository.Releases.FindMany(r => r.ProjectId == ConfigurationManager.AppSettings["octopus-base-release-projectId"]);

                var releaseBase = releases.FirstOrDefault();

                var release = client.repository.Releases.FindOne(r => r.Version == instance.Release && r.ProjectId == project.Id);

                if (release == null)
                {
                    var releaseResource = new ReleaseResource(instance.Release, project.Id);

                    releaseResource.SelectedPackages = releaseBase.SelectedPackages;

                    foreach (var package in releaseResource.SelectedPackages)
                    {
                        package.Version = nugetClient.GetLastVersion(package.StepName, instance.Branch);
                    }

                    var newRelease = client.repository.Releases.Create(releaseResource);

                    instance.ReleaseId = newRelease.Id;
                }
                else
                    instance.ReleaseId = release.Id;

                FinishedSuccessfully = true;
            }
            catch (Exception ex)
            {
                FinishedSuccessfully = false;

                Error = ex.Message;
            }
        }
        public void WaitForDeploymentToComplete(List<TaskResource> deploymentTasks, List<DeploymentResource> deployments, ProjectResource project, ReleaseResource release)
        {
            try
            {
                Log.InfoFormat("Waiting for {0} deployment(s) to complete....", deploymentTasks.Count);
                Repository.Tasks.WaitForCompletion(deploymentTasks.ToArray(), DeploymentStatusCheckSleepCycle.Seconds, DeploymentTimeout.Minutes);
                var failed = false;
                foreach (var deploymentTask in deploymentTasks)
                {
                    var updated = Repository.Tasks.Get(deploymentTask.Id);
                    if (updated.FinishedSuccessfully)
                    {
                        Log.InfoFormat("{0}: {1}", updated.Description, updated.State);
                    }
                    else
                    {
                        Log.ErrorFormat("{0}: {1}, {2}", updated.Description, updated.State, updated.ErrorMessage);
                        failed = true;
                    }
                }
                if (failed)
                {
                    throw new CommandException("One or more deployment tasks failed.");
                }

                Log.Info("Done!");
            }
            catch (TimeoutException e)
            {
                Log.Error(e.Message);
                var guidedFailureDeployments =
                    from d in deployments
                    where d.UseGuidedFailure
                    select d;
                if (guidedFailureDeployments.Any())
                {
                    Log.Warn("One or more deployments are using Guided Failure. Use the links below to check if intervention is required:");
                    foreach (var guidedFailureDeployment in guidedFailureDeployments)
                    {
                        var environment = Repository.Environments.Get(guidedFailureDeployment.Link("Environment"));
                        Log.WarnFormat("  - {0}: {1}", environment.Name, GetPortalUrl(string.Format("/app#/projects/{0}/releases/{1}/deployments/{2}", project.Slug, release.Version, guidedFailureDeployment.Id)));
                    }
                }
                throw new CommandException(e.Message);
            }
        }
        public async Task WaitForDeploymentToComplete(IReadOnlyList<DeploymentResource> deployments, ProjectResource project, ReleaseResource release)
        {
            var getTasks = deployments.Select(dep => Repository.Tasks.Get(dep.TaskId));
            var deploymentTasks = await Task.WhenAll(getTasks).ConfigureAwait(false);
            if (showProgress && deployments.Count > 1)
            {
                Log.Information("Only progress of the first task ({Task:l}) will be shown", deploymentTasks.First().Name);
            }

            try
            {
                Log.Information("Waiting for {NumberOfTasks} deployment(s) to complete....", deploymentTasks.Length);
                await Repository.Tasks.WaitForCompletion(deploymentTasks.ToArray(), DeploymentStatusCheckSleepCycle.Seconds, (int)DeploymentTimeout.TotalMinutes, PrintTaskOutput).ConfigureAwait(false);
                var failed = false;
                foreach (var deploymentTask in deploymentTasks)
                {
                    var updated = await Repository.Tasks.Get(deploymentTask.Id).ConfigureAwait(false);
                    if (updated.FinishedSuccessfully)
                    {
                        Log.Information("{Task:l}: {State}", updated.Description, updated.State);
                    }
                    else
                    {
                        Log.Error("{Task:l}: {State}, {Error:l}", updated.Description, updated.State, updated.ErrorMessage);
                        failed = true;

                        if (noRawLog)
                        {
                            continue;
                        }

                        try
                        {
                            var raw = await Repository.Tasks.GetRawOutputLog(updated).ConfigureAwait(false);
                            if (!string.IsNullOrEmpty(rawLogFile))
                            {
                                File.WriteAllText(rawLogFile, raw);
                            }
                            else
                            {
                                Log.Error(raw);
                            }
                        }
                        catch (Exception ex)
                        {
                            Log.Error(ex, "Could not retrieve the raw task log for the failed task.");
                        }
                    }
                }
                if (failed)
                {
                    throw new CommandException("One or more deployment tasks failed.");
                }

                Log.Information("Done!");
            }
            catch (TimeoutException e)
            {
                Log.Error(e.Message);

                await CancelDeploymentOnTimeoutIfRequested(deploymentTasks).ConfigureAwait(false);

                var guidedFailureDeployments =
                    from d in deployments
                    where d.UseGuidedFailure
                    select d;
                if (guidedFailureDeployments.Any())
                {
                    Log.Warning("One or more deployments are using Guided Failure. Use the links below to check if intervention is required:");
                    foreach (var guidedFailureDeployment in guidedFailureDeployments)
                    {
                        var environment = await Repository.Environments.Get(guidedFailureDeployment.Link("Environment")).ConfigureAwait(false);
                        Log.Warning("  - {Environment:l}: {Url:l}", environment.Name, GetPortalUrl(string.Format("/app#/projects/{0}/releases/{1}/deployments/{2}", project.Slug, release.Version, guidedFailureDeployment.Id)));
                    }
                }
                throw new CommandException(e.Message);
            }
        }
        private async Task<IReadOnlyList<DeploymentResource>> DeployTenantedRelease(ProjectResource project, ReleaseResource release)
        {
            if (DeployToEnvironmentNames.Count != 1)
                return new List<DeploymentResource>();

            var environment = DeployToEnvironmentNames[0];
            var specificMachineIdsTask = GetSpecificMachines();
            var releaseTemplate = await Repository.Releases.GetTemplate(release).ConfigureAwait(false);
            var deploymentTenants = await GetTenants(project, environment, release, releaseTemplate).ConfigureAwait(false);
            var specificMachineIds = await specificMachineIdsTask.ConfigureAwait(false);

            LogScheduledDeployment();

            var createTasks = deploymentTenants.Select(tenant =>
            {
                var promotion =
                    releaseTemplate.TenantPromotions
                        .First(t => t.Id == tenant.Id).PromoteTo
                        .First(tt => tt.Name.Equals(environment, StringComparison.CurrentCultureIgnoreCase));
                return CreateDeploymentTask(project, release, promotion, specificMachineIds, tenant);
            });

            return await Task.WhenAll(createTasks).ConfigureAwait(false);
        }
        private async Task<List<TenantResource>> GetTenants(ProjectResource project, string environmentName, ReleaseResource release,
            DeploymentTemplateResource releaseTemplate)
        {
            if (!Tenants.Any() && !TenantTags.Any())
            {
                return new List<TenantResource>();
            }

            var deployableTenants = new List<TenantResource>();

            if (Tenants.Contains("*"))
            {
                var tenantPromotions = releaseTemplate.TenantPromotions.Where(
                    tp => tp.PromoteTo.Any(
                        promo => promo.Name.Equals(environmentName, StringComparison.CurrentCultureIgnoreCase))).Select(tp => tp.Id).ToArray();

                var tentats = await Repository.Tenants.Get(tenantPromotions).ConfigureAwait(false);
                deployableTenants.AddRange(tentats);

                Log.Information("Found {NumberOfTenants} Tenants who can deploy {Project:l} {Version:l} to {Environment:l}", deployableTenants.Count, project.Name,release.Version, environmentName);
            }
            else
            {
                if (Tenants.Any())
                {
                    var tenantsByName = await Repository.Tenants.FindByNames(Tenants).ConfigureAwait(false);
                    var missing = tenantsByName == null || !tenantsByName.Any()
                        ? Tenants.ToArray()
                        : Tenants.Except(tenantsByName.Select(e => e.Name), StringComparer.OrdinalIgnoreCase).ToArray();

                    var tenantsById = await Repository.Tenants.Get(missing).ConfigureAwait(false);

                    missing = tenantsById == null || !tenantsById.Any()
                        ? missing
                        : missing.Except(tenantsById.Select(e => e.Id), StringComparer.OrdinalIgnoreCase).ToArray();

                    if (missing.Any())
                        throw new ArgumentException(
                            $"Could not find the {"tenant" + (missing.Length == 1 ? "" : "s")} {string.Join(", ", missing)} on the Octopus server.");

                    deployableTenants.AddRange(tenantsByName);
                    deployableTenants.AddRange(tenantsById);

                    var unDeployableTenants =
                        deployableTenants.Where(dt => !dt.ProjectEnvironments.ContainsKey(project.Id))
                            .Select(dt => $"'{dt.Name}'")
                            .ToList();
                    if (unDeployableTenants.Any())
                        throw new CommandException(
                            string.Format(
                                "Release '{0}' of project '{1}' cannot be deployed for tenant{2} {3}. This may be because either a) {4} not connected to this project, or b) you do not have permission to deploy {5} to this project.",
                                release.Version,
                                project.Name,
                                unDeployableTenants.Count == 1 ? "" : "s",
                                string.Join(" or ", unDeployableTenants),
                                unDeployableTenants.Count == 1 ? "it is" : "they are",
                                unDeployableTenants.Count == 1 ? "it" : "them"));

                    unDeployableTenants = deployableTenants.Where(dt =>
                    {
                        var tenantPromo = releaseTemplate.TenantPromotions.FirstOrDefault(tp => tp.Id == dt.Id);
                        return tenantPromo == null ||
                               !tenantPromo.PromoteTo.Any(
                                   tdt => tdt.Name.Equals(environmentName, StringComparison.CurrentCultureIgnoreCase));
                    }).Select(dt => $"'{dt.Name}'").ToList();
                    if (unDeployableTenants.Any())
                    {
                        throw new CommandException(
                            string.Format(
                                "Release '{0}' of project '{1}' cannot be deployed for tenant{2} {3} to environment '{4}'. This may be because a) the tenant{2} {5} not connected to this environment, a) The lifecycle has not reached this phase, b) the environment does not exist, b) the environment name is misspelled, c) you don't have permission to deploy to this environment, d) the environment is not in the list of environments defined by the lifecycle, or e) {6} unable to deploy to this channel.",
                                release.Version,
                                project.Name,
                                unDeployableTenants.Count == 1 ? "" : "s",
                                string.Join(" or ", unDeployableTenants),
                                environmentName,
                                unDeployableTenants.Count == 1 ? "is" : "are",
                                unDeployableTenants.Count == 1 ? "it is" : "they are"));
                    }
                }

                if (TenantTags.Any())
                {

                    var tenantsByTag = await Repository.Tenants.FindAll(null, TenantTags.ToArray()).ConfigureAwait(false);
                    var deployableByTag = tenantsByTag.Where(dt =>
                    {
                        var tenantPromo = releaseTemplate.TenantPromotions.FirstOrDefault(tp => tp.Id == dt.Id);
                        return tenantPromo != null && tenantPromo.PromoteTo.Any(tdt => tdt.Name.Equals(environmentName, StringComparison.CurrentCultureIgnoreCase));
                    }).Where(tenant => !deployableTenants.Any(deployable => deployable.Id == tenant.Id));
                    deployableTenants.AddRange(deployableByTag);
                }
            }

            if (!deployableTenants.Any())
                throw new CommandException(
                    string.Format(
                        "No tenants are available to be deployed for release '{0}' of project '{1}' to environment '{2}'.  This may be because a) No tenants matched the tags provided b) The tenants that do match are not connected to this project or environment, c) The tenants that do match are not yet able to release to this lifecycle phase, or d) you do not have the appropriate deployment permissions.",
                        release.Version, project.Name, environmentName));


            return deployableTenants;
        }
        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;
        }
Ejemplo n.º 10
0
 protected async Task DeployRelease(ProjectResource project, ReleaseResource release)
 {
     var deploymentsTask = IsTenantedDeployment ?
         DeployTenantedRelease(project, release) : 
         DeployToEnvironments(project, release);
     var deployments = await deploymentsTask.ConfigureAwait(false);
     if (deployments.Any() && WaitForDeployment)
     {
         await WaitForDeploymentToComplete(deployments, project, release).ConfigureAwait(false);
     }
 }
Ejemplo n.º 11
0
        private async Task<IReadOnlyList<DeploymentResource>> DeployToEnvironments(ProjectResource project, ReleaseResource release)
        {
            if (DeployToEnvironmentNames.Count == 0)
                return new List<DeploymentResource>();

            var releaseTemplate = await Repository.Releases.GetTemplate(release).ConfigureAwait(false);

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

            var unknownEnvironments = promotingEnvironments.Where(p => p.Promotion == 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 lifecycle.",
                        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"
                        ));
            }

            LogScheduledDeployment();
            var specificMachineIds = await GetSpecificMachines().ConfigureAwait(false);

            var createTasks = promotingEnvironments.Select(promotion => CreateDeploymentTask(project, release, promotion.Promotion, specificMachineIds));
            return await Task.WhenAll(createTasks).ConfigureAwait(false);
        }
Ejemplo n.º 12
0
 public static void TfsServiceMessage(this ILog log, string serverBaseUrl, ProjectResource project, ReleaseResource release)
 {
     if (!serviceMessagesEnabled)
         return;
     if (buildEnvironment == BuildEnvironment.TeamFoundationBuild || buildEnvironment == BuildEnvironment.NoneOrUnknown)
     {
         var workingDirectory = Environment.GetEnvironmentVariable("SYSTEM_DEFAULTWORKINGDIRECTORY") ?? new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName;
         var selflink = new Uri(new Uri(serverBaseUrl), release.Links["Web"].AsString());
         var markdown = string.Format("[Release {0} created for '{1}']({2})", release.Version, project.Name, selflink);
         var markdownFile = System.IO.Path.Combine(workingDirectory, Guid.NewGuid() + ".md");
         System.IO.File.WriteAllText(markdownFile, markdown);
         log.InfoFormat("##vso[task.addattachment type=Distributedtask.Core.Summary;name=Octopus Deploy;]{0}", markdownFile);
     }
 }
 private static IEnumerable<string> FormatReleasePropertiesAsStrings(ReleaseResource release)
 {
     return new List<string>{
             "Version: " + release.Version,
             "Assembled: "+release.Assembled,
             "Package Versions: " + GetPackageVersionsAsString(release.SelectedPackages),
             "Release Notes: " + ((release.ReleaseNotes != null) ? release.ReleaseNotes.Replace(System.Environment.NewLine,@"\n"): "")
         };
 }
Ejemplo n.º 14
0
        public ReleaseResource CreateRelease(string projectId, string version, IEnumerable<SelectedPackage> selectedPackages)
        {
            var release = new ReleaseResource
            {
                Version = version,
                ProjectId = projectId,
                SelectedPackages = selectedPackages.ToList()
            };

            return CreateRelease(release);
        }
        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 lifecycle.",
                        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));
            }

            if (DeployAt != null)
            {
                var now = DateTimeOffset.UtcNow;
                Log.InfoFormat("Deployment will be scheduled to start in: {0}", (DeployAt.Value - now).FriendlyDuration());
            }

            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);
                    }
                }

                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;
                    }
                }

                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,
                    FormValues = (preview.Form ?? new Form()).Values,
                    QueueTime = DeployAt == null ? null : (DateTimeOffset?)DeployAt.Value
                });

                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);
            }
        }
Ejemplo n.º 16
0
        public void AddAutoDeployReleaseOverride(EnvironmentResource environment, TenantResource tenant, ReleaseResource release)
        {
            var autoDeployReleaseOverrideResource = new AutoDeployReleaseOverrideResource(environment.Id, tenant?.Id, release.Id);

            var existingAutoDeployReleaseOverride = AutoDeployReleaseOverrides.SingleOrDefault(x => x.EnvironmentId == environment.Id && x.TenantId == tenant?.Id);

            if (existingAutoDeployReleaseOverride != null)
            {
                AutoDeployReleaseOverrides.Remove(existingAutoDeployReleaseOverride);
            }

            AutoDeployReleaseOverrides.Add(autoDeployReleaseOverrideResource);
        }
Ejemplo n.º 17
0
 public void AddAutoDeployReleaseOverride(EnvironmentResource environment, ReleaseResource release)
 {
     AddAutoDeployReleaseOverride(environment, null, release);
 }
        void AddOverrideForTenant(ProjectResource project, EnvironmentResource environment, TenantResource tenant, ReleaseResource release)
        {
            if (!tenant.ProjectEnvironments.ContainsKey(project.Id))
            {
                Log.Warning("The tenant {Tenant:l} was skipped because it has not been connected to the project {Project:l}", tenant.Name, project.Name);
                return;
            }
            if (!tenant.ProjectEnvironments[project.Id].Contains(environment.Id))
            {
                Log.Warning("The tenant {Tenant:l} was skipped because it has not been connected to the environment {Environment:l}", tenant.Name, environment.Name);
                return;
            }

            project.AddAutoDeployReleaseOverride(environment, tenant, release);
            Log.Information("Auto deploy will deploy version {Version:l} of the project {Project:l} to the environment {Environment:l} for the tenant {Tenant:l}", release.Version, project.Name, environment.Name, tenant.Name);
        }
 void AddOverrideForEnvironment(ProjectResource project, EnvironmentResource environment, ReleaseResource release)
 {
     project.AddAutoDeployReleaseOverride(environment, release);
     Log.Information("Auto deploy will deploy version {Version:l} of the project {Project:l} to the environment {Environment:l}", release.Version, project.Name, environment.Name);
 }
Ejemplo n.º 20
0
 public ReleaseResource CreateRelease(ReleaseResource release)
 {
     var project = _octopusRepository.Projects.Get(release.ProjectId);
     try
     {
         return _octopusRepository.Projects.GetReleaseByVersion(project, release.Version);
     }
     catch (OctopusResourceNotFoundException)
     {
         return _octopusRepository.Releases.Create(release);
     }
 }
        public void WaitForDeploymentToComplete(List<TaskResource> deploymentTasks, List<DeploymentResource> deployments, ProjectResource project, ReleaseResource release)
        {
            if (showProgress && deploymentTasks.Count > 1)
            {
                Log.InfoFormat("Only progress of the first task ({0}) will be shown", deploymentTasks.First().Description);
            }

            try
            {
                Log.InfoFormat("Waiting for {0} deployment(s) to complete....", deploymentTasks.Count);
                Repository.Tasks.WaitForCompletion(deploymentTasks.ToArray(), DeploymentStatusCheckSleepCycle.Seconds, (int)DeploymentTimeout.TotalMinutes, PrintTaskOutput);
                var failed = false;
                foreach (var deploymentTask in deploymentTasks)
                {
                    var updated = Repository.Tasks.Get(deploymentTask.Id);
                    if (updated.FinishedSuccessfully)
                    {
                        Log.InfoFormat("{0}: {1}", updated.Description, updated.State);
                    }
                    else
                    {
                        Log.ErrorFormat("{0}: {1}, {2}", updated.Description, updated.State, updated.ErrorMessage);
                        failed = true;

                        if (!noRawLog)
                        {
                            try
                            {
                                var raw = Repository.Tasks.GetRawOutputLog(updated);
                                if (!string.IsNullOrEmpty(rawLogFile))
                                {
                                    File.WriteAllText(rawLogFile, raw);
                                }
                                else
                                {
                                    Log.Error(raw);
                                }
                            }
                            catch (Exception ex)
                            {
                                Log.Error("Could not retrieve the raw task log for the failed task.", ex);
                            }
                        }
                    }
                }
                if (failed)
                {
                    throw new CommandException("One or more deployment tasks failed.");
                }

                Log.Info("Done!");
            }
            catch (TimeoutException e)
            {
                Log.Error(e.Message);
                var guidedFailureDeployments =
                    from d in deployments
                    where d.UseGuidedFailure
                    select d;
                if (guidedFailureDeployments.Any())
                {
                    Log.Warn("One or more deployments are using Guided Failure. Use the links below to check if intervention is required:");
                    foreach (var guidedFailureDeployment in guidedFailureDeployments)
                    {
                        var environment = Repository.Environments.Get(guidedFailureDeployment.Link("Environment"));
                        Log.WarnFormat("  - {0}: {1}", environment.Name, GetPortalUrl(string.Format("/app#/projects/{0}/releases/{1}/deployments/{2}", project.Slug, release.Version, guidedFailureDeployment.Id)));
                    }
                }
                throw new CommandException(e.Message);
            }
        }
        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 deployment = Repository.Deployments.Create(new DeploymentResource
                {
                    EnvironmentId = promote.Id,
                    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);
            }
        }