public void ShouldCreateReleaseTemplateResourceFromCreatorConfig() { // arrange ReleaseTemplateCreator releaseTemplateCreator = new ReleaseTemplateCreator(); CreatorConfig creatorConfig = new CreatorConfig() { apis = new List <APIConfig>() }; APIConfig api = new APIConfig() { name = "name", apiRevision = "2", isCurrent = true, suffix = "suffix", subscriptionRequired = true, openApiSpec = "https://petstore.swagger.io/v2/swagger.json", }; creatorConfig.apis.Add(api); // act string[] dependsOn = new string[] { "dependsOn" }; ReleaseTemplateResource releaseTemplateResource = releaseTemplateCreator.CreateAPIReleaseTemplateResource(api, dependsOn); // assert string releaseName = $""; Assert.Equal($"[concat(parameters('apimServiceName'), '/{api.name}/release-revision-{api.apiRevision}')]", releaseTemplateResource.name); Assert.Equal(dependsOn, releaseTemplateResource.dependsOn); Assert.Equal($"Release created to make revision {api.apiRevision} current.", releaseTemplateResource.properties.notes); Assert.Equal($"[resourceId('Microsoft.ApiManagement/service/apis', parameters('apimServiceName'), '{api.name}')]", releaseTemplateResource.properties.apiId); }
public ReleasePlan(ProjectResource project, ChannelResource channel, ReleaseTemplateResource releaseTemplate, DeploymentProcessResource deploymentProcess, IPackageVersionResolver versionResolver) { Project = project; Channel = channel; ReleaseTemplate = releaseTemplate; scriptSteps = deploymentProcess.Steps .SelectMany(s => s.Actions) .Select(a => new { StepName = a.Name, PackageId = a.Properties.ContainsKey("Octopus.Action.Package.PackageId") ? a.Properties["Octopus.Action.Package.PackageId"].Value : string.Empty, FeedId = a.Properties.ContainsKey("Octopus.Action.Package.FeedId") ? a.Properties["Octopus.Action.Package.FeedId"].Value : string.Empty, a.IsDisabled, a.Channels, }) .Where(x => string.IsNullOrEmpty(x.PackageId) && x.IsDisabled == false) // only consider enabled script steps .Where(a => !a.Channels.Any() || a.Channels.Contains(channel.Id)) // only include actions without channel scope or with a matchign channel scope .Select(x => new ReleasePlanItem(x.StepName, null, null, true, null) { IsDisabled = x.IsDisabled }).ToArray(); packageSteps = releaseTemplate.Packages.Select( p => new ReleasePlanItem( p.StepName, p.PackageId, p.FeedId, p.IsResolvable, versionResolver.ResolveVersion(p.StepName, p.PackageId))).ToArray(); }
public ReleasePlan(ReleaseTemplateResource releaseTemplate, IPackageVersionResolver versionResolver) { steps.AddRange( releaseTemplate.Packages.Select(p => new ReleasePlanItem( p.StepName, p.NuGetPackageId, p.NuGetFeedId, p.IsResolvable, versionResolver.ResolveVersion(p.StepName) ?? versionResolver.ResolveVersion(p.NuGetPackageId) )) ); }
public ReleasePlan(ProjectResource project, ChannelResource channel, ReleaseTemplateResource releaseTemplate, IPackageVersionResolver versionResolver) { Project = project; Channel = channel; ReleaseTemplate = releaseTemplate; steps = releaseTemplate.Packages.Select( p => new ReleasePlanItem( p.StepName, p.PackageId, p.FeedId, p.IsResolvable, versionResolver.ResolveVersion(p.StepName, p.PackageId))) .ToArray(); }
public List <TemplateResource> CreateChildResourceTemplates(APIConfig api) { List <TemplateResource> resources = new List <TemplateResource>(); // all child resources will depend on the api string[] dependsOn = new string[] { $"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{ParameterNames.ApimServiceName}'), '{api.name}')]" }; PolicyTemplateResource apiPolicyResource = api.policy != null?this.policyTemplateCreator.CreateAPIPolicyTemplateResource(api, dependsOn) : null; List <PolicyTemplateResource> operationPolicyResources = api.operations != null?this.policyTemplateCreator.CreateOperationPolicyTemplateResources(api, dependsOn) : null; List <ProductAPITemplateResource> productAPIResources = api.products != null?this.productAPITemplateCreator.CreateProductAPITemplateResources(api, dependsOn) : null; List <TagAPITemplateResource> tagAPIResources = api.tags != null?this.tagAPITemplateCreator.CreateTagAPITemplateResources(api, dependsOn) : null; DiagnosticTemplateResource diagnosticTemplateResource = api.diagnostic != null?this.diagnosticTemplateCreator.CreateAPIDiagnosticTemplateResource(api, dependsOn) : null; // add release resource if the name has been appended with ;rev{revisionNumber} ReleaseTemplateResource releaseTemplateResource = api.name.Contains(";rev") == true?this.releaseTemplateCreator.CreateAPIReleaseTemplateResource(api, dependsOn) : null; // add resources if not null if (apiPolicyResource != null) { resources.Add(apiPolicyResource); } if (operationPolicyResources != null) { resources.AddRange(operationPolicyResources); } if (productAPIResources != null) { resources.AddRange(productAPIResources); } if (tagAPIResources != null) { resources.AddRange(tagAPIResources); } if (diagnosticTemplateResource != null) { resources.Add(diagnosticTemplateResource); } if (releaseTemplateResource != null) { resources.Add(releaseTemplateResource); } return(resources); }
public ReleaseTemplateResource CreateAPIReleaseTemplateResource(ApiDeploymentDefinition api, string[] dependsOn) { string releaseName = $"release-revision-{api.ApiRevision}"; // create release resource with properties ReleaseTemplateResource releaseTemplateResource = new ReleaseTemplateResource() { Name = $"[concat(parameters('ApimServiceName'), '/{api.Name}/{releaseName}')]", Properties = new ReleaseTemplateProperties() { Notes = $"Release created to make revision {api.ApiRevision} current.", ApiId = $"[resourceId('{ResourceType.Api}', parameters('ApimServiceName'), '{api.Name}')]" }, DependsOn = dependsOn }; return(releaseTemplateResource); }
public ReleaseTemplateResource CreateAPIReleaseTemplateResource(APIConfig api, string[] dependsOn) { string releaseName = $"release-revision-{api.apiRevision}"; // create release resource with properties ReleaseTemplateResource releaseTemplateResource = new ReleaseTemplateResource() { Name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{api.name}/{releaseName}')]", Type = ResourceTypeConstants.APIRelease, ApiVersion = GlobalConstants.ApiVersion, Properties = new ReleaseTemplateProperties() { notes = $"Release created to make revision {api.apiRevision} current.", apiId = $"[resourceId('Microsoft.ApiManagement/service/apis', parameters('{ParameterNames.ApimServiceName}'), '{api.name}')]" }, DependsOn = dependsOn }; return(releaseTemplateResource); }
public void Setup() { // setup data objects channelVersionRules = new List <ChannelVersionRuleResource>(); projectResource = new ProjectResource { DeploymentProcessId = TestHelpers.GetId("deploymentprocess"), Id = TestHelpers.GetId("project") }; deploymentProcessResource = new DeploymentProcessResource { ProjectId = projectResource.Id, Id = projectResource.DeploymentProcessId }; releaseTemplateResource = new ReleaseTemplateResource { DeploymentProcessId = projectResource.DeploymentProcessId, Packages = new List <ReleaseTemplatePackage>(), Id = TestHelpers.GetId("releaseTemplate") }; channelResource = new ChannelResource { IsDefault = true, Id = TestHelpers.GetId("channel"), ProjectId = projectResource.Id, Rules = channelVersionRules, Name = TestHelpers.GetId("channelname") }; feedResource = new FeedResource { Links = new LinkCollection { { "SearchTemplate", TestHelpers.GetId("searchUri") } } }; // setup mocks logger = Substitute.For <ILogger>(); versionResolver = Substitute.For <IPackageVersionResolver>(); versionRuleTester = Substitute.For <IChannelVersionRuleTester>(); deploymentProcessRepository = Substitute.For <IDeploymentProcessRepository>(); deploymentProcessRepository.Get(projectResource.DeploymentProcessId) .Returns(Task.FromResult(deploymentProcessResource)); deploymentProcessRepository .GetTemplate(Arg.Is <DeploymentProcessResource>(deploymentProcessResource), Arg.Is <ChannelResource>(channelResource)).Returns(Task.FromResult(releaseTemplateResource)); versionRuleTester .Test(Arg.Any <IOctopusAsyncRepository>(), Arg.Any <ChannelVersionRuleResource>(), Arg.Any <string>()) .Returns(Task.FromResult(channelVersionRuleTestResult)); releaseRepository = Substitute.For <IReleaseRepository>(); feedRepository = Substitute.For <IFeedRepository>(); feedRepository.Get(Arg.Any <string>()).Returns(feedResource); repository = Substitute.For <IOctopusAsyncRepository>(); repository.DeploymentProcesses.Returns(deploymentProcessRepository); repository.Releases.Returns(releaseRepository); repository.Feeds.Returns(feedRepository); repository.Client .Get <List <PackageResource> >(Arg.Any <string>(), Arg.Any <IDictionary <string, object> >()).Returns(packages); builder = new ReleasePlanBuilder(logger, versionResolver, versionRuleTester); }
static void Main(string[] args) { var apiKey = "API-XXXXXXXXXXXXXXXXXXXXXXXXXX"; var octopusURL = "https://octopus.url"; var projectName = "testproject2"; var releaseVersion = ""; var channelName = "Default"; var environmentName = "Dev"; var fixedPackageVersion = ""; var endpoint = new OctopusServerEndpoint(octopusURL, apiKey); var repository = new OctopusRepository(endpoint); var project = repository.Projects.FindByName(projectName); var environment = repository.Environments.FindByName(environmentName); var template = new ReleaseTemplateResource(); var process = new DeploymentProcessResource(); process = repository.DeploymentProcesses.Get(project.DeploymentProcessId); var channel = repository.Channels.FindByName(project, channelName); template = repository.DeploymentProcesses.GetTemplate(process, channel); //if you dont pass a value to newReleaseVersion, It'll calculate it using the version template of your project. Just like when you hit the "Create Release" button from the web portal if (string.IsNullOrEmpty(releaseVersion)) { releaseVersion = template.NextVersionIncrement; } //Creating the release object var newrelease = new ReleaseResource { ProjectId = project.Id, Version = releaseVersion }; foreach (var package in template.Packages) { var selectedPackage = new SelectedPackage { ActionName = package.ActionName, PackageReferenceName = package.PackageReferenceName }; //If you don't pass a value to FixedPackageVersion, Octopus will look for the latest one in the feed. if (string.IsNullOrEmpty(fixedPackageVersion)) { //Gettin the latest version of the package available in the feed. //This is probably the most complicated line. The expression can get tricky, as a step(action) might be a parent and have many children(more nested actions) var packageStep = process.Steps.FirstOrDefault(s => s.Actions.Any(a => a.Name == selectedPackage.ActionName))? .Actions.FirstOrDefault(a => a.Name == selectedPackage.ActionName); var packageId = packageStep.Properties["Octopus.Action.Package.PackageId"].Value; var feedId = packageStep.Properties["Octopus.Action.Package.FeedId"].Value; var feed = repository.Feeds.Get(feedId); var latestPackageVersion = repository.Feeds.GetVersions(feed, new[] { packageId }).FirstOrDefault(); selectedPackage.Version = latestPackageVersion.Version; } else { selectedPackage.Version = fixedPackageVersion; } newrelease.SelectedPackages.Add(selectedPackage); } //Creating the release in Octopus var release = repository.Releases.Create(newrelease); //creating the deployment object var deployment = new DeploymentResource { ReleaseId = release.Id, ProjectId = project.Id, EnvironmentId = environment.Id }; //Deploying the release in Octopus repository.Deployments.Create(deployment); }
private async Task <ReleasePlan> Build(IOctopusAsyncRepository repository, ProjectResource project, ChannelResource channel, string versionPreReleaseTag, ReleaseTemplateResource releaseTemplate, DeploymentProcessResource deploymentProcess) { var plan = new ReleasePlan(project, channel, releaseTemplate, deploymentProcess, versionResolver); if (plan.UnresolvedSteps.Any()) { commandOutputProvider.Debug( "The package version for some steps was not specified. Going to try and resolve those automatically..."); var allRelevantFeeds = await LoadFeedsForSteps(repository, project, plan.UnresolvedSteps); foreach (var unresolved in plan.UnresolvedSteps) { if (!unresolved.IsResolveable) { commandOutputProvider.Error( "The version number for step '{Step:l}' cannot be automatically resolved because the feed or package ID is dynamic.", unresolved.ActionName); continue; } if (!string.IsNullOrEmpty(versionPreReleaseTag)) { commandOutputProvider.Debug("Finding latest package with pre-release '{Tag:l}' for step: {StepName:l}", versionPreReleaseTag, unresolved.ActionName); } else { commandOutputProvider.Debug("Finding latest package for step: {StepName:l}", unresolved.ActionName); } if (!allRelevantFeeds.TryGetValue(unresolved.PackageFeedId, out var feed)) { throw new CommandException(string.Format( "Could not find a feed with ID {0}, which is used by step: " + unresolved.ActionName, unresolved.PackageFeedId)); } var filters = BuildChannelVersionFilters(unresolved.ActionName, unresolved.PackageReferenceName, channel); filters["packageId"] = unresolved.PackageId; if (!string.IsNullOrWhiteSpace(versionPreReleaseTag)) { filters["preReleaseTag"] = versionPreReleaseTag; } var packages = await repository.Client.Get <List <PackageResource> >(feed.Link("SearchTemplate"), filters) .ConfigureAwait(false); var latestPackage = packages.FirstOrDefault(); if (latestPackage == null) { commandOutputProvider.Error( "Could not find any packages with ID '{PackageId:l}' in the feed '{FeedUri:l}'", unresolved.PackageId, feed.Name); } else { commandOutputProvider.Debug("Selected '{PackageId:l}' version '{Version:l}' for '{StepName:l}'", latestPackage.PackageId, latestPackage.Version, unresolved.ActionName); unresolved.SetVersionFromLatest(latestPackage.Version); } } } // Test each step in this plan satisfies the channel version rules if (channel != null) { foreach (var step in plan.PackageSteps) { // Note the rule can be null, meaning: anything goes var rule = channel.Rules.SingleOrDefault(r => r.ActionPackages.Any(pkg => pkg.DeploymentActionNameMatches(step.ActionName) && pkg.PackageReferenceNameMatches(step.PackageReferenceName))); var result = await versionRuleTester.Test(repository, rule, step.Version, step.PackageFeedId).ConfigureAwait(false); step.SetChannelVersionRuleTestResult(result); } } return(plan); }
public void Setup() { // setup data objects channelVersionRules = new List <ChannelVersionRuleResource>(); projectResource = new ProjectResource { DeploymentProcessId = TestHelpers.GetId("deploymentprocess"), Id = TestHelpers.GetId("project") }; deploymentProcessResource = new DeploymentProcessResource { ProjectId = projectResource.Id, Id = projectResource.DeploymentProcessId }; releaseTemplateResource = new ReleaseTemplateResource { DeploymentProcessId = projectResource.DeploymentProcessId, Packages = new List <ReleaseTemplatePackage>(), Id = TestHelpers.GetId("releaseTemplate") }; channelResource = new ChannelResource { IsDefault = true, Id = TestHelpers.GetId("channel"), ProjectId = projectResource.Id, Rules = channelVersionRules, Name = TestHelpers.GetId("channelname") }; feedResource = new FeedResource { Id = BuiltInFeedId, Name = "Built in feed", Links = new LinkCollection { { "SearchTemplate", TestHelpers.GetId("searchUri") } } }; // setup mocks logger = Substitute.For <ILogger>(); versionResolver = Substitute.For <IPackageVersionResolver>(); versionRuleTester = Substitute.For <IChannelVersionRuleTester>(); commandOutputProvider = Substitute.For <ICommandOutputProvider>(); deploymentProcessRepository = Substitute.For <IDeploymentProcessRepository>(); deploymentProcessRepository.Get(projectResource.DeploymentProcessId) .Returns(Task.FromResult(deploymentProcessResource)); deploymentProcessRepository .GetTemplate(Arg.Is(deploymentProcessResource), Arg.Is(channelResource)) .Returns(Task.FromResult(releaseTemplateResource)); versionRuleTester .Test(Arg.Any <IOctopusAsyncRepository>(), Arg.Any <ChannelVersionRuleResource>(), Arg.Any <string>(), Arg.Any <string>()) .Returns(Task.FromResult(channelVersionRuleTestResult)); deploymentProcessRepositoryBeta = Substitute.For <IDeploymentProcessRepositoryBeta>(); deploymentProcessRepositoryBeta.Get(projectResource, Arg.Any <string>()) .Returns(Task.FromResult(deploymentProcessResource)); var feeds = new List <FeedResource> { feedResource }; releaseRepository = Substitute.For <IReleaseRepository>(); feedRepository = Substitute.For <IFeedRepository>(); feedRepository.Get(Arg.Any <string[]>()).Returns(feeds); feedRepository.FindByNames(Arg.Any <IEnumerable <string> >()).Returns(feeds); repository = Substitute.For <IOctopusAsyncRepository>(); repository.DeploymentProcesses.Returns(deploymentProcessRepository); repository.DeploymentProcesses.Beta().Returns(deploymentProcessRepositoryBeta); repository.Releases.Returns(releaseRepository); repository.Feeds.Returns(feedRepository); repository.Client .Get <List <PackageResource> >(Arg.Any <string>(), Arg.Any <IDictionary <string, object> >()) .Returns(packages); builder = new ReleasePlanBuilder(logger, versionResolver, versionRuleTester, commandOutputProvider); gitReference = null; }