diff --git a/tools/notification-configuration/notification-creator/Contacts.cs b/tools/notification-configuration/notification-creator/Contacts.cs index 4fe2427bfcb0..9e6404f137a0 100644 --- a/tools/notification-configuration/notification-creator/Contacts.cs +++ b/tools/notification-configuration/notification-creator/Contacts.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Text.RegularExpressions; @@ -12,18 +13,21 @@ namespace Azure.Sdk.Tools.NotificationConfiguration; /// /// This class represents a set of contacts obtained from CODEOWNERS file -/// located in repository attached to given build definition. +/// located in repository attached to given build definition [1]. /// /// The contacts are the CODEOWNERS path owners of path that matches the build definition file path. /// /// To obtain the contacts, construct this class and then call GetFromBuildDefinitionRepoCodeowners(buildDefinition). +/// +/// [1] https://learn.microsoft.com/en-us/rest/api/azure/devops/build/definitions/get?view=azure-devops-rest-7.0#builddefinition /// internal class Contacts { private readonly ILogger log; private readonly GitHubService gitHubService; - // Type 2 maps to a build definition YAML file in the repository + // Type 2 maps to a build definition YAML file in the repository. + // You can confirm it by decompiling Microsoft.TeamFoundation.Build.WebApi.YamlProcess..ctor. private const int BuildDefinitionYamlProcessType = 2; internal Contacts(GitHubService gitHubService, ILogger log) @@ -40,14 +44,15 @@ public async Task> GetFromBuildDefinitionRepoCodeowners(BuildDefini if (buildDefinition.Process.Type != BuildDefinitionYamlProcessType) { this.log.LogDebug( - "buildDefinition.Process.Type '{buildDefinitionProcessType}' " + - "for buildDefinition.Name '{buildDefinitionName}' " + + "buildDefinition.Process.Type: '{buildDefinitionProcessType}' " + + "for buildDefinition.Name: '{buildDefinitionName}' " + "must be '{BuildDefinitionYamlProcessType}'.", buildDefinition.Process.Type, buildDefinition.Name, BuildDefinitionYamlProcessType); return null; } + YamlProcess yamlProcess = (YamlProcess)buildDefinition.Process; Uri repoUrl = GetCodeownersRepoUrl(buildDefinition); @@ -65,23 +70,15 @@ public async Task> GetFromBuildDefinitionRepoCodeowners(BuildDefini return null; } - if (buildDefinition.Process is not YamlProcess process) - { - this.log.LogError( - "buildDefinition.Process as YamlProcess is null. buildDefinition.Name: '{buildDefinitionName}'", - buildDefinition.Name); - return null; - } - - // process.YamlFilename is misleading here. It is actually a file path, not file name. + // yamlProcess.YamlFilename is misleading here. It is actually a file path, not file name. // E.g. it is "sdk/foo_service/ci.yml". - string buildDefinitionFilePath = process.YamlFilename; + string buildDefinitionFilePath = yamlProcess.YamlFilename; this.log.LogInformation( "Searching CODEOWNERS for matching path for '{buildDefinitionFilePath}'", buildDefinitionFilePath); - CodeownersEntry matchingCodeownersEntry = GetMatchingCodeownersEntry(process, codeownersEntries); + CodeownersEntry matchingCodeownersEntry = GetMatchingCodeownersEntry(yamlProcess, codeownersEntries); List contacts = matchingCodeownersEntry.Owners; this.log.LogInformation( @@ -98,7 +95,7 @@ private Uri GetCodeownersRepoUrl(BuildDefinition buildDefinition) Uri repoUrl = buildDefinition.Repository.Url; this.log.LogInformation("Fetching CODEOWNERS file from repoUrl: '{repoUrl}'", repoUrl); - if (String.IsNullOrEmpty(repoUrl)) + if (!string.IsNullOrEmpty(repoUrl?.ToString())) { repoUrl = new Uri(Regex.Replace(repoUrl.ToString(), @"\.git$", String.Empty)); }