/// <summary> /// Gets a project based on the Task Passed /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="task">Task to gather the project from.</param> /// <returns>ProjectResource</returns> public static ProjectResource GetProjectFromTask(OctopusRepository octRepository, TaskResource task) { var project = new ProjectResource(); project = octRepository.Projects.Get(DeploymentHelper.GetDeploymentFromTask(octRepository, task).ProjectId); return(project); }
static void Main(string[] args) { var apiKey = "API-B3ZK7BTFAKSKRTCHQFKAZNPT5Y"; var octopusURL = "http://localhost:82"; var endpoint = new OctopusServerEndpoint(octopusURL, apiKey); var client = new OctopusClient(endpoint); var repository = new OctopusRepository(endpoint); var actionTemplates = repository.ActionTemplates.GetAll(); foreach (var actionTemplate in actionTemplates) { var usages = client.Get <ActionTemplateUsageResource[]>(actionTemplate.Links["Usage"]); var usagesToUpdate = usages.Where(u => u.Version != actionTemplate.Version.ToString()); if (!usagesToUpdate.Any()) { continue; } var actionsByProcessId = usagesToUpdate.GroupBy(u => u.DeploymentProcessId); var actionIdsByProcessId = actionsByProcessId.ToDictionary(g => g.Key, g => g.Select(u => u.ActionId).ToArray()); var actionUpdate = new ActionsUpdateResource(); actionUpdate.Version = actionTemplate.Version; actionUpdate.ActionIdsByProcessId = actionIdsByProcessId; repository.ActionTemplates.UpdateActions(actionTemplate, actionUpdate); } }
/// <summary> /// Replaces a VariableSet Project from a passed file. /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="project">Project to replace variables in.</param> /// <param name="variableSetText">Variable set as JSON text.</param> public static void ReplaceProjectVariableSetFromFile(OctopusRepository octRepository, ProjectResource project, string variableSetText) { var variables = JsonConvert.DeserializeObject <List <VariableResource> >(variableSetText); var variableSet = GetVariableSetFromProject(octRepository, project); variableSet.Variables = variables; octRepository.VariableSets.Modify(variableSet); }
/// <summary> /// Removes a Variable to a Project's VariableSet. /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="project">Project to remove from.</param> /// <param name="variable"></param> public static void RemoveVariableFromProjectVariableSet(OctopusRepository octRepository, ProjectResource project, VariableResource variable) { var currentProjectVariables = GetVariableSetFromProject(octRepository, project); var variableToRemove = currentProjectVariables.Variables.Where(x => x.Id == variable.Id).FirstOrDefault(); currentProjectVariables.Variables.Remove(variableToRemove); octRepository.VariableSets.Modify(currentProjectVariables); }
/// <summary> /// Gathers the Deployment Variables needed for a deployment /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="release">The release to gather the variables from</param> /// <param name="environment">The environment used to gather the variables from</param> /// <returns>Dictionary of DeploymentVariables.</returns> public static IDictionary <string, string> GetDeploymentVariables(OctopusRepository octRepository, ReleaseResource release, EnvironmentResource environment) { var releaseTemplate = octRepository.Releases.GetTemplate(release); var deploymentPromotionTarget = releaseTemplate.PromoteTo.SingleOrDefault(x => x.Id.Equals(environment.Id, StringComparison.OrdinalIgnoreCase)); var deploymentPreview = octRepository.Releases.GetPreview(deploymentPromotionTarget); return(deploymentPreview.Form.Values); }
/// <summary> /// Updates the new Deployment Process with the info from another. (Look you cant update the Steps property, its read only for some reason) /// This ha changed but this is something ill need to look into more /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="newDeploymentProcess"></param> /// <param name="oldDeploymentProcess"></param> public static void UpdateDeploymentProcessFromDeploymentProcess(OctopusRepository octRepository, DeploymentProcessResource newDeploymentProcess, DeploymentProcessResource oldDeploymentProcess) { newDeploymentProcess.Id = oldDeploymentProcess.Id; newDeploymentProcess.ProjectId = oldDeploymentProcess.ProjectId; newDeploymentProcess.Version = oldDeploymentProcess.Version; newDeploymentProcess.Links = oldDeploymentProcess.Links; octRepository.DeploymentProcesses.Modify(newDeploymentProcess); }
/// <summary> /// Run the fixture /// </summary> public static void Run() { _repository = OctopusRepository.GetRepository().Result; Log.Logger.Information("**Running Library Fixture**"); CreateLibraryStuff(); }
/// <summary> /// A simple and efficient way to manage DeploymentTasks /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="deployment">The deployment to manage.</param> public OctopusDeploymentTaskManager(OctopusRepository octRepository, DeploymentResource deployment) { octRepositoryToManage = octRepository; deploymentToManage = deployment; if (!string.IsNullOrWhiteSpace(deploymentToManage.TaskId)) { taskToManage = octRepositoryToManage.Tasks.Get(deploymentToManage.TaskId); } }
/// <summary> /// Creates a LifeCycle /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="lifecycleName">Name of the Lifecycle to create.</param> /// <returns></returns> public static LifecycleResource CreateLifeCycle(OctopusRepository octRepository, string lifecycleName) { var lifecycle = new LifecycleResource() { Name = lifecycleName }; return(octRepository.Lifecycles.Create(lifecycle)); }
/// <summary> /// Creates a Project Group /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="projectGroupName">Name of the new Project Group.</param> /// <returns>Newly Created ProjectGroup</returns> public static ProjectGroupResource CreateProjectGroup(OctopusRepository octRepository, string projectGroupName) { var newProjectGroup = new ProjectGroupResource() { Name = projectGroupName }; return(octRepository.ProjectGroups.Create(newProjectGroup)); }
/// <summary> /// Executes the operation against the specified Octopus Deploy server. /// </summary> /// <param name="serverEndpoint">The Octopus Deploy server endpoint.</param> /// <exception cref="System.ArgumentException"> /// </exception> public void Execute(OctopusServerEndpoint serverEndpoint) { using (var client = clientFactory.CreateClient(serverEndpoint)) { var repository = new OctopusRepository(client); Execute(repository); } }
private static DashboardConfigurationResource CreateDashboard(OctopusRepository repository, IResource[] environments, IResource project) { var dashboardConfiguration = repository.DashboardConfigurations.GetDashboardConfiguration(); dashboardConfiguration.IncludedEnvironmentIds = new ReferenceCollection(environments.Select(e => e.Id)); dashboardConfiguration.IncludedProjectIds = new ReferenceCollection(project.Id); return(dashboardConfiguration); }
/// <summary> /// Responds to the interruption. /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="interruption"></param> /// <param name="response"></param> /// <param name="note"></param> public static void InterruptionReponse(OctopusRepository octRepository, InterruptionResource interruption, InterruptionResponse response, string note) { var stringResponse = Enum.GetName(typeof(InterruptionResponse), response); interruption.Form.Values[ResourceStrings.InterruptionGuidanceKey] = stringResponse; interruption.Form.Values[ResourceStrings.InterruptionNoteKey] = note; octRepository.Interruptions.TakeResponsibility(interruption); octRepository.Interruptions.Submit(interruption); }
/// <summary> /// Creates a release for the passed Project. /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="project">Project to create release for.</param> /// <param name="releaseVersion">Release version to create.</param> /// <param name="releaseNotes">Release Notes.</param> /// <returns>Newly Created ReleaseResource</returns> public static ReleaseResource CreateProjectRelease(OctopusRepository octRepository, ProjectResource project, string releaseVersion, string releaseNotes) { var release = new ReleaseResource(); var projectDeploymentProcess = DeploymentProcessHelper.GetDeploymentProcessFromProject(octRepository, project); release.ReleaseNotes = releaseNotes; release.Version = releaseVersion; release.ProjectId = project.Id; return(octRepository.Releases.Create(release)); }
public OctopusAuthenticationProxy(IOptions <AppSettings> settings) { if (settings == null) { throw new ArgumentNullException(nameof(settings)); } _octopusServerAddress = settings.Value.OctopusServerAddress; _repository = new OctopusRepository(new OctopusServerEndpoint(_octopusServerAddress)); }
/// <summary> /// Run the fixture /// </summary> public static void Run() { _repository = OctopusRepository.GetRepository().Result; Log.Logger.Information("**Running Configuration Fixture**"); SetFeatures(); CreateTeams(); CreateUserRoles(); CreateUsers(); }
/// <summary> /// Gets the manual Intervention Step Instructions /// </summary> /// <param name="octRepository"></param> /// <param name="interruption"></param> /// <returns></returns> public static string GetInterventionDirections(OctopusRepository octRepository, InterruptionResource interruption) { var instructions = string.Empty; var interruptionformElement = interruption.Form.Elements.Where(e => e.Name.Equals(ResourceStrings.InterventionInstructions)).FirstOrDefault(); if (interruptionformElement != null && interruptionformElement.Control.GetType() == typeof(Octopus.Client.Model.Forms.Paragraph)) { instructions = ((Octopus.Client.Model.Forms.Paragraph)interruptionformElement.Control).Text; } return(instructions); }
/// <summary> /// Creates a Project /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="projectName">The anem project to create.</param> /// <param name="projectGroup">The project group resource to add the project to</param> /// <param name="lifecycle">The lifecycle to add to the project.</param> /// <returns>ProjectResource</returns> public static ProjectResource CreateProject(OctopusRepository octRepository, string projectName, ProjectGroupResource projectGroup, LifecycleResource lifecycle) { var newProject = new ProjectResource() { Name = projectName, ProjectGroupId = projectGroup.Id, LifecycleId = lifecycle.Id }; return(octRepository.Projects.Create(newProject)); }
/// <summary> /// Removes any LibraryVariableSets from the passed Project that are not in the passed List. /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="project"></param> /// <param name="libraryVariableSetList"></param> public static void RemoveExtraLibararyVariableSetsFromProject(OctopusRepository octRepository, ProjectResource project, List <LibraryVariableSetResource> libraryVariableSetList) { foreach (var libraryVariableSetId in project.IncludedLibraryVariableSetIds) { if (!libraryVariableSetList.Select(l => l.Id).ToList().Exists(x => x.Equals(libraryVariableSetId))) { project.IncludedLibraryVariableSetIds.Remove(libraryVariableSetId); } } octRepository.Projects.Modify(project); }
/// <summary> /// Adds only the missing LibraryVariableSets to the passed Project. /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="project"></param> /// <param name="libraryVariableSetList"></param> public static void AddMissingLibararyVariableSetsToProject(OctopusRepository octRepository, ProjectResource project, List <LibraryVariableSetResource> libraryVariableSetList) { foreach (var libraryVariableToSet in libraryVariableSetList) { if (!project.IncludedLibraryVariableSetIds.Exists(x => x.Equals(libraryVariableToSet.Id))) { project.IncludedLibraryVariableSetIds.Add(libraryVariableToSet.Id); } } octRepository.Projects.Modify(project); }
protected override void Load(ContainerBuilder builder) { base.Load(builder); builder.RegisterType <CreateRelease>(); builder.RegisterType <Deploy>(); builder.RegisterType <WaitForDeploymentFinish>(); var repo = new OctopusRepository(new OctopusServerEndpoint("http://localhost:8070", "API-9TJC4IMCHVN2J4QU0FVMNVTJQU")); builder.RegisterInstance(repo).AsImplementedInterfaces(); builder.RegisterType <OctopusFacade>().AsImplementedInterfaces(); }
public void AllPropertiesAreNotNull() { var repository = new OctopusRepository(Substitute.For<IOctopusClient>()); var nullPropertiesQ = from p in typeof(OctopusRepository).GetProperties() where p.GetMethod.Invoke(repository, new object[0]) == null select p.Name; var nullProperties = nullPropertiesQ.ToArray(); if (nullProperties.Any()) Assert.Fail("The following properties are null after OctopusAsyncRepository instantiation: " + nullProperties.CommaSeperate()); }
/// <summary> /// Returns the full log of a task /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="task">Task to gather.</param> /// <returns>String of the whole log</returns> public static string GetFullLog(OctopusRepository octRepository, TaskResource task) { var activitySteps = GetActivityElementList(octRepository, task); var output = string.Empty; foreach (var activityStep in activitySteps) { output += ActivityElementHelper.GetLogInfo(activityStep, 0, null) + ResourceStrings.Return; } return(output.Trim()); }
public OctopusService(ICacheManager cacheManager) { ServerUrl = ConfigurationManager.AppSettings["OctopusServerUrl"]; ApiKey = ConfigurationManager.AppSettings["OctopusApiKey"]; var endpoint = new OctopusServerEndpoint(ServerUrl, ApiKey); _repository = new OctopusRepository(endpoint); _cahManager = cacheManager; }
/// <summary> /// Update a Release's Package Step version with another version. /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="release"></param> /// <param name="packageStepDictionary"></param> public static void UpdateReleasePackageVersionByStep(OctopusRepository octRepository, ReleaseResource release, Dictionary <string, SemanticVersion> packageStepDictionary) { var selectedPackageList = release.SelectedPackages.ToDictionary(x => x.ActionName); foreach (var packageStep in packageStepDictionary) { selectedPackageList[packageStep.Key].Version = packageStep.Value.ToString(); } release.SelectedPackages = selectedPackageList.Values.ToList(); octRepository.Releases.Modify(release); }
/// <summary> /// Creates an Environment /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="name">Name of the new Environment.</param> /// <param name="description">Description of the new Environment.</param> /// <param name="guidedFailure">Auto Enable GuidedFailure on Environment.</param> /// <returns>EnvironmentResource.</returns> public static EnvironmentResource CreateEnvironment(OctopusRepository octRepository, string name, string description, bool guidedFailure) { var environmentToCreate = new EnvironmentResource() { Name = name, UseGuidedFailure = guidedFailure, Description = description }; return(octRepository.Environments.Create(environmentToCreate)); }
/// <summary> /// Gathers the list of Environments of a Phase /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="phase">Phase to gather from.</param> /// <returns>Enumerable of EnvironmentResources</returns> public static IEnumerable <EnvironmentResource> GetPhaseEnvironments(OctopusRepository octRepository, PhaseResource phase) { var environmentList = new List <EnvironmentResource>(); foreach (var environment in phase.OptionalDeploymentTargets) { var environmentToAdd = GetEnvironmentById(octRepository, environment); environmentList.Add(environmentToAdd); } return(environmentList); }
public void Setup() { var asyncClient = Substitute.For <IOctopusAsyncClient>(); asyncRepository = new OctopusAsyncRepository(asyncClient); asyncClient.Post <ConvertProjectToGitCommand, ConvertProjectToGitResponse>(Arg.Do <string>(x => asyncUrlUsed = x), Arg.Any <ConvertProjectToGitCommand>()).Returns(new ConvertProjectToGitResponse()); var syncClient = Substitute.For <IOctopusClient>(); syncRepository = new OctopusRepository(syncClient); syncClient.Post <ConvertProjectToGitCommand, ConvertProjectToGitResponse>(Arg.Do <string>(x => syncUrlUsed = x), Arg.Any <ConvertProjectToGitCommand>()).Returns(new ConvertProjectToGitResponse()); }
/// <summary> /// Returns a list of Queued deployments ahead of the passed Deployment, this includes the currently executing one. /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="deployment">Deployment to check what is queued ahead of it.</param> /// <returns>Enumerable of DeploymentResources</returns> public static IEnumerable <DeploymentResource> GetQueuedDeployments(OctopusRepository octRepository, DeploymentResource deployment) { var deploymentsList = new List <DeploymentResource>(); var task = octRepository.Tasks.Get(deployment.TaskId); var queuedBehindTask = octRepository.Tasks.GetQueuedBehindTasks(task).Where(x => x.Arguments.ContainsKey(ResourceStrings.DeploymentIdKey)).Select(x => x.Arguments[ResourceStrings.DeploymentIdKey].ToString()); foreach (var queuedDeployment in queuedBehindTask) { deploymentsList.Add(octRepository.Deployments.Get(queuedDeployment)); } return(deploymentsList); }
private static void Main(string[] args) { try { var parametersDictionary = new Dictionary <ParameterEnum, string>(); if (args.Length == 4) { parametersDictionary.Add(ParameterEnum.ServerUrl, args[0].Trim()); parametersDictionary.Add(ParameterEnum.ApiKey, args[1].Trim()); parametersDictionary.Add(ParameterEnum.ProjectName, args[2].Trim()); parametersDictionary.Add(ParameterEnum.OutputPath, args[3].Trim()); } else { Console.WriteLine($"Required the parameter of ServerUrl, ApiKey and ProjectName"); Environment.Exit(1); } var endpoint = new OctopusServerEndpoint(parametersDictionary[ParameterEnum.ServerUrl], parametersDictionary[ParameterEnum.ApiKey]); var repository = new OctopusRepository(endpoint); var project = repository.Projects.FindOne(p => p.Name == parametersDictionary[ParameterEnum.ProjectName]); var variablesList = new List <VariableViewModel>(); //Dictionary to get Names from Ids var scopeNames = repository.Environments.FindAll().ToDictionary(x => x.Id, x => x.Name); repository.Machines.FindAll().ToList().ForEach(x => scopeNames[x.Id] = x.Name); repository.Projects.GetChannels(project).Items.ToList().ForEach(x => scopeNames[x.Id] = x.Name); var allEnvironments = repository.Environments.FindAll(); var allRoles = repository.MachineRoles.GetAllRoleNames(); var deploymentSteps = repository.DeploymentProcesses.Get(project.DeploymentProcessId).Steps.ToList(); deploymentSteps.SelectMany(x => x.Actions).ToList().ForEach(x => scopeNames[x.Id] = x.Name); //Get All Library Set Variables var allVariables = repository.LibraryVariableSets.FindAll(); ExportVariableSets(parametersDictionary, deploymentSteps, repository, project, variablesList, scopeNames, allVariables, allEnvironments); //var input = Console.ReadLine(); Environment.Exit(0); } catch (Exception ex) { Console.Error.WriteLine($"Error {ex.Message}|{ex.StackTrace}"); Environment.Exit(1); throw ex; } }
/// <summary> /// Gathers MachinePolicy By Id. /// </summary> /// <param name="octRepository">The repository to call against.</param> /// <param name="machinePolicyId">Id of the machine Policy</param> /// <returns>MachinePolicyResource</returns> public static MachinePolicyResource GetMachinePolicyById(OctopusRepository octRepository, string machinePolicyId) { var numberOnly = new int(); if (int.TryParse(machinePolicyId, out numberOnly)) { return(octRepository.MachinePolicies.Get(string.Format(ResourceStrings.MachinePolicyIdFormat, machinePolicyId))); } else { return(octRepository.MachinePolicies.Get(machinePolicyId)); } }
static void Main(string[] args) { var endpoint = new OctopusServerEndpoint("[URL]", "[APIKey]"); var _repository = new OctopusRepository(endpoint); string projectName = "[ProjectName]"; ProjectResource project = _repository.Projects.FindOne(p => p.Name == projectName); var variablesList = new List<VariableViewModel>(); //Dictionary to get Names from Ids Dictionary<string,string> scopeNames = _repository.Environments.FindAll().ToDictionary(x => x.Id, x => x.Name); _repository.Machines.FindAll().ToList().ForEach(x => scopeNames[x.Id] = x.Name); _repository.Projects.GetChannels(project).Items.ToList().ForEach(x => scopeNames[x.Id] = x.Name); _repository.DeploymentProcesses.Get(project.DeploymentProcessId).Steps.SelectMany(x=>x.Actions).ToList().ForEach(x => scopeNames[x.Id] = x.Name); //Get All Library Set Variables List<LibraryVariableSetResource> librarySets = _repository.LibraryVariableSets.FindAll(); foreach (var libraryVariableSetResource in librarySets) { var variables = _repository.VariableSets.Get(libraryVariableSetResource.VariableSetId); var variableSetName = libraryVariableSetResource.Name; foreach (var variable in variables.Variables) { variablesList.Add(new VariableViewModel(variable, variableSetName, scopeNames)); } } //Get All Project Variables for the Project var projectSets = _repository.VariableSets.Get(project.VariableSetId); foreach (var variable in projectSets.Variables) { variablesList.Add(new VariableViewModel(variable, projectName, scopeNames)); } foreach (var vm in variablesList) { Console.WriteLine($"VariableSet:{vm.VariableSetName} Name:{vm.Name} Value:{vm.Value} Scope: {vm.Scope}"); } var input = Console.ReadLine(); }
/// <summary> /// Executes the operation against the specified Octopus Deploy server. /// </summary> /// <param name="repository">The Octopus Deploy server repository.</param> /// <exception cref="System.ArgumentException"> /// </exception> public void Execute(OctopusRepository repository) { var selectedEnvironments = GetEnvironments(repository); var machinePolicy = GetMachinePolicy(repository); var machine = GetMachine(repository); var tenants = GetTenants(repository); ValidateTenantTags(repository); ApplyChanges(machine, selectedEnvironments, machinePolicy, tenants); if (machine.Id != null) repository.Machines.Modify(machine); else repository.Machines.Create(machine); }
/// <summary> /// Executes the operation against the specified Octopus Deploy server. /// </summary> /// <param name="serverEndpoint">The Octopus Deploy server endpoint.</param> /// <exception cref="System.ArgumentException"> /// </exception> public void Execute(OctopusServerEndpoint serverEndpoint) { using (var client = clientFactory.CreateClient(serverEndpoint)) { var repository = new OctopusRepository(client); Execute(repository); } }
List<TenantResource> GetTenants(OctopusRepository repository) { if (Tenants == null || !Tenants.Any()) { return new List<TenantResource>(); } var tenantsByName = repository.Tenants.FindByNames(Tenants); var missing = Tenants.Except(tenantsByName.Select(e => e.Name), StringComparer.OrdinalIgnoreCase).ToArray(); var tenantsById = repository.Tenants.Get(missing); 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."); return tenantsById.Concat(tenantsByName).ToList(); }
void ValidateTenantTags(OctopusRepository repository) { if (TenantTags == null || !TenantTags.Any()) return; var tagSets = repository.TagSets.FindAll(); var missingTags = TenantTags.Where(tt => !tagSets.Any(ts => ts.Tags.Any(t => t.CanonicalTagName.Equals(tt, StringComparison.OrdinalIgnoreCase)))).ToList(); if (missingTags.Any()) throw new ArgumentException($"Could not find the {"tag" + (missingTags.Count == 1 ? "" : "s")} {string.Join(", ", missingTags)} on the Octopus server."); }
MachineResource GetMachine(OctopusRepository repository) { var existing = default(MachineResource); try { existing = repository.Machines.FindByName(MachineName); if (!AllowOverwrite && existing?.Id != null) throw new ArgumentException(string.Format("A machine named '{0}' already exists in the environment. Use the 'force' parameter if you intended to update the existing machine.", MachineName)); } catch (OctopusDeserializationException) // eat it, probably caused by resource incompatability between versions { } return existing ?? new MachineResource(); }
MachinePolicyResource GetMachinePolicy(OctopusRepository repository) { var machinePolicy = default(MachinePolicyResource); if (!string.IsNullOrEmpty(MachinePolicy)) { machinePolicy = repository.MachinePolicies.FindByName(MachinePolicy); if (machinePolicy == null) throw new ArgumentException($"Could not find a machine policy named {MachinePolicy}."); } return machinePolicy; }
List<EnvironmentResource> GetEnvironments(OctopusRepository repository) { var selectedEnvironments = repository.Environments.FindByNames(EnvironmentNames); var missing = EnvironmentNames.Except(selectedEnvironments.Select(e => e.Name), StringComparer.OrdinalIgnoreCase).ToList(); if (missing.Any()) throw new ArgumentException($"Could not find the {"environment" + (missing.Count == 1 ? "" : "s")} {string.Join(", ", missing)} on the Octopus server."); return selectedEnvironments; }