internal Project([NotNull] TeamProjectReference project, [NotNull] WorkItemStore store) : base( project.Id, project.Name, new Uri(project.Url), new Lazy <IWorkItemTypeCollection>( () => { var wits = store.NativeWorkItemStore .Value .GetWorkItemTypesAsync(project.Name) .GetAwaiter() .GetResult(); var wits2 = new List <IWorkItemType>(wits.Count); for (var i = 0; i < wits.Count; i++) { var wit = wits[i]; wits2.Add(new WorkItemType(wit)); } return(new WorkItemTypeCollection(wits2)); }), new Lazy <IWorkItemClassificationNodeCollection <int> >(() => WorkItemClassificationNodeCollectionBuilder.BuildAsync(store.NativeWorkItemStore.Value.GetClassificationNodeAsync(project.Name, TreeStructureGroup.Areas, null, int.MaxValue)).GetAwaiter().GetResult()), new Lazy <IWorkItemClassificationNodeCollection <int> >(() => WorkItemClassificationNodeCollectionBuilder.BuildAsync(store.NativeWorkItemStore.Value.GetClassificationNodeAsync(project.Name, TreeStructureGroup.Iterations, null, int.MaxValue)).GetAwaiter().GetResult()) ) { }
public void ProjectsAndTeams_Projects_ChangeTeamProjectDescription_Success() { // arrange TeamProjects projects = new TeamProjects(_configuration); string name = System.Guid.NewGuid().ToString().ToLower().Substring(0, 30); // act //create project OperationReference createResult = projects.CreateTeamProject(name); //TODO: Instead of sleep, monitor the status ("online") System.Threading.Thread.Sleep(5000); //get the project we just created so we can get the id TeamProjectReference getResult = projects.GetTeamProjectWithCapabilities(name); //change project desription OperationReference updateResult = projects.ChangeTeamProjectDescription(getResult.Id, "This is my new project description"); //TODO: keep checking the operation untill it failed or is done // assert Assert.AreNotEqual(createResult.Status, OperationStatus.Failed); Assert.AreNotEqual(updateResult.Status, OperationStatus.Failed); }
public void ProjectsAndTeams_Projects_RenameTeamProject_Success() { // arrange TeamProjects projects = new TeamProjects(_configuration); string name = System.Guid.NewGuid().ToString().ToLower().Substring(0, 30); // act //create the project OperationReference createResult = projects.CreateTeamProject(name); //TODO: Instead of sleep, monitor the status ("online") System.Threading.Thread.Sleep(5000); //get the project so we can get the id TeamProjectReference getResult = projects.GetTeamProjectWithCapabilities(name); //rename the project OperationReference renameResult = projects.RenameTeamProject(getResult.Id, "Vandelay Scrum Project"); //TODO: keep checking the operation untill it failed or is done // assert Assert.AreNotEqual(createResult.Status, OperationStatus.Failed); Assert.AreNotEqual(renameResult.Status, OperationStatus.Failed); }
private IEnumerable <Resource> ToProjectNodes( TreeStructureGroup treeStructureGroup, TeamProjectReference teamProject) { var rootAreaNode = GetNode(treeStructureGroup, teamProject); return(GetStructureResources("", rootAreaNode)); }
public static bool FindDefaultProject(AzureDevOpsClientContext context, out TeamProjectReference project) { // Check if we already have a default project loaded if (!context.TryGetValue("$defautProject", out project)) { var connection = context.Connection; var projectClient = connection.GetClient <ProjectHttpClient>(); // Check if an ID was already set (this could have been provided by the caller) if (!context.TryGetValue("projectId", out Guid projectId)) { context.TryGetValue("projectName", out string projectName); var projects = projectClient.GetProjects(null, top: 10).Result; project = projects.OrderBy(c => c.Name == projectName ? 0 : 1).FirstOrDefault(); } else { // Get the details for this project project = projectClient.GetProject(projectId.ToString()).Result; } } if (project != null) { context.SetValue("$defautProject", project); } else { // create a project here? throw new Exception("No projects available for running the sample."); } return(project != null); }
private void LinkWorkItems(TeamProjectReference project, GitRepository repo, GitRef newBranch, string branchName, List <WorkItem> relatedWorkitems) { var patchDocument = new JsonPatchDocument(); var gitUri = $"vstfs:///Git/Ref/{project.Id}%2F{repo.Id}%2FGBdev%2F{branchName}"; patchDocument.Add( new JsonPatchOperation() { Operation = Operation.Add, Path = "/relations/-", Value = new { rel = "ArtifactLink", url = gitUri, attributes = new { name = "Branch" } } } ); foreach (var workItem in relatedWorkitems) { if (!workItem.Relations.Any(c => c.Rel == "ArtifactLink" && c.Url == gitUri)) { workItemTrackingClient.UpdateWorkItemAsync(patchDocument, (int)workItem.Id).Wait(); } } }
/// <summary> /// Gets the most likely project. /// </summary> /// <param name="projectHint">The project hint.</param> /// <returns></returns> /// <exception cref="System.InvalidOperationException">Could not locate a most likely project</exception> public MostLikelyProjectInfo GetMostLikelyProject(string projectHint) { TeamProjectReference locatedProjectReference = null; foreach (var project in KnownProjectReferences) { if (project.Value.Name.Equals(projectHint, StringComparison.OrdinalIgnoreCase) || project.Value.Description?.IndexOf(projectHint, StringComparison.OrdinalIgnoreCase) >= 0) { locatedProjectReference = project.Value; break; } } if (locatedProjectReference == null) { throw new InvalidOperationException("Could not locate a most likely project"); } var collectionName = KnownProjectToCollectionMap[locatedProjectReference.Name]; var locatedCollectionReference = KnownProjectCollectionReferences[collectionName]; return(new MostLikelyProjectInfo { TeamProjectCollectionRef = locatedCollectionReference, TeamProjectRef = locatedProjectReference }); }
public ServiceEndpoint CreateGenericEndpoint() { TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); // Get a service endpoint client instance VssConnection connection = Context.Connection; ServiceEndpointHttpClient endpointClient = connection.GetClient <ServiceEndpointHttpClient>(); // Create a generic service endpoint ServiceEndpoint endpoint = endpointClient.CreateServiceEndpointAsync(project.Id, new ServiceEndpoint() { Name = "MyNewServiceEndpoint", Type = ServiceEndpointTypes.Generic, Url = new Uri("https://myserver"), Authorization = new EndpointAuthorization() { Scheme = EndpointAuthorizationSchemes.UsernamePassword, Parameters = new Dictionary <string, string>() { { "username", "myusername" }, { "password", "mysecretpassword" } } } }).Result; Context.Log("Created endpoint: {0} {1} in {2}", endpoint.Id, endpoint.Name, project.Name); // Save new endpoint so it can be deleted later Context.SetValue <Guid>("$newServiceEndpointId", endpoint.Id); Context.SetValue <Guid>("$newServiceEndpointProjectId", project.Id); return(endpoint); }
public List <GitPullRequestStatus> GetPullRequestIterationStatuses() { VssConnection connection = this.Context.Connection; GitHttpClient gitClient = connection.GetClient <GitHttpClient>(); TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); GitRepository repo = GitSampleHelpers.FindAnyRepository(this.Context, project.Id); GitPullRequest pullRequest = GitSampleHelpers.CreatePullRequest(this.Context, repo); GitSampleHelpers.CreatePullRequestStatus(this.Context, repo.Id, pullRequest.PullRequestId, 1); GitSampleHelpers.CreatePullRequestStatus(this.Context, repo.Id, pullRequest.PullRequestId, 1); Console.WriteLine($"project {project.Name}, repo {repo.Name}, pullRequestId {pullRequest.PullRequestId}"); List <GitPullRequestStatus> iterationStatuses = gitClient.GetPullRequestIterationStatusesAsync(repo.Id, pullRequest.PullRequestId, 1).Result; Console.WriteLine($"{iterationStatuses.Count} statuses found for pull request {pullRequest.PullRequestId} iteration {1}"); foreach (var status in iterationStatuses) { Console.WriteLine($"{status.Description}({status.Context.Genre}/{status.Context.Name}) with id {status.Id}"); } GitSampleHelpers.AbandonPullRequest(this.Context, repo, pullRequest.PullRequestId); return(iterationStatuses); }
public bool DeleteTeam() { // Use the previously created team (from the sample above) WebApiTeamRef team; TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); if (!this.Context.TryGetValue <WebApiTeamRef>("$newTeam", out team) || !this.Context.TryGetValue <TeamProjectReference>("$projectOfNewTeam", out project)) { throw new Exception("Run the create team sample above first."); } // Get a client VssConnection connection = Context.Connection; TeamHttpClient teamClient = connection.GetClient <TeamHttpClient>(); try { teamClient.DeleteTeamAsync(project.Id.ToString(), team.Id.ToString()).SyncResult(); Console.WriteLine("'{0}' team deleted from project {1}", team.Name, project.Name); return(true); } catch (Exception ex) { Console.WriteLine("Unable to delete team: " + ex); return(false); } }
/// <summary> /// Performs execution of the command /// </summary> protected override GitRepository DoNewItem() { var(_, tp) = GetCollectionAndProject(); var repo = GetParameter <string>(nameof(NewGitRepository.Repository)); if (!ShouldProcess(tp, $"Create Git repository '{repo}'")) { return(null); } var client = GetClient <GitHttpClient>(); var tpRef = new TeamProjectReference() { Id = tp.Id, Name = tp.Name }; var repoToCreate = new GitRepository() { Name = repo, ProjectReference = tpRef }; return(client.CreateRepositoryAsync(repoToCreate, tp.Name) .GetResult("Error creating Git repository")); }
/// <inheritdoc /> public Subscription GetSubscription(Guid subscriptionId, TeamProjectReference teamProject) { subscriptionId.ThrowIfEmpty(nameof(subscriptionId)); teamProject.ThrowIfNull(nameof(teamProject)); var url = HttpContext.Current != null ? FormattableString.Invariant($"{HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority)}/api/event") : string.Empty; return(new Subscription { ConsumerActionId = "httpRequest", ConsumerId = "webHooks", ConsumerInputs = new Dictionary <string, string> { { "url", url }, { "httpHeaders", FormattableString.Invariant($"subscriptionToken:{subscriptionId}") } }, EventType = "ms.vss-release.deployment-approval-pending-event", PublisherId = "rm", PublisherInputs = new Dictionary <string, string> { { "projectId", teamProject.Id.ToString() } }, ResourceVersion = "3.0-preview.1" }); }
public IEnumerable <GitPush> ListPushesIntoDefault() { VssConnection connection = this.Context.Connection; GitHttpClient gitClient = connection.GetClient <GitHttpClient>(); TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); GitRepository repo = GitSampleHelpers.FindAnyRepository(this.Context, project.Id); string branchName = repo.DefaultBranch; List <GitPush> pushes = gitClient.GetPushesAsync( repo.Id, searchCriteria: new GitPushSearchCriteria() { IncludeRefUpdates = true, RefName = branchName, }).Result; Console.WriteLine("project {0}, repo {1}", project.Name, repo.Name); foreach (GitPush push in pushes) { Console.WriteLine("push {0} by {1} on {2}", push.PushId, push.PushedBy.DisplayName, push.Date); } return(pushes); }
public IEnumerable <GitPush> ListPushesInLast10Days() { VssConnection connection = this.Context.Connection; GitHttpClient gitClient = connection.GetClient <GitHttpClient>(); TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); GitRepository repo = GitSampleHelpers.FindAnyRepository(this.Context, project.Id); List <GitPush> pushes = gitClient.GetPushesAsync( repo.Id, searchCriteria: new GitPushSearchCriteria() { FromDate = DateTime.UtcNow - TimeSpan.FromDays(10), ToDate = DateTime.UtcNow, }).Result; Console.WriteLine("project {0}, repo {1}", project.Name, repo.Name); foreach (GitPush push in pushes) { Console.WriteLine("push {0} by {1} on {2}", push.PushId, push.PushedBy.DisplayName, push.Date); } return(pushes); }
private void IngestPullRequests(List <GitPullRequest> pullRequests, TeamProjectReference project) { List <VssPullRequestEntity> entities = new List <VssPullRequestEntity>(); foreach (GitPullRequest pullRequest in pullRequests) { VssPullRequestEntity entity = new VssPullRequestEntity { AuthorEmail = pullRequest.CreatedBy.UniqueName, ClosedDate = pullRequest.ClosedDate, CreationDate = pullRequest.CreationDate, PullRequestId = pullRequest.PullRequestId, LastMergeCommitID = pullRequest.LastMergeCommit?.CommitId, LastMergeTargetCommitId = pullRequest.LastMergeTargetCommit?.CommitId, SourceBranch = pullRequest.SourceRefName, Status = pullRequest.Status.ToString(), TargetBranch = pullRequest.TargetRefName, Title = pullRequest.Title, ProjectId = pullRequest.Repository.ProjectReference.Id, RepositoryId = pullRequest.Repository.Id, Organization = this.vssClient.OrganizationName, RowUpdatedDate = Helper.UtcNow, ProjectName = project.Name, }; entities.Add(entity); } using VssDbContext context = new VssDbContext(logger, this.sqlConnectionString); context.BulkInsertOrUpdate(entities); }
public IEnumerable <GitPullRequest> ListPullRequestsIntoMaster() { VssConnection connection = this.Context.Connection; GitHttpClient gitClient = connection.GetClient <GitHttpClient>(); TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); GitRepository repo = GitSampleHelpers.FindAnyRepository(this.Context, project.Id); List <GitPullRequest> prs = gitClient.GetPullRequestsAsync( repo.Id, new GitPullRequestSearchCriteria() { TargetRefName = "refs/heads/master", }).Result; Console.WriteLine("project {0}, repo {1}", project.Name, repo.Name); foreach (GitPullRequest pr in prs) { Console.WriteLine("{0} #{1} {2} -> {3}", pr.Title.Substring(0, Math.Min(40, pr.Title.Length)), pr.PullRequestId, pr.SourceRefName, pr.TargetRefName); } return(prs); }
public WebApiTeam RenameTeam() { // Use the previously created team (from the sample above) WebApiTeamRef team; TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); if (!this.Context.TryGetValue <WebApiTeamRef>("$newTeam", out team) || !this.Context.TryGetValue <TeamProjectReference>("$projectOfNewTeam", out project)) { throw new Exception("Run the create team sample above first."); } //Get a client VssConnection connection = Context.Connection; TeamHttpClient teamClient = connection.GetClient <TeamHttpClient>(); WebApiTeam teamUpdateParameters = new WebApiTeam() { Name = team.Name + " (renamed)" }; WebApiTeam updatedTeam = teamClient.UpdateTeamAsync(teamUpdateParameters, project.Id.ToString(), team.Id.ToString()).Result; Console.WriteLine("Team renamed from '{0}' to '{1}'", team.Name, updatedTeam.Name); return(updatedTeam); }
public PropertiesCollection GetPullRequestProperties() { VssConnection connection = Context.Connection; GitHttpClient gitClient = connection.GetClient <GitHttpClient>(); TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); GitRepository repo = GitSampleHelpers.FindAnyRepository(this.Context, project.Id); GitPullRequest pullRequest = GitSampleHelpers.CreatePullRequest(this.Context, repo); using (new ClientSampleHttpLoggerOutputSuppression()) { JsonPatchDocument patch = new JsonPatchDocument(); patch.Add(new JsonPatchOperation() { Operation = Operation.Add, Path = "/sampleId", Value = 8 }); patch.Add(new JsonPatchOperation() { Operation = Operation.Add, Path = "/startedDateTime", Value = DateTime.UtcNow }); gitClient.UpdatePullRequestPropertiesAsync(patch, repo.Id, pullRequest.PullRequestId).SyncResult(); } Console.WriteLine("project {0}, repo {1}, pullRequestId {2}", project.Name, repo.Name, pullRequest.PullRequestId); PropertiesCollection properties = gitClient.GetPullRequestPropertiesAsync(repo.Id, pullRequest.PullRequestId).SyncResult(); Console.WriteLine($"Pull request {pullRequest.PullRequestId} has {properties.Count} properties"); GitSampleHelpers.AbandonPullRequest(this.Context, repo, pullRequest.PullRequestId); return(properties); }
private static IObservable <List <Build> > GetBuilds(string branch, BuildHttpClient buildHttpClient, TeamProjectReference project, int definitionId, Version latestXAFMinor, int?top = null) { return(buildHttpClient .GetBuildsAsync(project.Id, new[] { definitionId }, tagFilters: new[] { $"{latestXAFMinor}" }, branchName: $"refs/heads/{branch}", top: top, statusFilter: BuildStatus.Completed) .ToObservable()); }
public void UpdatePullRequestIterationStatuses() { VssConnection connection = this.Context.Connection; GitHttpClient gitClient = connection.GetClient <GitHttpClient>(); TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); GitRepository repo = GitSampleHelpers.FindAnyRepository(this.Context, project.Id); GitPullRequest pullRequest = GitSampleHelpers.CreatePullRequest(this.Context, repo); GitPullRequestStatus status1 = GitSampleHelpers.CreatePullRequestStatus(this.Context, repo.Id, pullRequest.PullRequestId, 1); GitPullRequestStatus status2 = GitSampleHelpers.CreatePullRequestStatus(this.Context, repo.Id, pullRequest.PullRequestId, 1); Console.WriteLine($"project {project.Name}, repo {repo.Name}, pullRequestId {pullRequest.PullRequestId}"); var patch = new JsonPatchDocument(); patch.Add(new JsonPatchOperation() { Operation = VisualStudio.Services.WebApi.Patch.Operation.Remove, Path = $"/{status1.Id}" }); patch.Add(new JsonPatchOperation() { Operation = VisualStudio.Services.WebApi.Patch.Operation.Remove, Path = $"/{status2.Id}" }); gitClient.UpdatePullRequestIterationStatusesAsync(patch, repo.Id, pullRequest.PullRequestId, 1).SyncResult(); Console.WriteLine($"Statuses {status1.Id}, and {status2.Id} deleted from the pull request {pullRequest.PullRequestId}, iteration {1}"); GitSampleHelpers.AbandonPullRequest(this.Context, repo, pullRequest.PullRequestId); }
public WorkItem CreateWorkItem(string title, string type) { // Construct the object containing field values required for the new work item JsonPatchDocument patchDocument = new JsonPatchDocument(); patchDocument.Add( new JsonPatchOperation() { Operation = Operation.Add, Path = "/fields/System.Title", Value = title } ); // Get a client VssConnection connection = Context.Connection; WorkItemTrackingHttpClient workItemTrackingClient = connection.GetClient <WorkItemTrackingHttpClient>(); // Get the project to create the sample work item in TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); // Create the new work item WorkItem newWorkItem = workItemTrackingClient.CreateWorkItemAsync(patchDocument, project.Id, type).Result; Console.WriteLine("Created work item ID {0} {1}", newWorkItem.Id, newWorkItem.Fields["System.Title"]); return(newWorkItem); }
public WebApiTeam CreateTeam() { // Find a project to create the team in TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); string teamName = "Sample team " + Guid.NewGuid(); string teamDescription = "Short description of my new team"; // Get a client VssConnection connection = Context.Connection; TeamHttpClient teamClient = connection.GetClient <TeamHttpClient>(); // Construct team parameters object WebApiTeam newTeamCreateParameters = new WebApiTeam() { Name = teamName, Description = teamDescription }; WebApiTeam newTeam = teamClient.CreateTeamAsync(newTeamCreateParameters, project.Id.ToString()).Result; Console.WriteLine("Team created: '{0}' (ID: {1})", newTeam.Name, newTeam.Id); // Save the team for use later in the rename/delete samples this.Context.SetValue <WebApiTeamRef>("$newTeam", newTeam); this.Context.SetValue <TeamProjectReference>("$projectOfNewTeam", project); return(newTeam); }
private TeamContext getTeamContext() { TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); WebApiTeamRef team = ClientSampleHelpers.FindAnyTeam(this.Context, project.Id); TeamContext teamContext = new TeamContext(project.Name, team.Name); return(teamContext); }
public static string ToBotString(this TeamProjectReference obj) { if (obj == null) { return("Информация о проекте не найдена."); } return(string.Format("Вы находитесь в проекте <b>{0}</b>.<br />{1}", obj.Name, obj.Description)); }
public WorkItem GetTemplate() { VssConnection connection = Context.Connection; WorkItemTrackingHttpClient client = connection.GetClient <WorkItemTrackingHttpClient>(); TeamProjectReference project = ClientSampleHelpers.FindAnyProject(this.Context); WorkItem result = client.GetWorkItemTemplateAsync(project.Name, "Feature").Result; return(result); }
public TeamProjectReference GetProject(string name) { // create project object using (ProjectHttpClient projectHttpClient = new ProjectHttpClient(_uri, _credentials)) { TeamProjectReference project = projectHttpClient.GetProject(name).Result; return(project); } }
private static TeamProject GetProject(VssConnection connection, string projectName) { ProjectHttpClient projectClient = connection.GetClient <ProjectHttpClient>(); IEnumerable <TeamProjectReference> projects = projectClient.GetProjects(top: 10000).Result; TeamProjectReference project = projects.FirstOrDefault(p => p.Name.Equals(projectName, StringComparison.OrdinalIgnoreCase)); return(projectClient.GetProject(project.Id.ToString(), true).Result); }
/// <summary> /// Determines whether the repository is allowed to be touched. /// </summary> /// <param name="project">Team project</param> /// <returns>boolean</returns> public bool IsProjectAllowed(TeamProjectReference project) { if (this.ApplyTo == null || this.ApplyTo.Projects == null || this.ApplyTo.Projects.Count == 0) { return(true); } return(this.ApplyTo.Projects.Any(x => x == project.Name || (Guid.TryParse(x, out var guid) && guid == project.Id))); }
static void Main(string[] args) { VssConnection connection = GetVssConnection(); ProjectHttpClient projectClient = connection.GetClient <ProjectHttpClient>(); // Call to get the list of projects //IEnumerable<TeamProjectReference> projects = projectClient.GetProjects().Result; TeamProjectReference project = projectClient.GetProject("MITHRA").Result; GitHttpClient gitClient = connection.GetClient <GitHttpClient>(); WorkItemTrackingHttpClient witClient = connection.GetClient <WorkItemTrackingHttpClient>(); var repos = gitClient.GetRepositoriesAsync(project.Id, includeLinks: true).Result; var pullRequestSearchCriteria = new GitPullRequestSearchCriteria { Status = PullRequestStatus.Completed, IncludeLinks = true, }; List <GitPullRequest> allPullRequests = new List <GitPullRequest>(); int skip = 0; int threshold = 1000; foreach (var repo in repos) { Console.WriteLine($"{repo.Name} (DefaultBranch: {repo.DefaultBranch})"); IList <GitPullRequest> prs = gitClient.GetPullRequestsAsync(repo.Id, pullRequestSearchCriteria, skip: skip, top: threshold ).Result; foreach (GitPullRequest pr in prs.Where(x => x.Repository.Id == repo.Id)) { Console.WriteLine("\t{0} #{1} {2} -> {3} ({4})", pr.Title.Substring(0, Math.Min(40, pr.Title.Length)), pr.PullRequestId, pr.SourceRefName, pr.TargetRefName, pr.CreatedBy.DisplayName); //var prcommits = gitClient.GetPullRequestCommitsAsync(repo.Id, pr.PullRequestId).Result; var tags = gitClient.GetTagRefsAsync(repo.Id).Result; var prlinks = gitClient.GetPullRequestWorkItemRefsAsync(project.Id, repo.Id, pr.PullRequestId).Result; if (prlinks != null) { var wis = prlinks.ToList(); foreach (var wi in wis) { var workitem = witClient.GetWorkItemAsync(int.Parse(wi.Id)).Result; Console.WriteLine($"\t\t{wi.Id} - {workitem.Fields["System.Title"]}"); } } else { Console.WriteLine("\t\tNo links found"); } } } }
public TfProject(TeamProjectReference projectReference, ITfsConnection tfsConnection, ILogger logger) { _projectReference = projectReference; _tfsConnection = tfsConnection; _logger = logger; Approved = new ConcurrentDictionary <int, IPullRequest>(); Unapproved = new ConcurrentDictionary <int, IPullRequest>(); _repositories = new List <ITfGitRepository>(); }