From 2677cc45ebf1f1875fe37070c9cbb358238cb898 Mon Sep 17 00:00:00 2001 From: Dylan Date: Mon, 20 Jan 2025 14:18:14 +1000 Subject: [PATCH 1/5] Add support for CaC Runbooks --- ...AreaShouldNotRegress..NETCore.approved.txt | 73 ++++++++ ...houldNotRegress..NETFramework.approved.txt | 73 ++++++++ .../Model/ModifyRunbookCommand.cs | 7 + .../Model/ModifyRunbookProcessCommand.cs | 7 + .../Model/RunbookRunGitParameters.cs | 39 ++++ .../Model/RunbookRunGitResource.cs | 10 ++ .../Model/RunbookRunPreviewParameters.cs | 15 ++ .../Async/RunbookProcessRepository.cs | 49 ++++- .../Repositories/Async/RunbookRepository.cs | 168 ++++++++++++++++++ 9 files changed, 440 insertions(+), 1 deletion(-) create mode 100644 source/Octopus.Server.Client/Model/ModifyRunbookCommand.cs create mode 100644 source/Octopus.Server.Client/Model/ModifyRunbookProcessCommand.cs create mode 100644 source/Octopus.Server.Client/Model/RunbookRunGitParameters.cs create mode 100644 source/Octopus.Server.Client/Model/RunbookRunGitResource.cs create mode 100644 source/Octopus.Server.Client/Model/RunbookRunPreviewParameters.cs diff --git a/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETCore.approved.txt b/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETCore.approved.txt index b56784fd8..f7a6de82f 100644 --- a/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETCore.approved.txt +++ b/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETCore.approved.txt @@ -3354,6 +3354,21 @@ Octopus.Client.Model Octopus.Client.Model.PersistenceSettingsType Type { get; } String Url { get; set; } } + class GitRunbookRunParameters + { + .ctor(String) + String Comments { get; set; } + String EnvironmentId { get; set; } + String[] ExcludedMachineIds { get; set; } + Boolean ForcePackageDownload { get; set; } + Dictionary FormValues { get; set; } + Nullable QueueTime { get; set; } + Nullable QueueTimeExpiry { get; set; } + String[] SkipActions { get; set; } + String[] SpecificMachineIds { get; set; } + String TenantId { get; set; } + Boolean UseGuidedFailure { get; set; } + } class GitTagResource Octopus.Client.Extensibility.IResource Octopus.Client.Model.IAuditedResource @@ -4050,6 +4065,29 @@ Octopus.Client.Model .ctor() String ChangeDescription { get; set; } } + class ModifyRunbookCommand + Octopus.Client.Extensibility.IResource + Octopus.Client.Model.IAuditedResource + Octopus.Client.Extensibility.INamedResource + Octopus.Client.Extensibility.IHaveSpaceResource + Octopus.Client.Model.IHaveSlugResource + Octopus.Client.Model.ICommitCommand + Octopus.Client.Model.RunbookResource + { + .ctor() + String ChangeDescription { get; set; } + } + class ModifyRunbookProcessCommand + Octopus.Client.Extensibility.IResource + Octopus.Client.Model.IAuditedResource + Octopus.Client.Model.IProcessResource + Octopus.Client.Extensibility.IHaveSpaceResource + Octopus.Client.Model.ICommitCommand + Octopus.Client.Model.RunbookProcessResource + { + .ctor() + String ChangeDescription { get; set; } + } MultipleAccountType { None = 0 @@ -5003,6 +5041,11 @@ Octopus.Client.Model Int32 QuantityToKeep { get; set; } Boolean ShouldKeepForever { get; set; } } + class RunbookRunGitResource + { + .ctor(Octopus.Client.Model.RunbookRunResource[]) + Octopus.Client.Model.RunbookRunResource[] Resources { get; set; } + } class RunbookRunParameters { .ctor() @@ -5025,6 +5068,12 @@ Octopus.Client.Model Nullable UseGuidedFailure { get; set; } static Octopus.Client.Model.RunbookRunParameters MapFrom(Octopus.Client.Model.RunbookRunResource) } + class RunbookRunPreviewParameters + { + .ctor(Octopus.Client.Model.RunbookRunPreviewTarget[]) + Octopus.Client.Model.RunbookRunPreviewTarget[] DeploymentPreviews { get; set; } + Boolean IncludeDisabledSteps { get; set; } + } class RunbookRunPreviewResource Octopus.Client.Extensibility.IResource Octopus.Client.Model.IAuditedResource @@ -5032,6 +5081,12 @@ Octopus.Client.Model { .ctor() } + class RunbookRunPreviewTarget + { + .ctor(String) + String EnvironmentId { get; set; } + String TenantId { get; set; } + } class RunbookRunResource Octopus.Client.Extensibility.IResource Octopus.Client.Model.IAuditedResource @@ -5106,6 +5161,14 @@ Octopus.Client.Model String NextNameIncrement { get; set; } String RunbookProcessId { get; set; } } + class RunGitRunbookParameters + { + .ctor(Octopus.Client.Model.GitRunbookRunParameters[]) + String Notes { get; set; } + Octopus.Client.Model.GitRunbookRunParameters[] Runs { get; set; } + List SelectedGitResources { get; set; } + List SelectedPackages { get; set; } + } class S3FeedResource Octopus.Client.Extensibility.IResource Octopus.Client.Model.IAuditedResource @@ -9193,7 +9256,9 @@ Octopus.Client.Repositories.Async Octopus.Client.Repositories.Async.IGet Octopus.Client.Repositories.Async.IModify { + Task Get(Octopus.Client.Model.ProjectResource, String, String, CancellationToken) Task GetTemplate(Octopus.Client.Model.RunbookProcessResource) + Task Modify(Octopus.Client.Model.ProjectResource, String, Octopus.Client.Model.RunbookProcessResource, String, CancellationToken) } interface IRunbookRepository Octopus.Client.Repositories.Async.IFindByName @@ -9203,13 +9268,21 @@ Octopus.Client.Repositories.Async Octopus.Client.Repositories.Async.IModify Octopus.Client.Repositories.Async.IDelete { + Task Create(Octopus.Client.Model.ProjectResource, String, Octopus.Client.Model.RunbookResource, String, CancellationToken) Task CreateOrModify(Octopus.Client.Model.ProjectResource, String, String) + Task Delete(Octopus.Client.Model.ProjectResource, String, Octopus.Client.Model.RunbookResource, String, CancellationToken) Task FindByName(Octopus.Client.Model.ProjectResource, String) + Task Get(Octopus.Client.Model.ProjectResource, String, String, CancellationToken) Task GetPreview(Octopus.Client.Model.DeploymentPromotionTarget) + Task GetPreview(Octopus.Client.Model.ProjectResource, String, String, Octopus.Client.Model.RunbookRunPreviewParameters, CancellationToken) Task GetRunbookRunTemplate(Octopus.Client.Model.RunbookResource) + Task GetRunbookRunTemplate(Octopus.Client.Model.ProjectResource, String, String, CancellationToken) Task GetRunbookSnapshotTemplate(Octopus.Client.Model.RunbookResource) + Task GetRunbookSnapshotTemplate(Octopus.Client.Model.ProjectResource, String, String, CancellationToken) + Task Modify(Octopus.Client.Model.ProjectResource, String, Octopus.Client.Model.RunbookResource, String, CancellationToken) Task Run(Octopus.Client.Model.RunbookResource, Octopus.Client.Model.RunbookRunResource) Task Run(Octopus.Client.Model.RunbookResource, Octopus.Client.Model.RunbookRunParameters) + Task Run(Octopus.Client.Model.ProjectResource, String, String, Octopus.Client.Model.RunGitRunbookParameters, CancellationToken) } interface IRunbookRunRepository Octopus.Client.Repositories.Async.IGet diff --git a/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETFramework.approved.txt b/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETFramework.approved.txt index 527f635cf..e6413b4f9 100644 --- a/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETFramework.approved.txt +++ b/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETFramework.approved.txt @@ -3371,6 +3371,21 @@ Octopus.Client.Model Octopus.Client.Model.PersistenceSettingsType Type { get; } String Url { get; set; } } + class GitRunbookRunParameters + { + .ctor(String) + String Comments { get; set; } + String EnvironmentId { get; set; } + String[] ExcludedMachineIds { get; set; } + Boolean ForcePackageDownload { get; set; } + Dictionary FormValues { get; set; } + Nullable QueueTime { get; set; } + Nullable QueueTimeExpiry { get; set; } + String[] SkipActions { get; set; } + String[] SpecificMachineIds { get; set; } + String TenantId { get; set; } + Boolean UseGuidedFailure { get; set; } + } class GitTagResource Octopus.Client.Extensibility.IResource Octopus.Client.Model.IAuditedResource @@ -4067,6 +4082,29 @@ Octopus.Client.Model .ctor() String ChangeDescription { get; set; } } + class ModifyRunbookCommand + Octopus.Client.Extensibility.IResource + Octopus.Client.Model.IAuditedResource + Octopus.Client.Extensibility.INamedResource + Octopus.Client.Extensibility.IHaveSpaceResource + Octopus.Client.Model.IHaveSlugResource + Octopus.Client.Model.ICommitCommand + Octopus.Client.Model.RunbookResource + { + .ctor() + String ChangeDescription { get; set; } + } + class ModifyRunbookProcessCommand + Octopus.Client.Extensibility.IResource + Octopus.Client.Model.IAuditedResource + Octopus.Client.Model.IProcessResource + Octopus.Client.Extensibility.IHaveSpaceResource + Octopus.Client.Model.ICommitCommand + Octopus.Client.Model.RunbookProcessResource + { + .ctor() + String ChangeDescription { get; set; } + } MultipleAccountType { None = 0 @@ -5022,6 +5060,11 @@ Octopus.Client.Model Int32 QuantityToKeep { get; set; } Boolean ShouldKeepForever { get; set; } } + class RunbookRunGitResource + { + .ctor(Octopus.Client.Model.RunbookRunResource[]) + Octopus.Client.Model.RunbookRunResource[] Resources { get; set; } + } class RunbookRunParameters { .ctor() @@ -5044,6 +5087,12 @@ Octopus.Client.Model Nullable UseGuidedFailure { get; set; } static Octopus.Client.Model.RunbookRunParameters MapFrom(Octopus.Client.Model.RunbookRunResource) } + class RunbookRunPreviewParameters + { + .ctor(Octopus.Client.Model.RunbookRunPreviewTarget[]) + Octopus.Client.Model.RunbookRunPreviewTarget[] DeploymentPreviews { get; set; } + Boolean IncludeDisabledSteps { get; set; } + } class RunbookRunPreviewResource Octopus.Client.Extensibility.IResource Octopus.Client.Model.IAuditedResource @@ -5051,6 +5100,12 @@ Octopus.Client.Model { .ctor() } + class RunbookRunPreviewTarget + { + .ctor(String) + String EnvironmentId { get; set; } + String TenantId { get; set; } + } class RunbookRunResource Octopus.Client.Extensibility.IResource Octopus.Client.Model.IAuditedResource @@ -5125,6 +5180,14 @@ Octopus.Client.Model String NextNameIncrement { get; set; } String RunbookProcessId { get; set; } } + class RunGitRunbookParameters + { + .ctor(Octopus.Client.Model.GitRunbookRunParameters[]) + String Notes { get; set; } + Octopus.Client.Model.GitRunbookRunParameters[] Runs { get; set; } + List SelectedGitResources { get; set; } + List SelectedPackages { get; set; } + } class S3FeedResource Octopus.Client.Extensibility.IResource Octopus.Client.Model.IAuditedResource @@ -9218,7 +9281,9 @@ Octopus.Client.Repositories.Async Octopus.Client.Repositories.Async.IGet Octopus.Client.Repositories.Async.IModify { + Task Get(Octopus.Client.Model.ProjectResource, String, String, CancellationToken) Task GetTemplate(Octopus.Client.Model.RunbookProcessResource) + Task Modify(Octopus.Client.Model.ProjectResource, String, Octopus.Client.Model.RunbookProcessResource, String, CancellationToken) } interface IRunbookRepository Octopus.Client.Repositories.Async.IFindByName @@ -9228,13 +9293,21 @@ Octopus.Client.Repositories.Async Octopus.Client.Repositories.Async.IModify Octopus.Client.Repositories.Async.IDelete { + Task Create(Octopus.Client.Model.ProjectResource, String, Octopus.Client.Model.RunbookResource, String, CancellationToken) Task CreateOrModify(Octopus.Client.Model.ProjectResource, String, String) + Task Delete(Octopus.Client.Model.ProjectResource, String, Octopus.Client.Model.RunbookResource, String, CancellationToken) Task FindByName(Octopus.Client.Model.ProjectResource, String) + Task Get(Octopus.Client.Model.ProjectResource, String, String, CancellationToken) Task GetPreview(Octopus.Client.Model.DeploymentPromotionTarget) + Task GetPreview(Octopus.Client.Model.ProjectResource, String, String, Octopus.Client.Model.RunbookRunPreviewParameters, CancellationToken) Task GetRunbookRunTemplate(Octopus.Client.Model.RunbookResource) + Task GetRunbookRunTemplate(Octopus.Client.Model.ProjectResource, String, String, CancellationToken) Task GetRunbookSnapshotTemplate(Octopus.Client.Model.RunbookResource) + Task GetRunbookSnapshotTemplate(Octopus.Client.Model.ProjectResource, String, String, CancellationToken) + Task Modify(Octopus.Client.Model.ProjectResource, String, Octopus.Client.Model.RunbookResource, String, CancellationToken) Task Run(Octopus.Client.Model.RunbookResource, Octopus.Client.Model.RunbookRunResource) Task Run(Octopus.Client.Model.RunbookResource, Octopus.Client.Model.RunbookRunParameters) + Task Run(Octopus.Client.Model.ProjectResource, String, String, Octopus.Client.Model.RunGitRunbookParameters, CancellationToken) } interface IRunbookRunRepository Octopus.Client.Repositories.Async.IGet diff --git a/source/Octopus.Server.Client/Model/ModifyRunbookCommand.cs b/source/Octopus.Server.Client/Model/ModifyRunbookCommand.cs new file mode 100644 index 000000000..ea1ed71dc --- /dev/null +++ b/source/Octopus.Server.Client/Model/ModifyRunbookCommand.cs @@ -0,0 +1,7 @@ +namespace Octopus.Client.Model +{ + public class ModifyRunbookCommand : RunbookResource, ICommitCommand + { + public string ChangeDescription { get; set; } + } +} \ No newline at end of file diff --git a/source/Octopus.Server.Client/Model/ModifyRunbookProcessCommand.cs b/source/Octopus.Server.Client/Model/ModifyRunbookProcessCommand.cs new file mode 100644 index 000000000..e9c8e83ec --- /dev/null +++ b/source/Octopus.Server.Client/Model/ModifyRunbookProcessCommand.cs @@ -0,0 +1,7 @@ +namespace Octopus.Client.Model +{ + public class ModifyRunbookProcessCommand : RunbookProcessResource, ICommitCommand + { + public string ChangeDescription { get; set; } + } +} \ No newline at end of file diff --git a/source/Octopus.Server.Client/Model/RunbookRunGitParameters.cs b/source/Octopus.Server.Client/Model/RunbookRunGitParameters.cs new file mode 100644 index 000000000..f4ec14f52 --- /dev/null +++ b/source/Octopus.Server.Client/Model/RunbookRunGitParameters.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Octopus.Client.Model +{ + public class RunGitRunbookParameters(GitRunbookRunParameters[] runs) + { + public GitRunbookRunParameters[] Runs { get; set; } = runs; + public string Notes { get; set; } + public List SelectedPackages { get; set; } = new(); + public List SelectedGitResources { get; set; } = new(); + } + + public class GitRunbookRunParameters(string environmentId) + { + public string EnvironmentId { get; set; } = environmentId; + + public string TenantId { get; set; } + + public bool ForcePackageDownload { get; set; } = false; + + public string[] SkipActions { get; set; } = []; + + public string[] SpecificMachineIds { get; set; } = []; + + public string[] ExcludedMachineIds { get; set; } = []; + + public bool UseGuidedFailure { get; set; } = false; + + public Dictionary FormValues { get; set; } = new(); + + public DateTimeOffset? QueueTime { get; set; } + + public DateTimeOffset? QueueTimeExpiry { get; set; } + + public string Comments { get; set; } + } +} \ No newline at end of file diff --git a/source/Octopus.Server.Client/Model/RunbookRunGitResource.cs b/source/Octopus.Server.Client/Model/RunbookRunGitResource.cs new file mode 100644 index 000000000..2afcddf15 --- /dev/null +++ b/source/Octopus.Server.Client/Model/RunbookRunGitResource.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Octopus.Client.Model; + +public class RunbookRunGitResource(RunbookRunResource[] resources) +{ + public RunbookRunResource[] Resources { get; set; } = resources; +} \ No newline at end of file diff --git a/source/Octopus.Server.Client/Model/RunbookRunPreviewParameters.cs b/source/Octopus.Server.Client/Model/RunbookRunPreviewParameters.cs new file mode 100644 index 000000000..3e12ffd5e --- /dev/null +++ b/source/Octopus.Server.Client/Model/RunbookRunPreviewParameters.cs @@ -0,0 +1,15 @@ +namespace Octopus.Client.Model; + +public class RunbookRunPreviewParameters(RunbookRunPreviewTarget[] deploymentPreviews) +{ + public RunbookRunPreviewTarget[] DeploymentPreviews { get; set; } = deploymentPreviews; + public bool IncludeDisabledSteps { get; set; } +} + +public class RunbookRunPreviewTarget(string environmentId) +{ + + public string EnvironmentId { get; set; } = environmentId; + + public string TenantId { get; set; } +} \ No newline at end of file diff --git a/source/Octopus.Server.Client/Repositories/Async/RunbookProcessRepository.cs b/source/Octopus.Server.Client/Repositories/Async/RunbookProcessRepository.cs index 74f05ddb3..99e24a041 100644 --- a/source/Octopus.Server.Client/Repositories/Async/RunbookProcessRepository.cs +++ b/source/Octopus.Server.Client/Repositories/Async/RunbookProcessRepository.cs @@ -1,15 +1,23 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; using Octopus.Client.Model; +using Octopus.Client.Serialization; namespace Octopus.Client.Repositories.Async { public interface IRunbookProcessRepository : IGet, IModify { Task GetTemplate(RunbookProcessResource runbookProcess); + + // Config as Code methods + Task Get(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken); + Task Modify(ProjectResource project, string gitRef, RunbookProcessResource runbookProcess, string commitMessage, CancellationToken cancellationToken); } class RunbookProcessRepository : BasicRepository, IRunbookProcessRepository { + private readonly string baseGitUri = "~/api/{spaceId}/projects/{projectId}/{gitRef}"; + public RunbookProcessRepository(IOctopusAsyncRepository repository) : base(repository, "RunbookProcesses") { @@ -19,5 +27,44 @@ public Task GetTemplate(RunbookProcessResource { return Client.Get(runbookProcess.Link("RunbookSnapshotTemplate")); } + + public async Task Get(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken) + { + var route = $"{baseGitUri}/runbookProcesses/{{id}}"; + + return await Client.Get( + route, + new + { + spaceId = project.SpaceId, + projectId = project.Id, + gitRef = gitRef, + id = slug + }, + cancellationToken + ).ConfigureAwait(false); + } + + public async Task Modify(ProjectResource project, string gitRef, RunbookProcessResource runbookProcess, string commitMessage, CancellationToken cancellationToken) + { + var route = $"{baseGitUri}/runbookProcesses/{{id}}"; + + var json = Serializer.Serialize(runbookProcess); + var command = Serializer.Deserialize(json); + command.ChangeDescription = commitMessage; + + return await Client.Update( + route, + command, + new + { + spaceId = project.SpaceId, + projectId = project.Id, + gitRef = gitRef, + id = runbookProcess.Id + }, + cancellationToken + ).ConfigureAwait(false); + } } } diff --git a/source/Octopus.Server.Client/Repositories/Async/RunbookRepository.cs b/source/Octopus.Server.Client/Repositories/Async/RunbookRepository.cs index 21c14eac0..d36d88ca5 100644 --- a/source/Octopus.Server.Client/Repositories/Async/RunbookRepository.cs +++ b/source/Octopus.Server.Client/Repositories/Async/RunbookRepository.cs @@ -1,8 +1,10 @@ using System.Linq; +using System.Threading; using System.Threading.Tasks; using Octopus.Client.Editors.Async; using Octopus.Client.Exceptions; using Octopus.Client.Model; +using Octopus.Client.Serialization; namespace Octopus.Client.Repositories.Async { @@ -15,10 +17,21 @@ public interface IRunbookRepository : IFindByName, IGet GetPreview(DeploymentPromotionTarget promotionTarget); Task Run(RunbookResource runbook, RunbookRunResource runbookRun); Task Run(RunbookResource runbook, RunbookRunParameters runbookRunParameters); + + // Config as Code methods + Task Get(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken); + Task Create(ProjectResource project, string gitRef, RunbookResource runbook, string commitMessage, CancellationToken cancellationToken); + Task Modify(ProjectResource project, string gitRef, RunbookResource runbook, string commitMessage, CancellationToken cancellationToken); + Task Delete(ProjectResource project, string gitRef, RunbookResource runbook, string commitMessage, CancellationToken cancellationToken); + Task Run(ProjectResource project, string gitRef, string slug, RunGitRunbookParameters runbookRunParameters, CancellationToken cancellationToken); + Task GetRunbookSnapshotTemplate(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken); + Task GetRunbookRunTemplate(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken); + Task GetPreview(ProjectResource project, string gitRef, string slug, RunbookRunPreviewParameters runbookRunParameters, CancellationToken cancellationToken); } class RunbookRepository : BasicRepository, IRunbookRepository { + private readonly string baseGitUri = "~/api/{spaceId}/projects/{projectId}/{gitRef}"; private readonly SemanticVersion integrationTestVersion; private readonly SemanticVersion versionAfterWhichRunbookRunParametersAreAvailable; @@ -86,5 +99,160 @@ public async Task Run(RunbookResource runbook, RunbookRunP return await Client.Post(runbook.Link("CreateRunbookRun"), runbookRunParameters); } + + // Config as Code + public async Task Get(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken) + { + var route = $"{baseGitUri}/runbooks/{{id}}"; + + return await Client.Get( + route, + new + { + spaceId = project.SpaceId, + projectId = project.Id, + gitRef = gitRef, + id = slug + }, + cancellationToken + ).ConfigureAwait(false); + } + + public async Task Create(ProjectResource project, string gitRef, RunbookResource runbook, string commitMessage, CancellationToken cancellationToken) + { + var route = $"{baseGitUri}/runbooks/v2"; + var command = AppendCommitMessage(runbook, commitMessage); + + return await Client.Create( + route, + command, + new + { + spaceId = project.SpaceId, + projectId = project.Id, + gitRef = gitRef + }, + cancellationToken + ).ConfigureAwait(false); + } + + public async Task Modify(ProjectResource project, string gitRef, RunbookResource runbook, string commitMessage, CancellationToken cancellationToken) + { + var route = $"{baseGitUri}/runbooks/{{id}}"; + var command = AppendCommitMessage(runbook, commitMessage); + + return await Client.Update( + route, + command, + new + { + spaceId = project.SpaceId, + projectId = project.Id, + gitRef = gitRef, + id = runbook.Id + }, + cancellationToken + ).ConfigureAwait(false); + } + + public async Task Delete(ProjectResource project, string gitRef, RunbookResource runbook, string commitMessage, CancellationToken cancellationToken) + { + var route = $"{baseGitUri}/runbooks/{{id}}"; + + await Client.Delete( + route, + new + { + spaceId = project.SpaceId, + projectId = project.Id, + gitRef = gitRef, + slug = runbook.Id + }, + new + { + ChangeDescription = commitMessage + }, + cancellationToken + ).ConfigureAwait(false); + } + + public async Task Run(ProjectResource project, string gitRef, string slug, RunGitRunbookParameters runbookRunParameters, CancellationToken cancellationToken) + { + var route = $"{baseGitUri}/runbooks/{{id}}/run/v1"; + + return await Client.Post( + route, + runbookRunParameters, + new + { + spaceId = project.SpaceId, + projectId = project.Id, + gitRef = gitRef, + id = slug + }, + cancellationToken + ).ConfigureAwait(false); + } + + public async Task GetRunbookSnapshotTemplate(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken) + { + var route = $"{baseGitUri}/runbooks/{{id}}/runbookSnapshotTemplate"; + + return await Client.Get( + route, + new + { + spaceId = project.SpaceId, + projectId = project.Id, + gitRef = gitRef, + id = slug + }, + cancellationToken + ).ConfigureAwait(false); + } + + public async Task GetRunbookRunTemplate(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken) + { + var route = $"{baseGitUri}/runbooks/{{id}}/runbookRunTemplate"; + + return await Client.Get( + route, + new + { + spaceId = project.SpaceId, + projectId = project.Id, + gitRef = gitRef, + id = slug + }, + cancellationToken + ).ConfigureAwait(false); + } + + public async Task GetPreview(ProjectResource project, string gitRef, string slug, RunbookRunPreviewParameters runbookRunPreviewParameters, CancellationToken cancellationToken) + { + var route = $"{baseGitUri}/runbooks/{{id}}/runbookRuns/previews"; + + return await Client.Post( + route, + runbookRunPreviewParameters, + new + { + spaceId = project.SpaceId, + projectId = project.Id, + gitRef = gitRef, + id = slug + }, + cancellationToken + ).ConfigureAwait(false); + } + + ModifyRunbookCommand AppendCommitMessage(RunbookResource runbook, string commitMessage) + { + var json = Serializer.Serialize(runbook); + var command = Serializer.Deserialize(json); + + command.ChangeDescription = commitMessage; + return command; + } } } From 2052d8c855570a3bbf4abe84e6a21a025cf340c1 Mon Sep 17 00:00:00 2001 From: Dylan Date: Wed, 22 Jan 2025 15:42:58 +1000 Subject: [PATCH 2/5] Add support for retrying a Run --- ...AreaShouldNotRegress..NETCore.approved.txt | 1 + ...houldNotRegress..NETFramework.approved.txt | 1 + .../Async/RunbookRunRepository.cs | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETCore.approved.txt b/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETCore.approved.txt index f7a6de82f..02a8a3b6b 100644 --- a/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETCore.approved.txt +++ b/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETCore.approved.txt @@ -9294,6 +9294,7 @@ Octopus.Client.Repositories.Async Task GetTask(Octopus.Client.Model.RunbookRunResource) Task Paginate(String[], String[], String[], Func, Boolean>) Task Paginate(String[], String[], String[], String[], Func, Boolean>) + Task Retry(Octopus.Client.Model.RunbookRunResource, CancellationToken) } interface IRunbookSnapshotRepository Octopus.Client.Repositories.Async.IGet diff --git a/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETFramework.approved.txt b/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETFramework.approved.txt index e6413b4f9..212b40b0c 100644 --- a/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETFramework.approved.txt +++ b/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETFramework.approved.txt @@ -9319,6 +9319,7 @@ Octopus.Client.Repositories.Async Task GetTask(Octopus.Client.Model.RunbookRunResource) Task Paginate(String[], String[], String[], Func, Boolean>) Task Paginate(String[], String[], String[], String[], Func, Boolean>) + Task Retry(Octopus.Client.Model.RunbookRunResource, CancellationToken) } interface IRunbookSnapshotRepository Octopus.Client.Repositories.Async.IGet diff --git a/source/Octopus.Server.Client/Repositories/Async/RunbookRunRepository.cs b/source/Octopus.Server.Client/Repositories/Async/RunbookRunRepository.cs index 1094f83a3..4b3c1bd76 100644 --- a/source/Octopus.Server.Client/Repositories/Async/RunbookRunRepository.cs +++ b/source/Octopus.Server.Client/Repositories/Async/RunbookRunRepository.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; using Octopus.Client.Model; @@ -20,6 +21,7 @@ public interface IRunbookRunRepository : IGet, ICreate> FindBy(string[] projects, string[] runbooks, string[] environments, int skip = 0, int? take = null); Task Paginate(string[] projects, string[] runbooks, string[] environments, Func, bool> getNextPage); Task Paginate(string[] projects, string[] runbooks, string[] environments, string[] tenants, Func, bool> getNextPage); + Task Retry(RunbookRunResource run, CancellationToken cancellationToken); } class RunbookRunRepository : BasicRepository, IRunbookRunRepository @@ -48,5 +50,22 @@ public async Task Paginate(string[] projects, string[] runbooks, string[] enviro { await Client.Paginate(await Repository.Link("RunbookRuns").ConfigureAwait(false), new { projects = projects ?? new string[0], runbooks = runbooks ?? new string[0], environments = environments ?? new string[0], tenants = tenants ?? new string[0] }, getNextPage).ConfigureAwait(false); } + + public async Task Retry(RunbookRunResource run, CancellationToken cancellationToken) + { + var route = "~/api/{spaceId}/projects/{projectId}/runbookRuns/{id}/retry/v1"; + + return await Client.Post( + route, + null, + new + { + spaceId = run.SpaceId, + projectId = run.Id, + id = run.Id + }, + cancellationToken + ).ConfigureAwait(false); + } } } From 91128a44938b84cc59333a11f9e449764f849dc7 Mon Sep 17 00:00:00 2001 From: Dylan Date: Wed, 22 Jan 2025 16:53:36 +1000 Subject: [PATCH 3/5] GetPreview returns an array --- ...ePublicSurfaceAreaShouldNotRegress..NETCore.approved.txt | 2 +- ...icSurfaceAreaShouldNotRegress..NETFramework.approved.txt | 2 +- .../Repositories/Async/RunbookRepository.cs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETCore.approved.txt b/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETCore.approved.txt index 02a8a3b6b..6a1dc6293 100644 --- a/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETCore.approved.txt +++ b/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETCore.approved.txt @@ -9274,7 +9274,7 @@ Octopus.Client.Repositories.Async Task FindByName(Octopus.Client.Model.ProjectResource, String) Task Get(Octopus.Client.Model.ProjectResource, String, String, CancellationToken) Task GetPreview(Octopus.Client.Model.DeploymentPromotionTarget) - Task GetPreview(Octopus.Client.Model.ProjectResource, String, String, Octopus.Client.Model.RunbookRunPreviewParameters, CancellationToken) + Task GetPreview(Octopus.Client.Model.ProjectResource, String, String, Octopus.Client.Model.RunbookRunPreviewParameters, CancellationToken) Task GetRunbookRunTemplate(Octopus.Client.Model.RunbookResource) Task GetRunbookRunTemplate(Octopus.Client.Model.ProjectResource, String, String, CancellationToken) Task GetRunbookSnapshotTemplate(Octopus.Client.Model.RunbookResource) diff --git a/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETFramework.approved.txt b/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETFramework.approved.txt index 212b40b0c..55b01e22f 100644 --- a/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETFramework.approved.txt +++ b/source/Octopus.Client.Tests/PublicSurfaceAreaFixture.ThePublicSurfaceAreaShouldNotRegress..NETFramework.approved.txt @@ -9299,7 +9299,7 @@ Octopus.Client.Repositories.Async Task FindByName(Octopus.Client.Model.ProjectResource, String) Task Get(Octopus.Client.Model.ProjectResource, String, String, CancellationToken) Task GetPreview(Octopus.Client.Model.DeploymentPromotionTarget) - Task GetPreview(Octopus.Client.Model.ProjectResource, String, String, Octopus.Client.Model.RunbookRunPreviewParameters, CancellationToken) + Task GetPreview(Octopus.Client.Model.ProjectResource, String, String, Octopus.Client.Model.RunbookRunPreviewParameters, CancellationToken) Task GetRunbookRunTemplate(Octopus.Client.Model.RunbookResource) Task GetRunbookRunTemplate(Octopus.Client.Model.ProjectResource, String, String, CancellationToken) Task GetRunbookSnapshotTemplate(Octopus.Client.Model.RunbookResource) diff --git a/source/Octopus.Server.Client/Repositories/Async/RunbookRepository.cs b/source/Octopus.Server.Client/Repositories/Async/RunbookRepository.cs index d36d88ca5..dbbba7d2c 100644 --- a/source/Octopus.Server.Client/Repositories/Async/RunbookRepository.cs +++ b/source/Octopus.Server.Client/Repositories/Async/RunbookRepository.cs @@ -26,7 +26,7 @@ public interface IRunbookRepository : IFindByName, IGet Run(ProjectResource project, string gitRef, string slug, RunGitRunbookParameters runbookRunParameters, CancellationToken cancellationToken); Task GetRunbookSnapshotTemplate(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken); Task GetRunbookRunTemplate(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken); - Task GetPreview(ProjectResource project, string gitRef, string slug, RunbookRunPreviewParameters runbookRunParameters, CancellationToken cancellationToken); + Task GetPreview(ProjectResource project, string gitRef, string slug, RunbookRunPreviewParameters runbookRunParameters, CancellationToken cancellationToken); } class RunbookRepository : BasicRepository, IRunbookRepository @@ -228,11 +228,11 @@ public async Task GetRunbookRunTemplate(ProjectResou ).ConfigureAwait(false); } - public async Task GetPreview(ProjectResource project, string gitRef, string slug, RunbookRunPreviewParameters runbookRunPreviewParameters, CancellationToken cancellationToken) + public async Task GetPreview(ProjectResource project, string gitRef, string slug, RunbookRunPreviewParameters runbookRunPreviewParameters, CancellationToken cancellationToken) { var route = $"{baseGitUri}/runbooks/{{id}}/runbookRuns/previews"; - return await Client.Post( + return await Client.Post( route, runbookRunPreviewParameters, new From 67ff46ef4bcc71174f1052c6e3db0d4af7ce5077 Mon Sep 17 00:00:00 2001 From: Dylan Date: Wed, 22 Jan 2025 17:52:08 +1000 Subject: [PATCH 4/5] Pass parameters correctly --- .../Repositories/Async/RunbookRunRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Octopus.Server.Client/Repositories/Async/RunbookRunRepository.cs b/source/Octopus.Server.Client/Repositories/Async/RunbookRunRepository.cs index 4b3c1bd76..18ba38c17 100644 --- a/source/Octopus.Server.Client/Repositories/Async/RunbookRunRepository.cs +++ b/source/Octopus.Server.Client/Repositories/Async/RunbookRunRepository.cs @@ -61,7 +61,7 @@ public async Task Retry(RunbookRunResource run, Cancellation new { spaceId = run.SpaceId, - projectId = run.Id, + projectId = run.ProjectId, id = run.Id }, cancellationToken From 2fd1a0835659ed4e895c767c20018ad698c36d42 Mon Sep 17 00:00:00 2001 From: Dylan Date: Thu, 23 Jan 2025 11:29:05 +1000 Subject: [PATCH 5/5] Add documentation to new methods --- .../Async/RunbookProcessRepository.cs | 10 +++++ .../Repositories/Async/RunbookRepository.cs | 39 +++++++++++++++++++ .../Async/RunbookRunRepository.cs | 5 +++ 3 files changed, 54 insertions(+) diff --git a/source/Octopus.Server.Client/Repositories/Async/RunbookProcessRepository.cs b/source/Octopus.Server.Client/Repositories/Async/RunbookProcessRepository.cs index 99e24a041..cdbf3b411 100644 --- a/source/Octopus.Server.Client/Repositories/Async/RunbookProcessRepository.cs +++ b/source/Octopus.Server.Client/Repositories/Async/RunbookProcessRepository.cs @@ -10,7 +10,17 @@ public interface IRunbookProcessRepository : IGet, IModi Task GetTemplate(RunbookProcessResource runbookProcess); // Config as Code methods + + /// + /// Get a Runbook process for a specific Git ref and slug + /// + /// This operation is for Config as Code Runbooks only Task Get(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken); + + /// + /// Modifies a Runbook process for a specific Git ref and slug + /// + /// This operation is for Config as Code Runbooks only Task Modify(ProjectResource project, string gitRef, RunbookProcessResource runbookProcess, string commitMessage, CancellationToken cancellationToken); } diff --git a/source/Octopus.Server.Client/Repositories/Async/RunbookRepository.cs b/source/Octopus.Server.Client/Repositories/Async/RunbookRepository.cs index dbbba7d2c..3c1007d36 100644 --- a/source/Octopus.Server.Client/Repositories/Async/RunbookRepository.cs +++ b/source/Octopus.Server.Client/Repositories/Async/RunbookRepository.cs @@ -19,13 +19,52 @@ public interface IRunbookRepository : IFindByName, IGet Run(RunbookResource runbook, RunbookRunParameters runbookRunParameters); // Config as Code methods + /// + /// Returns a Runbook for a specific Git ref and slug + /// + /// This operation is for Config as Code Runbooks only Task Get(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken); + + /// + /// Creates a new Runbook with an empty process for a specific Git ref and slug + /// + /// This operation is for Config as Code Runbooks only Task Create(ProjectResource project, string gitRef, RunbookResource runbook, string commitMessage, CancellationToken cancellationToken); + + /// + /// Modifies a Runbook for a specific Git ref and slug + /// + /// This operation is for Config as Code Runbooks only Task Modify(ProjectResource project, string gitRef, RunbookResource runbook, string commitMessage, CancellationToken cancellationToken); + + /// + /// Deletes a Runbook for a specific Git ref and slug + /// + /// This operation is for Config as Code Runbooks only Task Delete(ProjectResource project, string gitRef, RunbookResource runbook, string commitMessage, CancellationToken cancellationToken); + + /// + /// Runs a Runbook for a specific Git ref and slug. Multiple runs for different environments and tenant combinations are configured in the run parameters. + /// + /// This operation is for Config as Code Runbooks only Task Run(ProjectResource project, string gitRef, string slug, RunGitRunbookParameters runbookRunParameters, CancellationToken cancellationToken); + + /// + /// Get a Runbook snapshot template for a specific Git ref and slug + /// + /// This operation is for Config as Code Runbooks only Task GetRunbookSnapshotTemplate(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken); + + /// + /// Get a Runbook run template for a specific Git ref and slug + /// + /// This operation is for Config as Code Runbooks only Task GetRunbookRunTemplate(ProjectResource project, string gitRef, string slug, CancellationToken cancellationToken); + + /// + /// Get a Runbook run preview for a specific Git ref and slug. Multple previews for different environments and tenant combinations are configured in the run parameters. + /// + /// This operation is for Config as Code Runbooks only Task GetPreview(ProjectResource project, string gitRef, string slug, RunbookRunPreviewParameters runbookRunParameters, CancellationToken cancellationToken); } diff --git a/source/Octopus.Server.Client/Repositories/Async/RunbookRunRepository.cs b/source/Octopus.Server.Client/Repositories/Async/RunbookRunRepository.cs index 18ba38c17..998aeb83a 100644 --- a/source/Octopus.Server.Client/Repositories/Async/RunbookRunRepository.cs +++ b/source/Octopus.Server.Client/Repositories/Async/RunbookRunRepository.cs @@ -21,6 +21,11 @@ public interface IRunbookRunRepository : IGet, ICreate> FindBy(string[] projects, string[] runbooks, string[] environments, int skip = 0, int? take = null); Task Paginate(string[] projects, string[] runbooks, string[] environments, Func, bool> getNextPage); Task Paginate(string[] projects, string[] runbooks, string[] environments, string[] tenants, Func, bool> getNextPage); + + /// + /// Retries a specific Runbook Run for a Config as Code Runbook + /// + /// This operation is for Config as Code Runbooks only Task Retry(RunbookRunResource run, CancellationToken cancellationToken); }