From 7724333188b705bd03541c5176244a5ba1ffc79b Mon Sep 17 00:00:00 2001 From: Sima Zhu <48036328+sima-zhu@users.noreply.github.com> Date: Thu, 18 Nov 2021 16:59:55 -0800 Subject: [PATCH] Add command option for output the codeowners directly. (#2245) --- .../stages/archetype-sdk-tool-dotnet.yml | 8 +++- .../CODEOWNERS | 30 +++++++++++++++ .../Program.cs | 38 +++++++++++-------- .../CodeOwnersParser/CodeOwnersFile.cs | 8 +--- .../CodeOwnersParser/FileHelpers.cs | 2 +- tools/code-owners-parser/ci.yml | 7 ++++ 6 files changed, 68 insertions(+), 25 deletions(-) create mode 100644 tools/code-owners-parser/Azure.Sdk.Tools.RetrieveCodeOwners.Tests/CODEOWNERS diff --git a/eng/pipelines/templates/stages/archetype-sdk-tool-dotnet.yml b/eng/pipelines/templates/stages/archetype-sdk-tool-dotnet.yml index 1e36ddaa26a..87a7641a5f7 100644 --- a/eng/pipelines/templates/stages/archetype-sdk-tool-dotnet.yml +++ b/eng/pipelines/templates/stages/archetype-sdk-tool-dotnet.yml @@ -18,7 +18,9 @@ parameters: - name: NoWarn type: boolean default: false - + - name: TestPostSteps + type: object + default: [] variables: - template: ../variables/globals.yml - name: Warn @@ -73,7 +75,9 @@ stages: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 DOTNET_MULTILEVEL_LOOKUP: 0 - + + - ${{ parameters.TestPostSteps }} + - task: PublishTestResults@2 condition: succeededOrFailed() inputs: diff --git a/tools/code-owners-parser/Azure.Sdk.Tools.RetrieveCodeOwners.Tests/CODEOWNERS b/tools/code-owners-parser/Azure.Sdk.Tools.RetrieveCodeOwners.Tests/CODEOWNERS new file mode 100644 index 00000000000..8c5af6a868f --- /dev/null +++ b/tools/code-owners-parser/Azure.Sdk.Tools.RetrieveCodeOwners.Tests/CODEOWNERS @@ -0,0 +1,30 @@ +# Instructions for CODEOWNERS file format and automatic build failure notifications: +# https://github.com/Azure/azure-sdk/blob/main/docs/policies/opensource.md#codeowners + +########### +# SDK +########### + +# Catch-all for SDK changes +/sdk/ @person1 @person2 + +# Service teams +/sdk/azconfig/ @person3 @person4 + +# Example for a service that needs issues to be labeled +# ServiceLabel: %KeyVault %Service Attention +/sdk/keyvault/ @person5 @person6 + +# Example for a service that needs PRs to be labeled +# PRLabel: %label +/sdk/servicebus/ @person7 @person8 + +# Example for a service that needs both issues and PRs to be labeled +# ServiceLabel: %label +# PRLabel: %label +/sdk/eventhubs/ @person7 @person8 + +# Example for service that does not have the code in the repo but wants issues to be labeled +# Notice the use of the moniker // +# ServiceLabel: %label %Service Attention +// @person7 @person8 \ No newline at end of file diff --git a/tools/code-owners-parser/Azure.Sdk.Tools.RetrieveCodeOwners/Program.cs b/tools/code-owners-parser/Azure.Sdk.Tools.RetrieveCodeOwners/Program.cs index ab0730fd8a7..d45ec5947f7 100644 --- a/tools/code-owners-parser/Azure.Sdk.Tools.RetrieveCodeOwners/Program.cs +++ b/tools/code-owners-parser/Azure.Sdk.Tools.RetrieveCodeOwners/Program.cs @@ -1,5 +1,5 @@ using System; -using System.IO; +using System.Text.Json; using Azure.Sdk.Tools.CodeOwnersParser; namespace Azure.Sdk.Tools.RetrieveCodeOwners @@ -9,27 +9,33 @@ class Program /// /// Retrieves codeowners information for specific section of the repo /// + /// The path of CODEOWNERS file in repo /// The directory whose information is to be retrieved - /// The root of the repo or $(Build.SourcesDirectory) on DevOps - /// Variable for setting user aliases - /// + /// Exit code - public static void Main( - string targetDirectory, - string rootDirectory, - string vsoOwningUsers + public static int Main( + string codeOwnerFilePath, + string targetDirectory ) { var target = targetDirectory.ToLower().Trim(); - var codeOwnersLocation = Path.Join(rootDirectory, ".github", "CODEOWNERS"); - var owners = CodeOwnersFile.ParseAndFindOwnersForClosestMatch(codeOwnersLocation, target); - if (owners == null) - { - Console.WriteLine(String.Format("We cannot find any closest code owners from the target path {0}", targetDirectory)); + try { + var codeOwnerEntry = CodeOwnersFile.ParseAndFindOwnersForClosestMatch(codeOwnerFilePath, target); + if (codeOwnerEntry == null) + { + Console.Error.WriteLine(String.Format("We cannot find any matching code owners from the target path {0}", targetDirectory)); + return 1; + } + else + { + var codeOwnerJson = JsonSerializer.Serialize(codeOwnerEntry, new JsonSerializerOptions { WriteIndented = true }); + Console.WriteLine(codeOwnerJson); + return 0; + } } - else - { - Console.WriteLine(String.Format("##vso[task.setvariable variable={0};]{1}", vsoOwningUsers, String.Join(",", owners))); + catch (Exception e) { + Console.Error.WriteLine(e.Message); + return 1; } } } diff --git a/tools/code-owners-parser/CodeOwnersParser/CodeOwnersFile.cs b/tools/code-owners-parser/CodeOwnersParser/CodeOwnersFile.cs index c8fecbe79de..879e0600d3e 100644 --- a/tools/code-owners-parser/CodeOwnersParser/CodeOwnersFile.cs +++ b/tools/code-owners-parser/CodeOwnersParser/CodeOwnersFile.cs @@ -10,16 +10,13 @@ public static class CodeOwnersFile public static List ParseFile(string filePathOrUrl) { string content; - Colorizer.Write("Retrieving file content from [Yellow!{0}]... ", filePathOrUrl); content = FileHelpers.GetFileContents(filePathOrUrl); - Colorizer.WriteLine("[Green!Done]"); return ParseContent(content); } public static List ParseContent(string fileContent) { - Colorizer.Write("Parsing CODEOWNERS table... "); List entries = new List(); string line; @@ -65,11 +62,10 @@ public static List ParseContent(string fileContent) } } - Colorizer.WriteLine("[Green!Done]"); return entries; } - public static List ParseAndFindOwnersForClosestMatch(string codeOwnersFilePathOrUrl, string targetPath) + public static CodeOwnerEntry ParseAndFindOwnersForClosestMatch(string codeOwnersFilePathOrUrl, string targetPath) { var codeOwnerEntries = ParseFile(codeOwnersFilePathOrUrl); // Normalize the start and end of the paths by trimming slash @@ -84,7 +80,7 @@ public static List ParseAndFindOwnersForClosestMatch(string codeOwnersFi // for our current scenarios but in the future might need to support globs if (targetPath.StartsWith(codeOwnerPath, StringComparison.OrdinalIgnoreCase)) { - return codeOwnerEntries[i].Owners; + return codeOwnerEntries[i]; } } diff --git a/tools/code-owners-parser/CodeOwnersParser/FileHelpers.cs b/tools/code-owners-parser/CodeOwnersParser/FileHelpers.cs index 26dc3318d9e..367ec7d72bc 100644 --- a/tools/code-owners-parser/CodeOwnersParser/FileHelpers.cs +++ b/tools/code-owners-parser/CodeOwnersParser/FileHelpers.cs @@ -17,7 +17,7 @@ public static string GetFileContents(string fileOrUri) Uri uri = new Uri(fileOrUri, UriKind.Absolute); if (uri.Scheme.ToLowerInvariant() != "https") { - throw new ArgumentException("Cannot download off non-https uris"); + throw new ArgumentException(string.Format("Cannot download off non-https uris, path: {0}", fileOrUri)); } // try to download it. diff --git a/tools/code-owners-parser/ci.yml b/tools/code-owners-parser/ci.yml index 3b8d0ec4ad5..97068d14b7b 100644 --- a/tools/code-owners-parser/ci.yml +++ b/tools/code-owners-parser/ci.yml @@ -26,3 +26,10 @@ extends: parameters: ToolDirectory: tools/code-owners-parser DotNetCoreVersion: 5.0.301 + TestPostSteps: + # This is a simple test for placeholder. Will replace the test with get-codeowners.ps1 in future. + - pwsh: | + $output = dotnet run --project "tools\code-owners-parser\Azure.Sdk.Tools.RetrieveCodeOwners\Azure.Sdk.Tools.RetrieveCodeOwners.csproj" ` + --code-owner-file-path "$(Build.SourcesDirectory)/tools/code-owners-parser/Azure.Sdk.Tools.RetrieveCodeOwners.Tests/CODEOWNERS" --target-directory "sdk" + $output | ConvertFrom-Json + displayName: Test on code owner tool output \ No newline at end of file