Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(GH-263) Add an alias to update a build definition #267

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions src/Cake.AzureDevOps/AzureDevOpsAliases.Pipelines.cs
Original file line number Diff line number Diff line change
Expand Up @@ -399,5 +399,91 @@ public static IEnumerable<AzureDevOpsTestRun> AzureDevOpsBuildTestRuns(
new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory())
.GetTestRuns();
}

/// <summary>
/// Gets Azure Pipelines build definitions for the specified settings.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="settings">Settings for getting the build definitions.</param>
/// <example>
/// <para>Get build definitions running on Azure DevOps Server:</para>
/// <code>
/// <![CDATA[
/// var buildSettings =
/// new AzureDevOpsBuildsSettings(
/// new Uri("http://myserver:8080/defaultcollection"),
/// "MyProject",
/// AzureDevOpsAuthenticationNtlm());
///
/// var buildDefinitions =
/// AzureDevOpsBuildDefinitions(
/// buildSettings);
/// ]]>
/// </code>
/// </example>
/// <returns>The build definitions or an empty list of build definitions.</returns>
[CakeMethodAlias]
[CakeAliasCategory("Azure Pipelines")]
[CakeNamespaceImport("Cake.AzureDevOps.Pipelines")]
public static IEnumerable<AzureDevOpsBuildDefinition> AzureDevOpsBuildDefinitions(
this ICakeContext context,
AzureDevOpsBuildsSettings settings)
{
context.NotNull(nameof(context));
settings.NotNull(nameof(settings));

return AzureDevOpsBuildsDefinitionHelper.GetAzureDevOpsBuildDefinitions(
context.Log,
settings);
}

/// <summary>
/// Updates a build definition for the specified settings and return the updated build definition.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="settings">Settings for accessing AzureDevOps.</param>
/// <param name="updateBuildDefinitionSettings">The settings to update the build definition.</param>
/// <example>
/// <para>Updates a build definition running on Azure DevOps Server:</para>
/// <code>
/// <![CDATA[
/// var buildSettings =
/// new AzureDevOpsBuildsSettings(
/// new Uri("http://myserver:8080/defaultcollection"),
/// "MyProject",
/// AzureDevOpsAuthenticationNtlm());
///
/// var updateBuildDefinitionSettings =
/// new AzureDevOpsUpdateBuildDefinitionSettings()
/// {
/// Id = 12,
/// QueueStatus = AzureDevOpsDefinitionQueueStatus.Disabled,
/// Comment = "Disable the queue.",
/// };
///
/// var updatedBuildDefinition =
/// UpdateAzureDevOpsBuildDefinition(
/// buildSettings,
/// updateBuildDefinitionSettings);
/// ]]>
/// </code>
/// </example>
/// <returns>The updated Azure DevOps build definition.</returns>
[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);
}
}
}
23 changes: 23 additions & 0 deletions src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuildDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Cake.AzureDevOps.Pipelines
{
/// <summary>
/// Represents of an build definition.
/// </summary>
public class AzureDevOpsBuildDefinition
{
/// <summary>
/// Gets the attempt of the build.
/// </summary>
public int Id { get; internal set; }

/// <summary>
/// Gets the name of the build definition reference.
/// </summary>
public string Name { get; internal set; }

/// <summary>
/// Gets the queue status.
/// </summary>
public AzureDevOpsDefinitionQueueStatus QueueStatus { get; internal set; }
}
}
125 changes: 125 additions & 0 deletions src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuildsDefinitionHelper.cs
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Provides functions for AzureDevOps build definitions.
/// </summary>
internal static class AzureDevOpsBuildsDefinitionHelper
{
/// <summary>
/// Returns the build definitions for the <paramref name="settings"/>.
/// </summary>
/// <param name="log">The Cake log context.</param>
/// <param name="settings">Settings for accessing AzureDevOps.</param>
/// <returns>The build definitions for the the <paramref name="settings"/>.</returns>
internal static IEnumerable<AzureDevOpsBuildDefinition> GetAzureDevOpsBuildDefinitions(
ICakeLog log,
AzureDevOpsBuildsSettings settings)
{
log.NotNull(nameof(log));
settings.NotNull(nameof(settings));

List<BuildDefinitionReference> 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();
}
}

/// <summary>
/// Updates a build definition with the new build definition settings and returns the updated build definition.
/// </summary>
/// <param name="log">The Cake log context.</param>
/// <param name="settings">Settings for accessing AzureDevOps.</param>
/// <param name="updateBuildDefinitionSettings">The settings to update the build definition.</param>
/// <returns>The updated Azure DevOps build definition.</returns>
internal static AzureDevOpsBuildDefinition UpdateBuildDefinition(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be consistent with other areas of this addin (e.g. for pull requestst) this should be implemented on the AzureDevOpsBuildDefinition class instead of a complete separate code flow.

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();
}
}
}
}
40 changes: 8 additions & 32 deletions src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuildsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ internal static IEnumerable<AzureDevOpsBuild> 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");
Expand Down Expand Up @@ -105,45 +105,21 @@ internal static IEnumerable<AzureDevOpsBuild> GetAzureDevOpsBuilds(
/// Returns the build definition for the <paramref name="settings"/>.
/// </summary>
/// <param name="log">The Cake log context.</param>
/// <param name="buildHttpClient">The Http build client.</param>
/// <param name="settings">Settings for accessing AzureDevOps.</param>
/// <returns>The build definition for the BuildDefinitionName on <paramref name="settings"/>.
/// <c>null</c> if the BuildDefinitionName was not set or no build definition was found.</returns>
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<BuildDefinitionReference> 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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace Cake.AzureDevOps.Pipelines
{
/// <summary>
/// Possible states of a build queue.
/// </summary>
public enum AzureDevOpsDefinitionQueueStatus : byte
{
/// <summary>
/// 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.
/// </summary>
Enabled = 0,

/// <summary>
/// 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.$
/// </summary>
Paused = 1,

/// <summary>
/// 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.
/// <summary>
Disabled = 2,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace Cake.AzureDevOps.Pipelines
{
using Microsoft.TeamFoundation.Build.WebApi;

/// <summary>
/// Class which contains settings for updating a build definition.
/// </summary>
public class AzureDevOpsUpdateBuildDefinitionSettings
{
/// <summary>
/// Gets or sets the id of the build definition.
/// </summary>
public int Id;

/// <summary>
/// Gets or sets the status of the queue.
/// </summary>
public AzureDevOpsDefinitionQueueStatus QueueStatus;

/// <summary>
/// Gets or sets the save-time comment of the queue.
/// </summary>
public string Comment;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace Cake.AzureDevOps.Pipelines
{
using Microsoft.TeamFoundation.Build.WebApi;

/// <summary>
/// Extensions for the <see cref="BuildDefinitionReference"/> class.
/// </summary>
internal static class BuildDefinitionReferenceExtensions
{
/// <summary>
/// Converts a <see cref="BuildDefinitionReference"/> to an <see cref="AzureDevOpsBuildDefinition"/>.
/// </summary>
/// <param name="buildDefinitionReference">Build definition reference record to convert.</param>
/// <returns>Converted build definition record.</returns>
public static AzureDevOpsBuildDefinition ToAzureDevOpsBuildDefinition(this BuildDefinitionReference buildDefinitionReference)
{
buildDefinitionReference.NotNull(nameof(buildDefinitionReference));

return
new AzureDevOpsBuildDefinition
{
Id = buildDefinitionReference.Id,
Name = buildDefinitionReference.Name,
QueueStatus = buildDefinitionReference.QueueStatus.ToAzureDevOpsDefinitionQueueStatus(),
};
}
}
}
Loading