Skip to content
Draft
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ private async Task EnsureTeamExists(


var result = teams.FirstOrDefault(team => team.Name == teamName);
bool teamCreatedOrUpdated = false;

if (result == default)
{
Expand All @@ -85,6 +86,7 @@ private async Task EnsureTeamExists(
{
result = await service.CreateTeamForProjectAsync(pipeline.Project.Id.ToString(), newTeam);
}
teamCreatedOrUpdated = true;
}
else
{
Expand All @@ -96,11 +98,15 @@ private async Task EnsureTeamExists(
{
result = await service.UpdateTeamForProjectAsync(pipeline.Project.Id.ToString(), result);
}
teamCreatedOrUpdated = true;
}
}
if (result != default)
{
await EnsureScheduledBuildFailSubscriptionExists(pipeline, result, persistChanges);
if (teamCreatedOrUpdated)
{
await EnsureScheduledBuildFailSubscriptionExists(pipeline, result, persistChanges);
}
await SyncTeamWithCodeownersFile(pipeline, result, gitHubToAADConverter, persistChanges);
}
}
Expand All @@ -121,33 +127,17 @@ private async Task SyncTeamWithCodeownersFile(
return;
}

// Get set of team members in the CODEOWNERS file
var contactsDescriptors = new List<string>();
foreach (string contact in contacts)
{
if (!contactsCache.ContainsKey(contact))
{
// TODO: Better to have retry if no success on this call.
var userPrincipal = await gitHubToAADConverter.GetUserPrincipalNameFromGithubAsync(contact);
if (!string.IsNullOrEmpty(userPrincipal))
{
contactsCache[contact] = await service.GetDescriptorForPrincipal(userPrincipal);
}
else
{
logger.LogInformation(
"Cannot find the user principal for GitHub contact '{contact}'",
contact);
contactsCache[contact] = null;
}
}
contactsDescriptors.Add(contactsCache[contact]);
}
var distinctContacts = contacts
.Where(contact => !string.IsNullOrEmpty(contact))
.Distinct()
.ToList();

var contactsDescriptors = await ResolveContactDescriptorsAsync(distinctContacts, gitHubToAADConverter);

var contactsSet = new HashSet<string>(contactsDescriptors);
// Get set of team members in the DevOps teams
var contactsSet = new HashSet<string>(contactsDescriptors.Where(d => d != null));

var teamMembers = await service.GetMembersAsync(team);
var teamDescriptors = new List<String>();
var teamDescriptors = new List<string>();
foreach (var member in teamMembers)
{
if (!teamMemberCache.ContainsKey(member.Identity.Id))
Expand All @@ -157,34 +147,92 @@ private async Task SyncTeamWithCodeownersFile(
}
teamDescriptors.Add(teamMemberCache[member.Identity.Id]);
}
var teamSet = new HashSet<string>(teamDescriptors);
var contactsToRemove = teamSet.Except(contactsSet);
var contactsToAdd = contactsSet.Except(teamSet);
var teamSet = new HashSet<string>(teamDescriptors.Where(d => d != null));

if (contactsSet.SetEquals(teamSet))
{
logger.LogInformation("Team membership is already synchronized. No changes needed.");
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
logger.LogInformation("Team membership is already synchronized. No changes needed.");

return;
}

var contactsToRemove = teamSet.Except(contactsSet).ToList();
var contactsToAdd = contactsSet.Except(teamSet).ToList();

string teamDescriptor = "";

if (contactsToRemove.Any() || contactsToAdd.Any())
{
teamDescriptor = await service.GetDescriptorAsync(team.Id);
}

if (contactsToRemove.Any())
{
logger.LogInformation("Removing {count} contact(s) from team", contactsToRemove.Count);
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (contactsToRemove.Any())
{
logger.LogInformation("Removing {count} contact(s) from team", contactsToRemove.Count);
}

Copy link
Member

Choose a reason for hiding this comment

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

@copilot remove this extra logging you added similarly for the add code path

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the aggregate logging for both remove and add operations, and the team sync status message. Changes in 9f9b142.


foreach (string descriptor in contactsToRemove)
{
if (persistChanges)
{
logger.LogInformation("Delete Contact TeamDescriptor = {0}, ContactDescriptor = {1}", teamDescriptor, descriptor);
await service.RemoveMember(teamDescriptor, descriptor);
}
else
{
logger.LogInformation("Would delete Contact TeamDescriptor = {0}, ContactDescriptor = {1}", teamDescriptor, descriptor);
}
Comment on lines +172 to +175
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
else
{
logger.LogInformation("Would delete Contact TeamDescriptor = {0}, ContactDescriptor = {1}", teamDescriptor, descriptor);
}

}

foreach (string descriptor in contactsToRemove)
{
if (persistChanges && descriptor != null)
if (contactsToAdd.Any())
{
logger.LogInformation("Delete Contact TeamDescriptor = {0}, ContactDescriptor = {1}", teamDescriptor, descriptor);
await service.RemoveMember(teamDescriptor, descriptor);
logger.LogInformation("Adding {count} contact(s) to team", contactsToAdd.Count);
}

foreach (string descriptor in contactsToAdd)
{
if (persistChanges)
{
logger.LogInformation("Add Contact TeamDescriptor = {0}, ContactDescriptor = {1}", teamDescriptor, descriptor);
await service.AddToTeamAsync(teamDescriptor, descriptor);
}
else
{
logger.LogInformation("Would add Contact TeamDescriptor = {0}, ContactDescriptor = {1}", teamDescriptor, descriptor);
}
}
}
}
}

foreach (string descriptor in contactsToAdd)
/// <summary>
/// Resolves contact GitHub handles to descriptors with caching
/// </summary>
private async Task<List<string>> ResolveContactDescriptorsAsync(
List<string> contacts,
GitHubToAADConverter gitHubToAADConverter)
{
var contactsDescriptors = new List<string>();

foreach (string contact in contacts)
{
if (!contactsCache.ContainsKey(contact))
{
if (persistChanges && descriptor != null)
var userPrincipal = await gitHubToAADConverter.GetUserPrincipalNameFromGithubAsync(contact);
if (!string.IsNullOrEmpty(userPrincipal))
{
contactsCache[contact] = await service.GetDescriptorForPrincipal(userPrincipal);
}
else
{
logger.LogInformation("Add Contact TeamDescriptor = {0}, ContactDescriptor = {1}", teamDescriptor, descriptor);
await service.AddToTeamAsync(teamDescriptor, descriptor);
logger.LogInformation(
"Cannot find the user principal for GitHub contact '{contact}'",
contact);
// Cache null results to avoid re-requesting
contactsCache[contact] = null;
}
}
contactsDescriptors.Add(contactsCache[contact]);
}

return contactsDescriptors;
}

private async Task<IEnumerable<BuildDefinition>> GetPipelinesAsync(string projectName, string projectPath, PipelineSelectionStrategy strategy)
Expand Down Expand Up @@ -242,6 +290,7 @@ private async Task EnsureScheduledBuildFailSubscriptionExists(BuildDefinition pi
};

logger.LogInformation("Creating Subscription PipelineId = {0}, TeamId = {1}", pipeline.Id, team.Id);

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change

if (persistChanges)
{
subscription = await service.CreateSubscriptionAsync(newSubscription);
Expand Down