diff --git a/src/Cake.AzureDevOps/AzureDevOpsAliases.Pipelines.cs b/src/Cake.AzureDevOps/AzureDevOpsAliases.Pipelines.cs index e3e123a..0db3e72 100644 --- a/src/Cake.AzureDevOps/AzureDevOpsAliases.Pipelines.cs +++ b/src/Cake.AzureDevOps/AzureDevOpsAliases.Pipelines.cs @@ -399,5 +399,91 @@ public static IEnumerable AzureDevOpsBuildTestRuns( new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory()) .GetTestRuns(); } + + /// + /// Gets Azure Pipelines build definitions for the specified settings. + /// + /// The context. + /// Settings for getting the build definitions. + /// + /// Get build definitions running on Azure DevOps Server: + /// + /// + /// + /// + /// The build definitions or an empty list of build definitions. + [CakeMethodAlias] + [CakeAliasCategory("Azure Pipelines")] + [CakeNamespaceImport("Cake.AzureDevOps.Pipelines")] + public static IEnumerable AzureDevOpsBuildDefinitions( + this ICakeContext context, + AzureDevOpsBuildsSettings settings) + { + context.NotNull(nameof(context)); + settings.NotNull(nameof(settings)); + + return AzureDevOpsBuildsDefinitionHelper.GetAzureDevOpsBuildDefinitions( + context.Log, + settings); + } + + /// + /// Updates a build definition for the specified settings and return the updated build definition. + /// + /// The context. + /// Settings for accessing AzureDevOps. + /// The settings to update the build definition. + /// + /// Updates a build definition running on Azure DevOps Server: + /// + /// + /// + /// + /// The updated Azure DevOps build definition. + [CakeMethodAlias] + [CakeAliasCategory("Azure Pipelines")] + [CakeNamespaceImport("Cake.AzureDevOps.Pipelines")] + public static AzureDevOpsBuildDefinition UpdateAzureDevOpsBuildDefinition( + this ICakeContext context, + AzureDevOpsBuildsSettings settings, + AzureDevOpsUpdateBuildDefinitionSettings updateBuildDefinitionSettings) + { + context.NotNull(nameof(context)); + settings.NotNull(nameof(settings)); + + return AzureDevOpsBuildsDefinitionHelper.UpdateBuildDefinition( + context.Log, + settings, + updateBuildDefinitionSettings); + } } } diff --git a/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuildDefinition.cs b/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuildDefinition.cs new file mode 100644 index 0000000..f19cd7e --- /dev/null +++ b/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuildDefinition.cs @@ -0,0 +1,23 @@ +namespace Cake.AzureDevOps.Pipelines +{ + /// + /// Represents of an build definition. + /// + public class AzureDevOpsBuildDefinition + { + /// + /// Gets the attempt of the build. + /// + public int Id { get; internal set; } + + /// + /// Gets the name of the build definition reference. + /// + public string Name { get; internal set; } + + /// + /// Gets the queue status. + /// + public AzureDevOpsDefinitionQueueStatus QueueStatus { get; internal set; } + } +} diff --git a/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuildsDefinitionHelper.cs b/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuildsDefinitionHelper.cs new file mode 100644 index 0000000..4fcbfaf --- /dev/null +++ b/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuildsDefinitionHelper.cs @@ -0,0 +1,125 @@ +namespace Cake.AzureDevOps.Pipelines +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Cake.Core.Diagnostics; + using Microsoft.TeamFoundation.Build.WebApi; + + /// + /// Provides functions for AzureDevOps build definitions. + /// + internal static class AzureDevOpsBuildsDefinitionHelper + { + /// + /// Returns the build definitions for the . + /// + /// The Cake log context. + /// Settings for accessing AzureDevOps. + /// The build definitions for the the . + internal static IEnumerable GetAzureDevOpsBuildDefinitions( + ICakeLog log, + AzureDevOpsBuildsSettings settings) + { + log.NotNull(nameof(log)); + settings.NotNull(nameof(settings)); + + List buildDefinitions = null; + + using (var buildHttpClient = new BuildClientFactory().CreateBuildClient(settings.CollectionUrl, settings.Credentials)) + { + if (settings.ProjectGuid != Guid.Empty) + { + buildDefinitions = + buildHttpClient + .GetDefinitionsAsync(settings.ProjectGuid) + .ConfigureAwait(false) + .GetAwaiter() + .GetResult(); + } + else if (!string.IsNullOrWhiteSpace(settings.ProjectName)) + { + buildDefinitions = + buildHttpClient + .GetDefinitionsAsync(settings.ProjectName) + .ConfigureAwait(false) + .GetAwaiter() + .GetResult(); + } + else + { + throw new ArgumentOutOfRangeException( + nameof(settings), + "Either ProjectGuid or ProjectName needs to be set"); + } + + log.Verbose( + "{0} Build definitions found", + buildDefinitions.Count); + + return buildDefinitions + .Select(x => x.ToAzureDevOpsBuildDefinition()) + .ToList(); + } + } + + /// + /// Updates a build definition with the new build definition settings and returns the updated build definition. + /// + /// The Cake log context. + /// Settings for accessing AzureDevOps. + /// The settings to update the build definition. + /// The updated Azure DevOps build definition. + internal static AzureDevOpsBuildDefinition UpdateBuildDefinition( + ICakeLog log, + AzureDevOpsBuildsSettings settings, + AzureDevOpsUpdateBuildDefinitionSettings updateBuildDefinitionSettings) + { + log.NotNull(nameof(log)); + settings.NotNull(nameof(settings)); + updateBuildDefinitionSettings.NotNull(nameof(updateBuildDefinitionSettings)); + + using (var buildHttpClient = new BuildClientFactory().CreateBuildClient(settings.CollectionUrl, settings.Credentials)) + { + BuildDefinition buildDefinitionToUpdate = null; + + if (settings.ProjectGuid != Guid.Empty) + { + buildDefinitionToUpdate = + buildHttpClient + .GetDefinitionAsync(settings.ProjectGuid, updateBuildDefinitionSettings.Id) + .ConfigureAwait(false) + .GetAwaiter() + .GetResult(); + } + else if (!string.IsNullOrWhiteSpace(settings.ProjectName)) + { + buildDefinitionToUpdate = + buildHttpClient + .GetDefinitionAsync(settings.ProjectName, updateBuildDefinitionSettings.Id) + .ConfigureAwait(false) + .GetAwaiter() + .GetResult(); + } + else + { + throw new ArgumentOutOfRangeException( + nameof(settings), + "Either ProjectGuid or ProjectName needs to be set"); + } + + buildDefinitionToUpdate.QueueStatus = updateBuildDefinitionSettings.QueueStatus.ToDefinitionQueueStatus(); + buildDefinitionToUpdate.Comment = updateBuildDefinitionSettings.Comment; + + var updatedBuildDefinition = + buildHttpClient + .UpdateDefinitionAsync(buildDefinitionToUpdate) + .ConfigureAwait(false) + .GetAwaiter() + .GetResult(); + + return updatedBuildDefinition.ToAzureDevOpsBuildDefinition(); + } + } + } +} diff --git a/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuildsHelper.cs b/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuildsHelper.cs index 08b64b7..df9d179 100644 --- a/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuildsHelper.cs +++ b/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuildsHelper.cs @@ -34,11 +34,11 @@ internal static IEnumerable GetAzureDevOpsBuilds( authorizedIdenity.Id, authorizedIdenity.DisplayName); - BuildDefinitionReference buildDefinition = null; + AzureDevOpsBuildDefinition buildDefinition = null; if (!string.IsNullOrEmpty(settings.BuildDefinitionName)) { - buildDefinition = GetBuildDefinition(log, buildHttpClient, settings); + buildDefinition = GetBuildDefinition(log, settings); if (buildDefinition == null) { throw new InvalidOperationException($"Build definition '{settings.BuildDefinitionName}' not found"); @@ -105,45 +105,21 @@ internal static IEnumerable GetAzureDevOpsBuilds( /// Returns the build definition for the . /// /// The Cake log context. - /// The Http build client. /// Settings for accessing AzureDevOps. /// The build definition for the BuildDefinitionName on . /// null if the BuildDefinitionName was not set or no build definition was found. - private static BuildDefinitionReference GetBuildDefinition( + private static AzureDevOpsBuildDefinition GetBuildDefinition( ICakeLog log, - BuildHttpClient buildHttpClient, AzureDevOpsBuildsSettings settings) { log.NotNull(nameof(log)); - buildHttpClient.NotNull(nameof(buildHttpClient)); settings.NotNull(nameof(settings)); - List buildDefinitions = null; - - if (settings.ProjectGuid != Guid.Empty) - { - buildDefinitions = - buildHttpClient - .GetDefinitionsAsync(settings.ProjectGuid) - .ConfigureAwait(false) - .GetAwaiter() - .GetResult(); - } - else if (!string.IsNullOrWhiteSpace(settings.ProjectName)) - { - buildDefinitions = - buildHttpClient - .GetDefinitionsAsync(settings.ProjectName) - .ConfigureAwait(false) - .GetAwaiter() - .GetResult(); - } - else - { - throw new ArgumentOutOfRangeException( - nameof(settings), - "Either ProjectGuid or ProjectName needs to be set"); - } + var buildDefinitions = + AzureDevOpsBuildsDefinitionHelper + .GetAzureDevOpsBuildDefinitions( + log, + settings); var buildDefinition = buildDefinitions diff --git a/src/Cake.AzureDevOps/Pipelines/AzureDevOpsDefinitionQueueStatus.cs b/src/Cake.AzureDevOps/Pipelines/AzureDevOpsDefinitionQueueStatus.cs new file mode 100644 index 0000000..43db692 --- /dev/null +++ b/src/Cake.AzureDevOps/Pipelines/AzureDevOpsDefinitionQueueStatus.cs @@ -0,0 +1,29 @@ +namespace Cake.AzureDevOps.Pipelines +{ + /// + /// Possible states of a build queue. + /// + public enum AzureDevOpsDefinitionQueueStatus : byte + { + /// + /// When enabled the definition queue allows builds to be queued by users, the system + /// will queue scheduled, gated and continuous integration builds, and the queued + /// builds will be started by the system. + /// + Enabled = 0, + + /// + /// When paused the definition queue allows builds to be queued by users and the + /// system will queue scheduled, gated and continuous integration builds. Builds + /// in the queue will not be started by the system.$ + /// + Paused = 1, + + /// + /// When disabled the definition queue will not allow builds to be queued by users + /// and the system will not queue scheduled, gated or continuous integration builds. + /// Builds already in the queue will not be started by the system. + /// + Disabled = 2, + } +} diff --git a/src/Cake.AzureDevOps/Pipelines/AzureDevOpsUpdateBuildDefinitionSettings.cs b/src/Cake.AzureDevOps/Pipelines/AzureDevOpsUpdateBuildDefinitionSettings.cs new file mode 100644 index 0000000..1530320 --- /dev/null +++ b/src/Cake.AzureDevOps/Pipelines/AzureDevOpsUpdateBuildDefinitionSettings.cs @@ -0,0 +1,25 @@ +namespace Cake.AzureDevOps.Pipelines +{ + using Microsoft.TeamFoundation.Build.WebApi; + + /// + /// Class which contains settings for updating a build definition. + /// + public class AzureDevOpsUpdateBuildDefinitionSettings + { + /// + /// Gets or sets the id of the build definition. + /// + public int Id; + + /// + /// Gets or sets the status of the queue. + /// + public AzureDevOpsDefinitionQueueStatus QueueStatus; + + /// + /// Gets or sets the save-time comment of the queue. + /// + public string Comment; + } +} diff --git a/src/Cake.AzureDevOps/Pipelines/BuildDefinitionReferenceExtensions.cs b/src/Cake.AzureDevOps/Pipelines/BuildDefinitionReferenceExtensions.cs new file mode 100644 index 0000000..bae096a --- /dev/null +++ b/src/Cake.AzureDevOps/Pipelines/BuildDefinitionReferenceExtensions.cs @@ -0,0 +1,28 @@ +namespace Cake.AzureDevOps.Pipelines +{ + using Microsoft.TeamFoundation.Build.WebApi; + + /// + /// Extensions for the class. + /// + internal static class BuildDefinitionReferenceExtensions + { + /// + /// Converts a to an . + /// + /// Build definition reference record to convert. + /// Converted build definition record. + public static AzureDevOpsBuildDefinition ToAzureDevOpsBuildDefinition(this BuildDefinitionReference buildDefinitionReference) + { + buildDefinitionReference.NotNull(nameof(buildDefinitionReference)); + + return + new AzureDevOpsBuildDefinition + { + Id = buildDefinitionReference.Id, + Name = buildDefinitionReference.Name, + QueueStatus = buildDefinitionReference.QueueStatus.ToAzureDevOpsDefinitionQueueStatus(), + }; + } + } +} diff --git a/src/Cake.AzureDevOps/Pipelines/DefinitionQueueStatusExtensions.cs b/src/Cake.AzureDevOps/Pipelines/DefinitionQueueStatusExtensions.cs new file mode 100644 index 0000000..69a5c75 --- /dev/null +++ b/src/Cake.AzureDevOps/Pipelines/DefinitionQueueStatusExtensions.cs @@ -0,0 +1,50 @@ +namespace Cake.AzureDevOps.Pipelines +{ + using Microsoft.TeamFoundation.Build.WebApi; + + /// + /// Extensions for the class. + /// + internal static class DefinitionQueueStatusExtensions + { + /// + /// Converts a to an . + /// + /// Status to convert. + /// Converted status. + public static AzureDevOpsDefinitionQueueStatus ToAzureDevOpsDefinitionQueueStatus(this DefinitionQueueStatus status) + { + switch (status) + { + case DefinitionQueueStatus.Enabled: + return AzureDevOpsDefinitionQueueStatus.Enabled; + case DefinitionQueueStatus.Paused: + return AzureDevOpsDefinitionQueueStatus.Paused; + case DefinitionQueueStatus.Disabled: + return AzureDevOpsDefinitionQueueStatus.Disabled; + default: + throw new System.Exception("Unknown value"); + } + } + + /// + /// Converts a to an . + /// + /// Status to convert. + /// Converted status. + public static DefinitionQueueStatus ToDefinitionQueueStatus(this AzureDevOpsDefinitionQueueStatus status) + { + switch (status) + { + case AzureDevOpsDefinitionQueueStatus.Enabled: + return DefinitionQueueStatus.Enabled; + case AzureDevOpsDefinitionQueueStatus.Paused: + return DefinitionQueueStatus.Paused; + case AzureDevOpsDefinitionQueueStatus.Disabled: + return DefinitionQueueStatus.Disabled; + default: + throw new System.Exception("Unknown value"); + } + } + } +}