diff --git a/src/Cake.AzureDevOps.Tests/Fakes/FakeAllSetBuildClientFactory.cs b/src/Cake.AzureDevOps.Tests/Fakes/FakeAllSetBuildClientFactory.cs index 218c8afd..9c745eb6 100644 --- a/src/Cake.AzureDevOps.Tests/Fakes/FakeAllSetBuildClientFactory.cs +++ b/src/Cake.AzureDevOps.Tests/Fakes/FakeAllSetBuildClientFactory.cs @@ -1,10 +1,12 @@ namespace Cake.AzureDevOps.Tests.Fakes { using System; + using System.Collections.Generic; using System.Threading; using Cake.AzureDevOps.Authentication; using Microsoft.TeamFoundation.Build.WebApi; using Microsoft.TeamFoundation.Core.WebApi; + using Microsoft.VisualStudio.Services.WebApi; using Moq; public class FakeAllSetBuildClientFactory : FakeBuildClientFactory @@ -29,6 +31,12 @@ public override BuildHttpClient CreateBuildClient(Uri collectionUrl, IAzureDevOp Project = new TeamProjectReference { Name = projectName }, }); + mock.Setup(arg => arg.GetBuildWorkItemsRefsAsync(It.IsAny(), It.IsAny(), It.IsAny(), null, default)) + .ReturnsAsync((string projectName, int buildId, int? top, object userState, CancellationToken token) => new List + { + new ResourceRef { Id = "42" }, + }); + mock = this.Setup(mock); return mock.Object; diff --git a/src/Cake.AzureDevOps.Tests/Fakes/FakeAllSetWorkItemTrackingClientFactory.cs b/src/Cake.AzureDevOps.Tests/Fakes/FakeAllSetWorkItemTrackingClientFactory.cs new file mode 100644 index 00000000..59027717 --- /dev/null +++ b/src/Cake.AzureDevOps.Tests/Fakes/FakeAllSetWorkItemTrackingClientFactory.cs @@ -0,0 +1,36 @@ +namespace Cake.AzureDevOps.Tests.Fakes +{ + using System; + using System.Collections.Generic; + using System.Threading; + using Cake.AzureDevOps.Authentication; + using Microsoft.TeamFoundation.TestManagement.WebApi; + using Microsoft.TeamFoundation.WorkItemTracking.WebApi; + using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models; + using Moq; + + public class FakeAllSetWorkItemTrackingClientFactory : FakeWorkItemTrackingClientFactory + { + public override WorkItemTrackingHttpClient CreateWorkItemTrackingClient(Uri collectionUrl, IAzureDevOpsCredentials credentials) + { + var mock = new Mock(MockBehavior.Strict, collectionUrl, credentials.ToVssCredentials()); + + mock.Setup(arg => arg.GetWorkItemsAsync(It.IsAny>(), It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), null, default)) + .ReturnsAsync((IEnumerable workItemIds, IEnumerable fields, DateTime? asOf, WorkItemExpand? expand, WorkItemErrorPolicy? errorPolicy, object userState, CancellationToken token) => + { + var result = new List(); + + foreach (var workItemId in workItemIds) + { + result.Add(new WorkItem { Id = workItemId }); + } + + return result; + }); + + mock = this.Setup(mock); + + return mock.Object; + } + } +} \ No newline at end of file diff --git a/src/Cake.AzureDevOps.Tests/Fakes/FakeWorkItemTrackingClientFactory.cs b/src/Cake.AzureDevOps.Tests/Fakes/FakeWorkItemTrackingClientFactory.cs new file mode 100644 index 00000000..61c8ab0f --- /dev/null +++ b/src/Cake.AzureDevOps.Tests/Fakes/FakeWorkItemTrackingClientFactory.cs @@ -0,0 +1,24 @@ +namespace Cake.AzureDevOps.Tests.Fakes +{ + using System; + using Cake.AzureDevOps.Authentication; + using Microsoft.TeamFoundation.WorkItemTracking.WebApi; + using Microsoft.VisualStudio.Services.Identity; + using Moq; + + public abstract class FakeWorkItemTrackingClientFactory : IWorkItemTrackingClientFactory + { + public abstract WorkItemTrackingHttpClient CreateWorkItemTrackingClient(Uri collectionUrl, IAzureDevOpsCredentials credentials); + + public WorkItemTrackingHttpClient CreateWorkItemTrackingClient(Uri collectionUrl, IAzureDevOpsCredentials credentials, out Identity authorizedIdentity) + { + authorizedIdentity = new Identity { ProviderDisplayName = "FakeUser", Id = Guid.NewGuid(), IsActive = true }; + return this.CreateWorkItemTrackingClient(collectionUrl, credentials); + } + + protected virtual Mock Setup(Mock m) + { + return m; + } + } +} diff --git a/src/Cake.AzureDevOps.Tests/Pipelines/AzureDevOpsBuildTests.cs b/src/Cake.AzureDevOps.Tests/Pipelines/AzureDevOpsBuildTests.cs index 999776d5..293cf5ad 100644 --- a/src/Cake.AzureDevOps.Tests/Pipelines/AzureDevOpsBuildTests.cs +++ b/src/Cake.AzureDevOps.Tests/Pipelines/AzureDevOpsBuildTests.cs @@ -23,7 +23,8 @@ public void Should_Return_Empty_List_If_Build_Is_Invalid() fixture.Log, fixture.Settings, fixture.BuildClientFactory, - fixture.TestManagementClientFactory); + fixture.TestManagementClientFactory, + fixture.WorkItemTrackingClientFactory); // When var result = build.GetTestRuns(); @@ -42,7 +43,8 @@ public void Should_Return_Empty_List_If_Build_Does_Not_Contain_Test_Runs() fixture.Log, fixture.Settings, fixture.BuildClientFactory, - fixture.TestManagementClientFactory); + fixture.TestManagementClientFactory, + fixture.WorkItemTrackingClientFactory); // When var result = build.GetTestRuns(); @@ -64,7 +66,8 @@ public void Should_Return_List_Of_Test_Runs_With_X_Test_Results_If_X_Is_Less_The fixture.Log, fixture.Settings, fixture.BuildClientFactory, - fixture.TestManagementClientFactory); + fixture.TestManagementClientFactory, + fixture.WorkItemTrackingClientFactory); // When var result = build.GetTestRuns(testRunsCount); @@ -87,7 +90,8 @@ public void Should_Throw_If_Input_Test_Outcomes_Are_Invalid() fixture.Log, fixture.Settings, fixture.BuildClientFactory, - fixture.TestManagementClientFactory); + fixture.TestManagementClientFactory, + fixture.WorkItemTrackingClientFactory); // When var result = Record.Exception(() => build.GetTestRuns(null, new string[] { "FakeOutcome" })); @@ -105,7 +109,8 @@ public void Should_Return_List_Of_Test_Runs_With_Test_Results() fixture.Log, fixture.Settings, fixture.BuildClientFactory, - fixture.TestManagementClientFactory); + fixture.TestManagementClientFactory, + fixture.WorkItemTrackingClientFactory); // When var result = build.GetTestRuns(); @@ -126,5 +131,29 @@ public void Should_Return_List_Of_Test_Runs_With_Test_Results() new AzureDevOpsTestResult { AutomatedTestName = "t3", Outcome = "Passed", ErrorMessage = string.Empty }); } } + + public sealed class TheGetWorkItemsMethod + { + [Fact] + public void Should_Return_List_Of_WorkItems() + { + // Given + var fixture = new BuildFixture(BuildFixture.ValidAzureDevOpsCollectionUrl, "Foo", 42); + var build = new AzureDevOpsBuild( + fixture.Log, + fixture.Settings, + fixture.BuildClientFactory, + fixture.TestManagementClientFactory, + fixture.WorkItemTrackingClientFactory); + + // When + var result = build.GetWorkItems(); + + // Then + result.ShouldNotBeNull(); + result.ShouldHaveSingleItem(); + result.First().WorkItemId.ShouldBe(42); + } + } } } diff --git a/src/Cake.AzureDevOps.Tests/Pipelines/BuildFixture.cs b/src/Cake.AzureDevOps.Tests/Pipelines/BuildFixture.cs index 54f16707..7d5dd8cd 100644 --- a/src/Cake.AzureDevOps.Tests/Pipelines/BuildFixture.cs +++ b/src/Cake.AzureDevOps.Tests/Pipelines/BuildFixture.cs @@ -23,6 +23,8 @@ public BuildFixture(string collectionUrl, string projectName, int buildId) public ITestManagementClientFactory TestManagementClientFactory { get; set; } + public IWorkItemTrackingClientFactory WorkItemTrackingClientFactory { get; set; } + public AzureDevOpsBuildSettings Settings { get; set; } private void InitialzeFakes() @@ -30,6 +32,7 @@ private void InitialzeFakes() this.Log = new FakeLog(); this.BuildClientFactory = new FakeAllSetBuildClientFactory(); this.TestManagementClientFactory = new FakeAllSetTestManagementClientFactory(); + this.WorkItemTrackingClientFactory = new FakeAllSetWorkItemTrackingClientFactory(); } } } diff --git a/src/Cake.AzureDevOps/AzureDevOpsAliases.Pipelines.cs b/src/Cake.AzureDevOps/AzureDevOpsAliases.Pipelines.cs index 20769ac6..01744f53 100644 --- a/src/Cake.AzureDevOps/AzureDevOpsAliases.Pipelines.cs +++ b/src/Cake.AzureDevOps/AzureDevOpsAliases.Pipelines.cs @@ -1,6 +1,7 @@ namespace Cake.AzureDevOps { using System.Collections.Generic; + using Cake.AzureDevOps.Boards.WorkItemTracking; using Cake.AzureDevOps.Pipelines; using Cake.Core; using Cake.Core.Annotations; @@ -47,7 +48,7 @@ public static AzureDevOpsBuild AzureDevOpsBuild( context.NotNull(nameof(context)); settings.NotNull(nameof(settings)); - var build = new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory()); + var build = new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory(), new WorkItemTrackingClientFactory()); if (build.HasBuildLoaded) { @@ -279,7 +280,7 @@ public static bool AzureDevOpsBuildIsFailing( settings.NotNull(nameof(settings)); return - new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory()) + new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory(), new WorkItemTrackingClientFactory()) .IsBuildFailing(); } @@ -327,10 +328,106 @@ public static IEnumerable AzureDevOpsBuildChanges( settings.NotNull(nameof(settings)); return - new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory()) + new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory(), new WorkItemTrackingClientFactory()) .GetChanges(); } + /// + /// Gets the work item ids associated with an Azure Pipelines build. + /// + /// The context. + /// Settings for getting the build. + /// + /// Get work item ids associated with an Azure Pipelines build: + /// + /// + /// + /// + /// The work item ids associated with the build. + /// Returns an empty list if build could not be found and + /// is set to false. + /// If build could not be found and + /// is set to true. + [CakeMethodAlias] + [CakeAliasCategory("Azure Pipelines")] + [CakeNamespaceImport("Cake.AzureDevOps.Pipelines")] + public static IEnumerable AzureDevOpsBuildWorkItemIds( + this ICakeContext context, + AzureDevOpsBuildSettings settings) + { + context.NotNull(nameof(context)); + settings.NotNull(nameof(settings)); + + return + new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory(), new WorkItemTrackingClientFactory()) + .GetWorkItemIds(); + } + + /// + /// Gets the work items associated with an Azure Pipelines build. + /// + /// The context. + /// Settings for getting the build. + /// + /// Get work items associated with an Azure Pipelines build: + /// + /// + /// + /// + /// The work items associated with the build. + /// Returns an empty list if build could not be found and + /// is set to false. + /// If build could not be found and + /// is set to true. + [CakeMethodAlias] + [CakeAliasCategory("Azure Pipelines")] + [CakeNamespaceImport("Cake.AzureDevOps.Pipelines")] + public static IEnumerable AzureDevOpsBuildWorkItems( + this ICakeContext context, + AzureDevOpsBuildSettings settings) + { + context.NotNull(nameof(context)); + settings.NotNull(nameof(settings)); + + return + new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory(), new WorkItemTrackingClientFactory()) + .GetWorkItems(); + } + /// /// Gets the timeline entries for an Azure Pipelines build. /// @@ -375,7 +472,7 @@ public static IEnumerable AzureDevOpsBuildTimelineRec settings.NotNull(nameof(settings)); return - new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory()) + new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory(), new WorkItemTrackingClientFactory()) .GetTimelineRecords(); } @@ -423,7 +520,7 @@ public static IEnumerable AzureDevOpsBuildArtifacts( settings.NotNull(nameof(settings)); return - new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory()) + new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory(), new WorkItemTrackingClientFactory()) .GetArtifacts(); } @@ -471,7 +568,7 @@ public static IEnumerable AzureDevOpsBuildTestRuns( settings.NotNull(nameof(settings)); return - new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory()) + new AzureDevOpsBuild(context.Log, settings, new BuildClientFactory(), new TestManagementClientFactory(), new WorkItemTrackingClientFactory()) .GetTestRuns(); } diff --git a/src/Cake.AzureDevOps/AzureDevOpsAliases.WorkItemTracking.cs b/src/Cake.AzureDevOps/AzureDevOpsAliases.WorkItemTracking.cs index a00367ea..f78528dd 100644 --- a/src/Cake.AzureDevOps/AzureDevOpsAliases.WorkItemTracking.cs +++ b/src/Cake.AzureDevOps/AzureDevOpsAliases.WorkItemTracking.cs @@ -61,7 +61,7 @@ public static AzureDevOpsWorkItem AzureDevOpsWorkItem( /// Make sure the build has the 'Allow Scripts to access OAuth token' option enabled. /// /// The context. - /// ID of the work witem. + /// ID of the work item. /// /// Get an Azure DevOps work item: /// diff --git a/src/Cake.AzureDevOps/Boards/WorkItemTracking/AzureDevOpsWorkItem.cs b/src/Cake.AzureDevOps/Boards/WorkItemTracking/AzureDevOpsWorkItem.cs index 219e061c..fadfff74 100644 --- a/src/Cake.AzureDevOps/Boards/WorkItemTracking/AzureDevOpsWorkItem.cs +++ b/src/Cake.AzureDevOps/Boards/WorkItemTracking/AzureDevOpsWorkItem.cs @@ -2,8 +2,6 @@ { using System; using System.Collections.Generic; - using System.Linq; - using Cake.AzureDevOps.Authentication; using Cake.Core.Diagnostics; using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models; using Microsoft.VisualStudio.Services.Common; @@ -36,7 +34,8 @@ public AzureDevOpsWorkItem(ICakeLog log, AzureDevOpsWorkItemSettings settings) /// The Cake log context. /// Settings for accessing AzureDevOps. /// The work item. - internal AzureDevOpsWorkItem(ICakeLog log, AzureDevOpsWorkItemSettings settings, WorkItem workItem) + /// A factory to communicate with work item tracking client. + internal AzureDevOpsWorkItem(ICakeLog log, AzureDevOpsWorkItemSettings settings, WorkItem workItem, IWorkItemTrackingClientFactory workItemTrackingClientFactory) { log.NotNull(nameof(log)); settings.NotNull(nameof(settings)); @@ -44,7 +43,7 @@ internal AzureDevOpsWorkItem(ICakeLog log, AzureDevOpsWorkItemSettings settings, this.log = log; this.workItem = workItem; - this.workItemTrackingClientFactory = new WorkItemTrackingClientFactory(); + this.workItemTrackingClientFactory = workItemTrackingClientFactory; this.settings = settings; } @@ -140,7 +139,7 @@ internal AzureDevOpsWorkItem( /// /// Gets the URL for accessing the web portal of the Azure DevOps collection. /// - public Uri CollectionUrl => this.settings.CollectionUrl; + public Uri CollectionUrl => this.settings.CollectionUrl; /// /// Gets the ID of the work item. diff --git a/src/Cake.AzureDevOps/Boards/WorkItemTracking/AzureDevOpsWorkItemSettings.cs b/src/Cake.AzureDevOps/Boards/WorkItemTracking/AzureDevOpsWorkItemSettings.cs index dd835a9e..c6860114 100644 --- a/src/Cake.AzureDevOps/Boards/WorkItemTracking/AzureDevOpsWorkItemSettings.cs +++ b/src/Cake.AzureDevOps/Boards/WorkItemTracking/AzureDevOpsWorkItemSettings.cs @@ -2,6 +2,7 @@ { using System; using Cake.AzureDevOps.Authentication; + using Cake.AzureDevOps.Pipelines; /// /// Settings for aliases handling work items. @@ -81,6 +82,16 @@ public AzureDevOpsWorkItemSettings(int workItemId, IAzureDevOpsCredentials crede this.WorkItemId = workItemId; } + /// + /// Initializes a new instance of the class + /// based on the instance of a class. + /// + /// Settings containing the parameters. + public AzureDevOpsWorkItemSettings(BaseAzureDevOpsProjectSettings settings) + : base(settings) + { + } + /// /// Gets the ID of the work item. /// diff --git a/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuild.cs b/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuild.cs index 83979974..a8745ce1 100644 --- a/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuild.cs +++ b/src/Cake.AzureDevOps/Pipelines/AzureDevOpsBuild.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; - using Cake.AzureDevOps.Authentication; + using Cake.AzureDevOps.Boards.WorkItemTracking; using Cake.Core.Diagnostics; using Microsoft.TeamFoundation.Build.WebApi; using Microsoft.TeamFoundation.TestManagement.WebApi; @@ -15,10 +15,11 @@ public sealed class AzureDevOpsBuild { private readonly ICakeLog log; - private readonly IAzureDevOpsCredentials credentials; + private readonly BaseAzureDevOpsProjectSettings settings; private readonly bool throwExceptionIfBuildCouldNotBeFound; private readonly IBuildClientFactory buildClientFactory; private readonly ITestManagementClientFactory testClientFactory; + private readonly IWorkItemTrackingClientFactory workItemTrackingClientFactory; private readonly Build build; /// @@ -29,7 +30,7 @@ public sealed class AzureDevOpsBuild /// If /// is set to true and no build could be found. public AzureDevOpsBuild(ICakeLog log, AzureDevOpsBuildSettings settings) - : this(log, settings, new BuildClientFactory(), new TestManagementClientFactory()) + : this(log, settings, new BuildClientFactory(), new TestManagementClientFactory(), new WorkItemTrackingClientFactory()) { } @@ -49,8 +50,8 @@ internal AzureDevOpsBuild(ICakeLog log, AzureDevOpsBuildsSettings settings, Buil this.build = build; this.buildClientFactory = new BuildClientFactory(); this.testClientFactory = new TestManagementClientFactory(); - this.credentials = settings.Credentials; - this.CollectionUrl = settings.CollectionUrl; + this.workItemTrackingClientFactory = new WorkItemTrackingClientFactory(); + this.settings = settings; } /// @@ -60,24 +61,27 @@ internal AzureDevOpsBuild(ICakeLog log, AzureDevOpsBuildsSettings settings, Buil /// Settings for accessing AzureDevOps. /// A factory to communicate with build client. /// A factory to communicate with test management client. + /// A factory to communicate with work item tracking client. /// If /// is set to true and no build could be found. internal AzureDevOpsBuild( ICakeLog log, AzureDevOpsBuildSettings settings, IBuildClientFactory buildClientFactory, - ITestManagementClientFactory testManagementClientFactory) + ITestManagementClientFactory testManagementClientFactory, + IWorkItemTrackingClientFactory workItemTrackingClientFactory) { log.NotNull(nameof(log)); settings.NotNull(nameof(settings)); buildClientFactory.NotNull(nameof(buildClientFactory)); testManagementClientFactory.NotNull(nameof(testManagementClientFactory)); + workItemTrackingClientFactory.NotNull(nameof(workItemTrackingClientFactory)); this.log = log; this.buildClientFactory = buildClientFactory; this.testClientFactory = testManagementClientFactory; - this.credentials = settings.Credentials; - this.CollectionUrl = settings.CollectionUrl; + this.workItemTrackingClientFactory = workItemTrackingClientFactory; + this.settings = settings; this.throwExceptionIfBuildCouldNotBeFound = settings.ThrowExceptionIfBuildCouldNotBeFound; using (var buildClient = this.buildClientFactory.CreateBuildClient(settings.CollectionUrl, settings.Credentials, out var authorizedIdenity)) @@ -149,7 +153,7 @@ internal AzureDevOpsBuild( /// /// Gets the URL for accessing the web portal of the Azure DevOps collection. /// - public Uri CollectionUrl { get; } + public Uri CollectionUrl => this.settings.CollectionUrl; /// /// Gets the id of the Azure DevOps project. @@ -357,7 +361,7 @@ public IEnumerable GetChanges() return new List(); } - using (var buildClient = this.buildClientFactory.CreateBuildClient(this.CollectionUrl, this.credentials)) + using (var buildClient = this.buildClientFactory.CreateBuildClient(this.CollectionUrl, this.settings.Credentials)) { return buildClient @@ -369,6 +373,72 @@ public IEnumerable GetChanges() } } + /// + /// Gets the work item ids associated with a build. + /// + /// The work item ids associated with a build or an empty list if no build could be found and + /// is set to false. + /// If build could not be found and + /// is set to true. + public IEnumerable GetWorkItemIds() + { + if (!this.ValidateBuild()) + { + return Array.Empty(); + } + + using (var buildClient = this.buildClientFactory.CreateBuildClient(this.CollectionUrl, this.settings.Credentials)) + { + Task> task; + if (this.ProjectId != Guid.Empty) + { + task = buildClient.GetBuildWorkItemsRefsAsync(this.ProjectId, this.BuildId); + } + else if (!string.IsNullOrWhiteSpace(this.ProjectName)) + { + task = buildClient.GetBuildWorkItemsRefsAsync(this.ProjectName, this.BuildId); + } + else + { + throw new InvalidOperationException("Either ProjectId or ProjectName needs to be set"); + } + + return task + .ConfigureAwait(false) + .GetAwaiter() + .GetResult() + .Select(r => int.Parse(r.Id)); + } + } + + /// + /// Gets the work items associated with a build. + /// + /// The work items associated with a build or an empty list if no build could be found and + /// is set to false. + /// If build could not be found and + /// is set to true. + public IEnumerable GetWorkItems() + { + if (!this.ValidateBuild()) + { + return Array.Empty(); + } + + var workItemIds = this.GetWorkItemIds(); + + using (var workItemTrackingClient = this.workItemTrackingClientFactory.CreateWorkItemTrackingClient(this.settings.CollectionUrl, this.settings.Credentials)) + { + return + workItemTrackingClient + .GetWorkItemsAsync(workItemIds, expand: Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models.WorkItemExpand.Relations) + .ConfigureAwait(false) + .GetAwaiter() + .GetResult() + .Select(x => new AzureDevOpsWorkItem(this.log, new AzureDevOpsWorkItemSettings(this.settings), x, this.workItemTrackingClientFactory)); + } + } + /// /// Checks if the build is failing. /// @@ -396,7 +466,7 @@ public IEnumerable GetTimelineRecords() return new List(); } - using (var buildClient = this.buildClientFactory.CreateBuildClient(this.CollectionUrl, this.credentials)) + using (var buildClient = this.buildClientFactory.CreateBuildClient(this.CollectionUrl, this.settings.Credentials)) { return buildClient @@ -423,7 +493,7 @@ public IEnumerable GetArtifacts() return new List(); } - using (var buildClient = this.buildClientFactory.CreateBuildClient(this.CollectionUrl, this.credentials)) + using (var buildClient = this.buildClientFactory.CreateBuildClient(this.CollectionUrl, this.settings.Credentials)) { return buildClient @@ -476,7 +546,7 @@ public AzureDevOpsBuildArtifact LinkArtifact(string name, string type, string lo return null; } - using (var buildClient = this.buildClientFactory.CreateBuildClient(this.CollectionUrl, this.credentials)) + using (var buildClient = this.buildClientFactory.CreateBuildClient(this.CollectionUrl, this.settings.Credentials)) { var artifact = new BuildArtifact @@ -543,7 +613,7 @@ public IEnumerable GetTestRuns(int? maxResultsPerTestRun, IE return new List(); } - using (var testClient = this.testClientFactory.CreateTestManagementClient(this.CollectionUrl, this.credentials)) + using (var testClient = this.testClientFactory.CreateTestManagementClient(this.CollectionUrl, this.settings.Credentials)) { // Read test result details for current build. var testResultDetails =