From 5b3c1a2a89b57a5f49be1404a492a0de1acbaaff Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Wed, 1 Nov 2023 03:01:19 +0300 Subject: [PATCH 01/21] Replace `/users/me` with `/me` in middleware. --- .../Http/UriReplacementHandlerTests.cs | 52 +++++++++ .../Http/UriReplacementHandler.cs | 106 ++++++++++++++++++ .../IO/GraphCliClientFactory.cs | 3 + src/sample/Program.cs | 13 +++ 4 files changed, 174 insertions(+) create mode 100644 src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacementHandlerTests.cs create mode 100644 src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs diff --git a/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacementHandlerTests.cs b/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacementHandlerTests.cs new file mode 100644 index 00000000..a95eb961 --- /dev/null +++ b/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacementHandlerTests.cs @@ -0,0 +1,52 @@ +using System; +using Microsoft.Graph.Cli.Core.Http; +using Xunit; + +namespace Microsoft.Graph.Cli.Core.Tests.Http; + +public class MeUriReplacementTests +{ + [Fact] + public void Returns_Null_When_Given_A_Null_Url() + { + var replacement = new MeUriReplacement(); + + Assert.Null(replacement.Replace(null)); + } + + [Fact] + public void Returns_Original_Uri_When_No_Match_Is_Found() + { + var uri = new Uri("http://example.com/test"); + var replacement = new MeUriReplacement(); + + Assert.Equal(uri, replacement.Replace(uri)); + + uri = new Uri("http://example.com/users/messages"); + Assert.Equal(uri, replacement.Replace(uri)); + + uri = new Uri("http://example.com/v1.0/users/messages"); + Assert.Equal(uri, replacement.Replace(uri)); + + uri = new Uri("http://example.com/users/test/me"); + Assert.Equal(uri, replacement.Replace(uri)); + + uri = new Uri("http://example.com/a/b/users/test/me"); + Assert.Equal(uri, replacement.Replace(uri)); + } + + [Fact] + public void Returns_A_New_Url_When_A_Match_Is_Found() + { + var replacement = new MeUriReplacement(); + + var uri = new Uri("http://example.com/v1.0/users/me/messages"); + Assert.Equal("http://example.com/v1.0/me/messages", replacement.Replace(uri)!.ToString()); + + uri = new Uri("http://example.com/v1.0/users/me"); + Assert.Equal("http://example.com/v1.0/me", replacement.Replace(uri)!.ToString()); + + uri = new Uri("http://example.com/v1.0/users/me?a=b"); + Assert.Equal("http://example.com/v1.0/me?a=b", replacement.Replace(uri)!.ToString()); + } +} diff --git a/src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs b/src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs new file mode 100644 index 00000000..f581233f --- /dev/null +++ b/src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs @@ -0,0 +1,106 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Microsoft.Graph.Cli.Core.Http; + +/// +/// Interface for making URI replacements. +/// +public interface IUriReplacement +{ + /// + /// Accepts a URI and returns a new URI with all replacements applied. + /// + /// The URI to apply replacements to + /// A new URI with all replacements applied. + Uri? Replace(Uri? original); +} + +/// +/// Specialized replacement for /[version]/users/me with /[version]/me +/// +public struct MeUriReplacement : IUriReplacement +{ + /// + /// If a URI path starts with /[version]/users/me, replace it with /[version]/me + /// + /// The original URI + /// A URI with /[version]/users/me replaced with /[version]/me + /// This method assumes that the first segment after the root is a version segment to match Microsoft Graph API's format. + public readonly Uri? Replace(Uri? original) + { + if (original is null) + { + return null; + } + + if (original.Segments.Length < 4) + { + // Must have at least segments "/", "[version]/", "users/", "me" + return original; + } + + var separator = new ReadOnlySpan('/'); + var matchUsers = new ReadOnlySpan(new char[] { 'u', 's', 'e', 'r', 's' }); + var matchMe = new ReadOnlySpan(new char[] { 'm', 'e' }); + + var maybeUsersSegment = original.Segments[2].AsSpan(); + if (!maybeUsersSegment[..(maybeUsersSegment.Length - 1)].SequenceEqual(matchUsers)) + { + return original; + } + + var maybeMeSegment = original.Segments[3].AsSpan(); + if (!maybeMeSegment[..(maybeMeSegment.EndsWith(separator) ? maybeMeSegment.Length - 1 : maybeMeSegment.Length)].SequenceEqual(matchMe)) + { + return original; + } + + var newUrl = new UriBuilder(original); + var versionSegment = original.Segments[1].AsSpan(); + const int USERS_ME_LENGTH = 9; + var length = versionSegment.Length + USERS_ME_LENGTH; + if (newUrl.Path.Length == length) + { + // Matched /[version]/users/me + newUrl.Path = string.Concat(separator, versionSegment, matchMe); + } + else + { + // Maybe matched /[version]/users/me... + // Logic to make sure we don't match paths like /users/messages + var span = newUrl.Path.AsSpan(length); + if (span[0] == '/') + { + newUrl.Path = string.Concat(separator, versionSegment, matchMe, span); + } + } + + return newUrl.Uri; + } +} + +/// +/// Replaces a portion of the URL. +/// +public partial class UriReplacementHandler : DelegatingHandler +{ + private readonly IUriReplacement urlReplacement; + + /// + /// Creates a new UriReplacementHandler. + /// + public UriReplacementHandler(IUriReplacement urlReplacement) + { + this.urlReplacement = urlReplacement; + } + + /// + protected override async Task SendAsync( + HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) + { + request.RequestUri = urlReplacement.Replace(request.RequestUri); + return await base.SendAsync(request, cancellationToken); + } +} diff --git a/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs b/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs index 67ae7c05..f7b992bd 100644 --- a/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs +++ b/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs @@ -38,6 +38,9 @@ public static HttpClient GetDefaultClient(GraphClientOptions? options = null, st m.AddRange(middlewares); + // Add replacement handler for /users/me to /me + m.Add(new UriReplacementHandler(new MeUriReplacement())); + // Add logging handler. if (loggingHandler is LoggingHandler lh) { diff --git a/src/sample/Program.cs b/src/sample/Program.cs index 48a1805f..aeece85f 100644 --- a/src/sample/Program.cs +++ b/src/sample/Program.cs @@ -42,6 +42,19 @@ class Program static async Task Main(string[] args) { + // Replace `me ...` with `users ... --user-id me` + if (args[0] == "me") { + var newArgs = new string[args.Length + 2]; + newArgs[0] = "users"; + for (int i = 1; i < args.Length; i++) + { + newArgs[i] = args[i]; + } + newArgs[args.Length] = "--user-id"; + newArgs[args.Length + 1] = "me"; + args = newArgs; + } + var builder = BuildCommandLine() .UseDefaults() .UseHost(CreateHostBuilder) From 1a0f0e9091c23ea984abd0a9e100ce19800ddb4a Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Wed, 1 Nov 2023 03:11:37 +0300 Subject: [PATCH 02/21] Update args replacement --- src/sample/Program.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/sample/Program.cs b/src/sample/Program.cs index aeece85f..07fe45c2 100644 --- a/src/sample/Program.cs +++ b/src/sample/Program.cs @@ -6,6 +6,7 @@ using System.CommandLine.Parsing; using System.Diagnostics.Tracing; using System.IO; +using System.Linq; using System.Net.Http; using System.Reflection; using System.Threading.Tasks; @@ -43,16 +44,21 @@ class Program static async Task Main(string[] args) { // Replace `me ...` with `users ... --user-id me` - if (args[0] == "me") { - var newArgs = new string[args.Length + 2]; + if (args[0] == "me") + { + var hasHelp = args.Any(static x => x.Contains("-h") || x.Contains("/?")); + var newArgs = hasHelp ? args : new string[args.Length + 2]; newArgs[0] = "users"; for (int i = 1; i < args.Length; i++) { newArgs[i] = args[i]; } - newArgs[args.Length] = "--user-id"; - newArgs[args.Length + 1] = "me"; - args = newArgs; + if (newArgs.Length > args.Length) + { + newArgs[args.Length] = "--user-id"; + newArgs[args.Length + 1] = "me"; + args = newArgs; + } } var builder = BuildCommandLine() From 93877ea97c97682c9615c6a6f80c458888192d80 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Wed, 1 Nov 2023 03:59:23 +0300 Subject: [PATCH 03/21] Refactor `UriReplacementHandler` to use generics, thus eliminating `MeUriReplacement` boxing allocations. Cleanup code. --- .../Http/LoggingHandler.cs | 21 ++------------ .../Http/UriReplacementHandler.cs | 28 +++++++++++++------ .../IO/GraphCliClientFactory.cs | 19 ++++++------- src/sample/Program.cs | 2 +- 4 files changed, 32 insertions(+), 38 deletions(-) diff --git a/src/Microsoft.Graph.Cli.Core/Http/LoggingHandler.cs b/src/Microsoft.Graph.Cli.Core/Http/LoggingHandler.cs index 66900383..60b79797 100644 --- a/src/Microsoft.Graph.Cli.Core/Http/LoggingHandler.cs +++ b/src/Microsoft.Graph.Cli.Core/Http/LoggingHandler.cs @@ -45,12 +45,6 @@ protected override async Task SendAsync( return response; } - /// - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - } - private static string HeadersToString(in HttpHeaders headers, in HttpContentHeaders? contentHeaders) { if (!headers.Any() && contentHeaders?.Any() == false) return string.Empty; @@ -61,7 +55,7 @@ static string selector(KeyValuePair> h) { value = "[PROTECTED]"; } - return string.Format("{0}: {1}\n", h.Key, value); + return $"{h.Key}: {value}\n"; }; static string aggregator(string a, string b) @@ -95,17 +89,8 @@ private static async Task ContentToStringAsync(HttpContent? content, Can { return await content.ReadAsStringAsync(cancellationToken); } - else - { - if (content.Headers.ContentLength > 0) - { - return $"[...<{content.Headers.ContentLength} byte data stream>...]"; - } - else - { - return "[......]"; - } - } + + return content.Headers.ContentLength > 0 ? $"[...<{content.Headers.ContentLength} byte data stream>...]" : "[......]"; } [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = "\nRequest:\n\n{RequestMethod} {RequestUri} HTTP/{HttpVersion}\n{Headers}\n{RequestContent}\n")] diff --git a/src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs b/src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs index f581233f..7dedd8a2 100644 --- a/src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs +++ b/src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs @@ -41,12 +41,22 @@ public struct MeUriReplacement : IUriReplacement return original; } - var separator = new ReadOnlySpan('/'); - var matchUsers = new ReadOnlySpan(new char[] { 'u', 's', 'e', 'r', 's' }); - var matchMe = new ReadOnlySpan(new char[] { 'm', 'e' }); + Span toMatch = stackalloc char[9]; + toMatch[0] = '/'; + toMatch[1] = 'u'; + toMatch[2] = 's'; + toMatch[3] = 'e'; + toMatch[4] = 'r'; + toMatch[5] = 's'; + toMatch[6] = '/'; + toMatch[7] = 'm'; + toMatch[8] = 'e'; + var separator = toMatch[..1]; + var matchUsers = toMatch[1..6]; + var matchMe = toMatch[7..]; var maybeUsersSegment = original.Segments[2].AsSpan(); - if (!maybeUsersSegment[..(maybeUsersSegment.Length - 1)].SequenceEqual(matchUsers)) + if (!maybeUsersSegment[..^1].SequenceEqual(matchUsers)) { return original; } @@ -59,8 +69,8 @@ public struct MeUriReplacement : IUriReplacement var newUrl = new UriBuilder(original); var versionSegment = original.Segments[1].AsSpan(); - const int USERS_ME_LENGTH = 9; - var length = versionSegment.Length + USERS_ME_LENGTH; + const int usersMeLength = 9; + var length = versionSegment.Length + usersMeLength; if (newUrl.Path.Length == length) { // Matched /[version]/users/me @@ -84,14 +94,14 @@ public struct MeUriReplacement : IUriReplacement /// /// Replaces a portion of the URL. /// -public partial class UriReplacementHandler : DelegatingHandler +public class UriReplacementHandler : DelegatingHandler where TUriReplacement: IUriReplacement { - private readonly IUriReplacement urlReplacement; + private readonly TUriReplacement urlReplacement; /// /// Creates a new UriReplacementHandler. /// - public UriReplacementHandler(IUriReplacement urlReplacement) + public UriReplacementHandler(TUriReplacement urlReplacement) { this.urlReplacement = urlReplacement; } diff --git a/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs b/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs index f7b992bd..cd3e0387 100644 --- a/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs +++ b/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs @@ -39,10 +39,10 @@ public static HttpClient GetDefaultClient(GraphClientOptions? options = null, st m.AddRange(middlewares); // Add replacement handler for /users/me to /me - m.Add(new UriReplacementHandler(new MeUriReplacement())); + m.Add(new UriReplacementHandler(new MeUriReplacement())); // Add logging handler. - if (loggingHandler is LoggingHandler lh) + if (loggingHandler is { } lh) { m.Add(lh); } @@ -50,20 +50,19 @@ public static HttpClient GetDefaultClient(GraphClientOptions? options = null, st // Set compression handler to be last (Allows logging handler to log request body) m.Sort((a, b) => { - var a_match = a is Kiota.Http.HttpClientLibrary.Middleware.CompressionHandler; - var b_match = b is Kiota.Http.HttpClientLibrary.Middleware.CompressionHandler; - if (a_match && !b_match) + var aMatch = a is Kiota.Http.HttpClientLibrary.Middleware.CompressionHandler; + var bMatch = b is Kiota.Http.HttpClientLibrary.Middleware.CompressionHandler; + if (aMatch && !bMatch) { return 1; } - else if (b_match && !a_match) + + if (bMatch && !aMatch) { return -1; } - else - { - return 0; - } + + return 0; }); return GraphClientFactory.Create(version: version, nationalCloud: nationalCloud, finalHandler: finalHandler, handlers: m); diff --git a/src/sample/Program.cs b/src/sample/Program.cs index 07fe45c2..addfb44c 100644 --- a/src/sample/Program.cs +++ b/src/sample/Program.cs @@ -49,7 +49,7 @@ static async Task Main(string[] args) var hasHelp = args.Any(static x => x.Contains("-h") || x.Contains("/?")); var newArgs = hasHelp ? args : new string[args.Length + 2]; newArgs[0] = "users"; - for (int i = 1; i < args.Length; i++) + for (var i = 1; i < args.Length; i++) { newArgs[i] = args[i]; } From 687e9758a0fc54c2af60265e94cb7f92c17b7a46 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Wed, 1 Nov 2023 04:08:10 +0300 Subject: [PATCH 04/21] Use from end indexing shorthand --- src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs b/src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs index 7dedd8a2..2aed76e3 100644 --- a/src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs +++ b/src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs @@ -62,7 +62,7 @@ public struct MeUriReplacement : IUriReplacement } var maybeMeSegment = original.Segments[3].AsSpan(); - if (!maybeMeSegment[..(maybeMeSegment.EndsWith(separator) ? maybeMeSegment.Length - 1 : maybeMeSegment.Length)].SequenceEqual(matchMe)) + if (!maybeMeSegment[..(maybeMeSegment.EndsWith(separator) ? ^1 : ^0)].SequenceEqual(matchMe)) { return original; } From 04fd9bbfd5aad9e69de811c51695d6b87f920685 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Wed, 1 Nov 2023 04:17:12 +0300 Subject: [PATCH 05/21] Use explicit help detection --- src/sample/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sample/Program.cs b/src/sample/Program.cs index addfb44c..23ec893b 100644 --- a/src/sample/Program.cs +++ b/src/sample/Program.cs @@ -46,7 +46,7 @@ static async Task Main(string[] args) // Replace `me ...` with `users ... --user-id me` if (args[0] == "me") { - var hasHelp = args.Any(static x => x.Contains("-h") || x.Contains("/?")); + var hasHelp = args.Any(static x => x == "--help" || x == "-h" || x == "/?"); var newArgs = hasHelp ? args : new string[args.Length + 2]; newArgs[0] = "users"; for (var i = 1; i < args.Length; i++) From 0622cb24ea5f76eaefa28f65c5b1740bb163a1fb Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Wed, 1 Nov 2023 16:31:45 +0300 Subject: [PATCH 06/21] Move UriReplacement to kiota cli commons --- .github/workflows/sonarcloud.yml | 78 +++++++++++++++++++ .../MeUriReplacementTests.cs} | 4 +- .../MeUrlReplacement.cs} | 43 +--------- .../Microsoft.Graph.Cli.Core.csproj | 2 +- 4 files changed, 82 insertions(+), 45 deletions(-) create mode 100644 .github/workflows/sonarcloud.yml rename src/Microsoft.Graph.Cli.Core.Tests/Http/{UriReplacementHandlerTests.cs => UriReplacement/MeUriReplacementTests.cs} (93%) rename src/Microsoft.Graph.Cli.Core/Http/{UriReplacementHandler.cs => UriReplacement/MeUrlReplacement.cs} (65%) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml new file mode 100644 index 00000000..79a5b9b3 --- /dev/null +++ b/.github/workflows/sonarcloud.yml @@ -0,0 +1,78 @@ +name: Sonarcloud +on: + workflow_dispatch: + push: + branches: + - main + paths-ignore: ['**.md', '.vscode/**', '**.svg'] + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: ['**.md', '.vscode/**', '**.svg'] + +env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + +jobs: + checksecret: + name: check if SONAR_TOKEN is set in github secrets + runs-on: ubuntu-latest + outputs: + is_SONAR_TOKEN_set: ${{ steps.checksecret_job.outputs.is_SONAR_TOKEN_set }} + steps: + - name: Check whether unity activation requests should be done + id: checksecret_job + run: | + echo "is_SONAR_TOKEN_set=${{ env.SONAR_TOKEN != '' }}" >> $GITHUB_OUTPUT + build: + needs: [checksecret] + if: needs.checksecret.outputs.is_SONAR_TOKEN_set == 'true' + name: Build + runs-on: ubuntu-latest + steps: + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + distribution: 'adopt' + java-version: 17 + - name: Setup .NET 5 # At the moment the scanner requires dotnet 5 https://www.nuget.org/packages/dotnet-sonarscanner + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 5.0.x + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 7.0.x + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - name: Cache SonarCloud packages + uses: actions/cache@v3 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Cache SonarCloud scanner + id: cache-sonar-scanner + uses: actions/cache@v3 + with: + path: ./.sonar/scanner + key: ${{ runner.os }}-sonar-scanner + restore-keys: ${{ runner.os }}-sonar-scanner + - name: Install SonarCloud scanner + if: steps.cache-sonar-scanner.outputs.cache-hit != 'true' + shell: pwsh + run: | + New-Item -Path ./.sonar/scanner -ItemType Directory + dotnet tool update dotnet-sonarscanner --tool-path ./.sonar/scanner + - name: Build and analyze + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + CollectCoverage: true + CoverletOutputFormat: 'opencover' # https://github.com/microsoft/vstest/issues/4014#issuecomment-1307913682 + shell: pwsh + run: | + ./.sonar/scanner/dotnet-sonarscanner begin /k:"microsoft_kiota-cli-commons" /o:"microsoft" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/*.Tests/**/coverage.opencover.xml" + dotnet workload restore + dotnet build + dotnet test Microsoft.Kiota.Cli.Commons.sln --no-build --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=opencover + ./.sonar/scanner/dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" diff --git a/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacementHandlerTests.cs b/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs similarity index 93% rename from src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacementHandlerTests.cs rename to src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs index a95eb961..00d3b565 100644 --- a/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacementHandlerTests.cs +++ b/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs @@ -1,8 +1,8 @@ using System; -using Microsoft.Graph.Cli.Core.Http; +using Microsoft.Graph.Cli.Core.Http.UriReplacement; using Xunit; -namespace Microsoft.Graph.Cli.Core.Tests.Http; +namespace Microsoft.Graph.Cli.Core.Tests.Http.UriReplacement; public class MeUriReplacementTests { diff --git a/src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs b/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUrlReplacement.cs similarity index 65% rename from src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs rename to src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUrlReplacement.cs index 2aed76e3..14524d3b 100644 --- a/src/Microsoft.Graph.Cli.Core/Http/UriReplacementHandler.cs +++ b/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUrlReplacement.cs @@ -1,21 +1,4 @@ -using System; -using System.Net.Http; -using System.Threading.Tasks; - -namespace Microsoft.Graph.Cli.Core.Http; - -/// -/// Interface for making URI replacements. -/// -public interface IUriReplacement -{ - /// - /// Accepts a URI and returns a new URI with all replacements applied. - /// - /// The URI to apply replacements to - /// A new URI with all replacements applied. - Uri? Replace(Uri? original); -} +namespace Microsoft.Graph.Cli.Core.Http.UriReplacement; /// /// Specialized replacement for /[version]/users/me with /[version]/me @@ -90,27 +73,3 @@ public struct MeUriReplacement : IUriReplacement return newUrl.Uri; } } - -/// -/// Replaces a portion of the URL. -/// -public class UriReplacementHandler : DelegatingHandler where TUriReplacement: IUriReplacement -{ - private readonly TUriReplacement urlReplacement; - - /// - /// Creates a new UriReplacementHandler. - /// - public UriReplacementHandler(TUriReplacement urlReplacement) - { - this.urlReplacement = urlReplacement; - } - - /// - protected override async Task SendAsync( - HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) - { - request.RequestUri = urlReplacement.Replace(request.RequestUri); - return await base.SendAsync(request, cancellationToken); - } -} diff --git a/src/Microsoft.Graph.Cli.Core/Microsoft.Graph.Cli.Core.csproj b/src/Microsoft.Graph.Cli.Core/Microsoft.Graph.Cli.Core.csproj index e06bca93..478a919d 100644 --- a/src/Microsoft.Graph.Cli.Core/Microsoft.Graph.Cli.Core.csproj +++ b/src/Microsoft.Graph.Cli.Core/Microsoft.Graph.Cli.Core.csproj @@ -44,7 +44,7 @@ - + From 40bd0f8a04651520ee237986dc02ea279ee92000 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Wed, 1 Nov 2023 16:39:02 +0300 Subject: [PATCH 07/21] Remove redundant pipeline --- .github/workflows/release-package.yml | 58 --------------------------- 1 file changed, 58 deletions(-) delete mode 100644 .github/workflows/release-package.yml diff --git a/.github/workflows/release-package.yml b/.github/workflows/release-package.yml deleted file mode 100644 index c26b0650..00000000 --- a/.github/workflows/release-package.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Release solution - -on: - workflow_dispatch: - push: - # paths: ['src/**', '.github/workflows/**', 'msgraph-cli-core.sln'] - -jobs: - build: - runs-on: ubuntu-latest - env: - MS_NUGET_URL: https://nuget.pkg.github.com/microsoft/index.json - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup .NET Core SDK 6 - uses: actions/setup-dotnet@v3.2.0 - with: - dotnet-version: 7.x - - uses: actions/cache@v3 - with: - path: ~/.nuget/packages - # Look to see if there is a cache hit for the corresponding requirements file - key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} - restore-keys: | - ${{ runner.os }}-nuget - - name: Install dependencies - run: dotnet restore - - name: Test - run: dotnet test --no-restore - - id: publish - name: Publish - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} - run: dotnet publish --no-restore --verbosity normal -c Release - - id: pack - name: Pack - if: ${{ steps.publish.outcome == 'success' }} - run: dotnet pack --no-restore --no-build --verbosity normal -c Release - - name: Upload Nuget Package - if: ${{ steps.pack.outcome == 'success' }} - uses: actions/upload-artifact@v3 - with: - name: drop - path: | - ./src/Microsoft.Graph.Cli.Core/bin/Release/*.nupkg - deploy: - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} - runs-on: ubuntu-latest - needs: [build] - steps: - - name: Setup .NET - uses: actions/setup-dotnet@v3.2.0 - with: - dotnet-version: 7.x - - uses: actions/download-artifact@v3 - with: - name: drop - - run: dotnet nuget push "*.nupkg" --skip-duplicate -s https://nuget.pkg.github.com/microsoftgraph/index.json -k ${{ secrets.GITHUB_TOKEN }} From 5075616c8d1572f098d6b3d80cafe4b355905963 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Wed, 1 Nov 2023 16:46:46 +0300 Subject: [PATCH 08/21] Revert: Remove redundant pipeline --- .github/workflows/release-package.yml | 58 +++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/workflows/release-package.yml diff --git a/.github/workflows/release-package.yml b/.github/workflows/release-package.yml new file mode 100644 index 00000000..c26b0650 --- /dev/null +++ b/.github/workflows/release-package.yml @@ -0,0 +1,58 @@ +name: Release solution + +on: + workflow_dispatch: + push: + # paths: ['src/**', '.github/workflows/**', 'msgraph-cli-core.sln'] + +jobs: + build: + runs-on: ubuntu-latest + env: + MS_NUGET_URL: https://nuget.pkg.github.com/microsoft/index.json + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup .NET Core SDK 6 + uses: actions/setup-dotnet@v3.2.0 + with: + dotnet-version: 7.x + - uses: actions/cache@v3 + with: + path: ~/.nuget/packages + # Look to see if there is a cache hit for the corresponding requirements file + key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} + restore-keys: | + ${{ runner.os }}-nuget + - name: Install dependencies + run: dotnet restore + - name: Test + run: dotnet test --no-restore + - id: publish + name: Publish + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + run: dotnet publish --no-restore --verbosity normal -c Release + - id: pack + name: Pack + if: ${{ steps.publish.outcome == 'success' }} + run: dotnet pack --no-restore --no-build --verbosity normal -c Release + - name: Upload Nuget Package + if: ${{ steps.pack.outcome == 'success' }} + uses: actions/upload-artifact@v3 + with: + name: drop + path: | + ./src/Microsoft.Graph.Cli.Core/bin/Release/*.nupkg + deploy: + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + runs-on: ubuntu-latest + needs: [build] + steps: + - name: Setup .NET + uses: actions/setup-dotnet@v3.2.0 + with: + dotnet-version: 7.x + - uses: actions/download-artifact@v3 + with: + name: drop + - run: dotnet nuget push "*.nupkg" --skip-duplicate -s https://nuget.pkg.github.com/microsoftgraph/index.json -k ${{ secrets.GITHUB_TOKEN }} From 8fe974bc972b76067835625d113927e12d59dc76 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Wed, 1 Nov 2023 19:19:37 +0300 Subject: [PATCH 09/21] Simplify stackalloc initialization --- .../Http/UriReplacement/MeUrlReplacement.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUrlReplacement.cs b/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUrlReplacement.cs index 14524d3b..7f7c3abc 100644 --- a/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUrlReplacement.cs +++ b/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUrlReplacement.cs @@ -1,3 +1,5 @@ +using System; + namespace Microsoft.Graph.Cli.Core.Http.UriReplacement; /// @@ -24,16 +26,7 @@ public struct MeUriReplacement : IUriReplacement return original; } - Span toMatch = stackalloc char[9]; - toMatch[0] = '/'; - toMatch[1] = 'u'; - toMatch[2] = 's'; - toMatch[3] = 'e'; - toMatch[4] = 'r'; - toMatch[5] = 's'; - toMatch[6] = '/'; - toMatch[7] = 'm'; - toMatch[8] = 'e'; + Span toMatch = stackalloc char[] { '/', 'u', 's', 'e', 'r', 's', '/', 'm', 'e' }; var separator = toMatch[..1]; var matchUsers = toMatch[1..6]; var matchMe = toMatch[7..]; From d0eefa2d0058e2685763499a0f2a852d49b94d4c Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Thu, 2 Nov 2023 02:52:40 +0300 Subject: [PATCH 10/21] Update src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs Co-authored-by: Peter Ombwa --- .../UriReplacement/MeUriReplacementTests.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs b/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs index 00d3b565..038ca53a 100644 --- a/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs +++ b/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs @@ -35,18 +35,15 @@ public void Returns_Original_Uri_When_No_Match_Is_Found() Assert.Equal(uri, replacement.Replace(uri)); } - [Fact] - public void Returns_A_New_Url_When_A_Match_Is_Found() + [Theory] + [InlineData("http://example.com/v1.0/users/me/messages", "http://example.com/v1.0/me/messages")] + [InlineData("http://example.com/v1.0/users/me", "http://example.com/v1.0/me")] + [InlineData("http://example.com/v1.0/users/me?a=b", "http://example.com/v1.0/me?a=b")] + public void Returns_A_New_Url_When_A_Match_Is_Found(string inputUri, string expectedUri) { var replacement = new MeUriReplacement(); - var uri = new Uri("http://example.com/v1.0/users/me/messages"); - Assert.Equal("http://example.com/v1.0/me/messages", replacement.Replace(uri)!.ToString()); - - uri = new Uri("http://example.com/v1.0/users/me"); - Assert.Equal("http://example.com/v1.0/me", replacement.Replace(uri)!.ToString()); - - uri = new Uri("http://example.com/v1.0/users/me?a=b"); - Assert.Equal("http://example.com/v1.0/me?a=b", replacement.Replace(uri)!.ToString()); + var uri = new Uri(inputUri); + Assert.Equal(expectedUri, replacement.Replace(uri)!.ToString()); } } From 51d1fa1d34d074dee84fa9c2b1f3f94a02f27e83 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Thu, 2 Nov 2023 02:53:02 +0300 Subject: [PATCH 11/21] Update src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs Co-authored-by: Peter Ombwa --- .../UriReplacement/MeUriReplacementTests.cs | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs b/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs index 038ca53a..b3e90c77 100644 --- a/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs +++ b/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs @@ -14,25 +14,18 @@ public void Returns_Null_When_Given_A_Null_Url() Assert.Null(replacement.Replace(null)); } - [Fact] - public void Returns_Original_Uri_When_No_Match_Is_Found() + [Theory] + [InlineData("http://example.com/test")] + [InlineData("http://example.com/users/messages")] + [InlineData("http://example.com/v1.0/users/messages")] + [InlineData("http://example.com/users/test/me")] + [InlineData("http://example.com/a/b/users/test/me")] + public void Returns_Original_Uri_When_No_Match_Is_Found(string inputUri) { - var uri = new Uri("http://example.com/test"); + var uri = new Uri(inputUri); var replacement = new MeUriReplacement(); Assert.Equal(uri, replacement.Replace(uri)); - - uri = new Uri("http://example.com/users/messages"); - Assert.Equal(uri, replacement.Replace(uri)); - - uri = new Uri("http://example.com/v1.0/users/messages"); - Assert.Equal(uri, replacement.Replace(uri)); - - uri = new Uri("http://example.com/users/test/me"); - Assert.Equal(uri, replacement.Replace(uri)); - - uri = new Uri("http://example.com/a/b/users/test/me"); - Assert.Equal(uri, replacement.Replace(uri)); } [Theory] From 702e488a593e4ac764d04664e183e70f6d4768a9 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Thu, 2 Nov 2023 20:47:34 +0300 Subject: [PATCH 12/21] Update MeUriReplacementOption --- ...ests.cs => MeUriReplacementOptionTests.cs} | 8 +++---- ...placement.cs => MeUriReplacementOption.cs} | 22 +++++++++++++++++-- .../IO/GraphCliClientFactory.cs | 4 +++- .../Microsoft.Graph.Cli.Core.csproj | 4 ++-- 4 files changed, 29 insertions(+), 9 deletions(-) rename src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/{MeUriReplacementTests.cs => MeUriReplacementOptionTests.cs} (87%) rename src/Microsoft.Graph.Cli.Core/Http/UriReplacement/{MeUrlReplacement.cs => MeUriReplacementOption.cs} (80%) diff --git a/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs b/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementOptionTests.cs similarity index 87% rename from src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs rename to src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementOptionTests.cs index 00d3b565..0c3b4ff1 100644 --- a/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementTests.cs +++ b/src/Microsoft.Graph.Cli.Core.Tests/Http/UriReplacement/MeUriReplacementOptionTests.cs @@ -4,12 +4,12 @@ namespace Microsoft.Graph.Cli.Core.Tests.Http.UriReplacement; -public class MeUriReplacementTests +public class MeUriReplacementOptionTests { [Fact] public void Returns_Null_When_Given_A_Null_Url() { - var replacement = new MeUriReplacement(); + var replacement = new MeUriReplacementOption(); Assert.Null(replacement.Replace(null)); } @@ -18,7 +18,7 @@ public void Returns_Null_When_Given_A_Null_Url() public void Returns_Original_Uri_When_No_Match_Is_Found() { var uri = new Uri("http://example.com/test"); - var replacement = new MeUriReplacement(); + var replacement = new MeUriReplacementOption(); Assert.Equal(uri, replacement.Replace(uri)); @@ -38,7 +38,7 @@ public void Returns_Original_Uri_When_No_Match_Is_Found() [Fact] public void Returns_A_New_Url_When_A_Match_Is_Found() { - var replacement = new MeUriReplacement(); + var replacement = new MeUriReplacementOption(); var uri = new Uri("http://example.com/v1.0/users/me/messages"); Assert.Equal("http://example.com/v1.0/me/messages", replacement.Replace(uri)!.ToString()); diff --git a/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUrlReplacement.cs b/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUriReplacementOption.cs similarity index 80% rename from src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUrlReplacement.cs rename to src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUriReplacementOption.cs index 7f7c3abc..e50d50bd 100644 --- a/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUrlReplacement.cs +++ b/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUriReplacementOption.cs @@ -1,12 +1,30 @@ using System; +using Microsoft.Kiota.Http.HttpClientLibrary.Middleware.Options; namespace Microsoft.Graph.Cli.Core.Http.UriReplacement; /// /// Specialized replacement for /[version]/users/me with /[version]/me /// -public struct MeUriReplacement : IUriReplacement +public readonly struct MeUriReplacementOption : IUriReplacementHandlerOption { + private readonly bool isEnabled; + + /// + /// Create new MeUriReplacement + /// + /// + public MeUriReplacementOption(bool isEnabled = true) + { + this.isEnabled = isEnabled; + } + + /// + public readonly bool IsEnabled() + { + return isEnabled; + } + /// /// If a URI path starts with /[version]/users/me, replace it with /[version]/me /// @@ -20,7 +38,7 @@ public struct MeUriReplacement : IUriReplacement return null; } - if (original.Segments.Length < 4) + if (!isEnabled || original.Segments.Length < 4) { // Must have at least segments "/", "[version]/", "users/", "me" return original; diff --git a/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs b/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs index cd3e0387..2a1d3cff 100644 --- a/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs +++ b/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using System.Net.Http; using Microsoft.Graph.Cli.Core.Http; +using Microsoft.Graph.Cli.Core.Http.UriReplacement; +using Microsoft.Kiota.Http.HttpClientLibrary.Middleware; namespace Microsoft.Graph.Cli.Core.IO; @@ -39,7 +41,7 @@ public static HttpClient GetDefaultClient(GraphClientOptions? options = null, st m.AddRange(middlewares); // Add replacement handler for /users/me to /me - m.Add(new UriReplacementHandler(new MeUriReplacement())); + m.Add(new UriReplacementHandler(new MeUriReplacementOption())); // Add logging handler. if (loggingHandler is { } lh) diff --git a/src/Microsoft.Graph.Cli.Core/Microsoft.Graph.Cli.Core.csproj b/src/Microsoft.Graph.Cli.Core/Microsoft.Graph.Cli.Core.csproj index 478a919d..7dc12f56 100644 --- a/src/Microsoft.Graph.Cli.Core/Microsoft.Graph.Cli.Core.csproj +++ b/src/Microsoft.Graph.Cli.Core/Microsoft.Graph.Cli.Core.csproj @@ -44,8 +44,8 @@ - - + + From 35338c340c885644f552a62e08835a24236e096e Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Thu, 2 Nov 2023 21:01:25 +0300 Subject: [PATCH 13/21] Update MeUriReplacement to use kiota http handler --- .../Http/UriReplacement/MeUriReplacementOption.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUriReplacementOption.cs b/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUriReplacementOption.cs index e50d50bd..eb69ed3d 100644 --- a/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUriReplacementOption.cs +++ b/src/Microsoft.Graph.Cli.Core/Http/UriReplacement/MeUriReplacementOption.cs @@ -6,21 +6,21 @@ namespace Microsoft.Graph.Cli.Core.Http.UriReplacement; /// /// Specialized replacement for /[version]/users/me with /[version]/me /// -public readonly struct MeUriReplacementOption : IUriReplacementHandlerOption +public class MeUriReplacementOption : IUriReplacementHandlerOption { private readonly bool isEnabled; /// - /// Create new MeUriReplacement + /// Create new MeUriReplacementOption /// - /// + /// Whether the uri replacement is enabled. public MeUriReplacementOption(bool isEnabled = true) { this.isEnabled = isEnabled; } /// - public readonly bool IsEnabled() + public bool IsEnabled() { return isEnabled; } @@ -31,7 +31,7 @@ public readonly bool IsEnabled() /// The original URI /// A URI with /[version]/users/me replaced with /[version]/me /// This method assumes that the first segment after the root is a version segment to match Microsoft Graph API's format. - public readonly Uri? Replace(Uri? original) + public Uri? Replace(Uri? original) { if (original is null) { From 90a2d00c137f841627f37fa701adea40d2c9ed4e Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Thu, 2 Nov 2023 22:21:30 +0300 Subject: [PATCH 14/21] Update sonarcloud --- .github/workflows/sonarcloud.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 79a5b9b3..f671e5cf 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -71,8 +71,8 @@ jobs: CoverletOutputFormat: 'opencover' # https://github.com/microsoft/vstest/issues/4014#issuecomment-1307913682 shell: pwsh run: | - ./.sonar/scanner/dotnet-sonarscanner begin /k:"microsoft_kiota-cli-commons" /o:"microsoft" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/*.Tests/**/coverage.opencover.xml" + ./.sonar/scanner/dotnet-sonarscanner begin /k:"microsoft_graph-cli-core" /o:"microsoft" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/*.Tests/**/coverage.opencover.xml" dotnet workload restore dotnet build - dotnet test Microsoft.Kiota.Cli.Commons.sln --no-build --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=opencover + dotnet test msgraph-cli-core.sln --no-build --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=opencover ./.sonar/scanner/dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" From c780b78a6b44a2e05063db1ec747d0896b81b254 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Fri, 3 Nov 2023 03:26:42 +0300 Subject: [PATCH 15/21] Update .github/workflows/sonarcloud.yml Co-authored-by: Peter Ombwa --- .github/workflows/sonarcloud.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index f671e5cf..069cf02c 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -71,7 +71,7 @@ jobs: CoverletOutputFormat: 'opencover' # https://github.com/microsoft/vstest/issues/4014#issuecomment-1307913682 shell: pwsh run: | - ./.sonar/scanner/dotnet-sonarscanner begin /k:"microsoft_graph-cli-core" /o:"microsoft" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/*.Tests/**/coverage.opencover.xml" + ./.sonar/scanner/dotnet-sonarscanner begin /k:"microsoftgraph_msgraph-cli-core" /o:"microsoft" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/*.Tests/**/coverage.opencover.xml" dotnet workload restore dotnet build dotnet test msgraph-cli-core.sln --no-build --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=opencover From 35d0ce06498bdcd8ffce4f0eb7866308d2069c51 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Fri, 3 Nov 2023 03:35:49 +0300 Subject: [PATCH 16/21] Update sonar org. --- .github/workflows/sonarcloud.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 069cf02c..accf14f2 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -71,7 +71,7 @@ jobs: CoverletOutputFormat: 'opencover' # https://github.com/microsoft/vstest/issues/4014#issuecomment-1307913682 shell: pwsh run: | - ./.sonar/scanner/dotnet-sonarscanner begin /k:"microsoftgraph_msgraph-cli-core" /o:"microsoft" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/*.Tests/**/coverage.opencover.xml" + ./.sonar/scanner/dotnet-sonarscanner begin /k:"microsoftgraph_msgraph-cli-core" /o:"microsoftgraph" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/*.Tests/**/coverage.opencover.xml" dotnet workload restore dotnet build dotnet test msgraph-cli-core.sln --no-build --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=opencover From 08cf7e9646e4e30f139a6ccba2668837a02dc345 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Fri, 3 Nov 2023 18:20:58 +0300 Subject: [PATCH 17/21] Update sonarcloud org name --- .github/workflows/sonarcloud.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index accf14f2..07438f09 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -71,7 +71,7 @@ jobs: CoverletOutputFormat: 'opencover' # https://github.com/microsoft/vstest/issues/4014#issuecomment-1307913682 shell: pwsh run: | - ./.sonar/scanner/dotnet-sonarscanner begin /k:"microsoftgraph_msgraph-cli-core" /o:"microsoftgraph" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/*.Tests/**/coverage.opencover.xml" + ./.sonar/scanner/dotnet-sonarscanner begin /k:"microsoftgraph_msgraph-cli-core" /o:"microsoftgraph2" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/*.Tests/**/coverage.opencover.xml" dotnet workload restore dotnet build dotnet test msgraph-cli-core.sln --no-build --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=opencover From f0a533f939c33b2cfa9b94099040d24df3972033 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Fri, 3 Nov 2023 18:58:15 +0300 Subject: [PATCH 18/21] Fix code smell --- src/sample/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sample/Program.cs b/src/sample/Program.cs index 23ec893b..8d741376 100644 --- a/src/sample/Program.cs +++ b/src/sample/Program.cs @@ -46,7 +46,7 @@ static async Task Main(string[] args) // Replace `me ...` with `users ... --user-id me` if (args[0] == "me") { - var hasHelp = args.Any(static x => x == "--help" || x == "-h" || x == "/?"); + var hasHelp = Array.Exists(args, static x => x == "--help" || x == "-h" || x == "/?"); var newArgs = hasHelp ? args : new string[args.Length + 2]; newArgs[0] = "users"; for (var i = 1; i < args.Length; i++) From ecb667ba4666b130ea1797a513e8766b8d0c92bd Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Mon, 6 Nov 2023 11:09:09 +0300 Subject: [PATCH 19/21] Add coverlet msbuild for coverage reporting --- .../Microsoft.Graph.Cli.Core.Tests.csproj | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Graph.Cli.Core.Tests/Microsoft.Graph.Cli.Core.Tests.csproj b/src/Microsoft.Graph.Cli.Core.Tests/Microsoft.Graph.Cli.Core.Tests.csproj index f0f2f0dd..4a01a512 100644 --- a/src/Microsoft.Graph.Cli.Core.Tests/Microsoft.Graph.Cli.Core.Tests.csproj +++ b/src/Microsoft.Graph.Cli.Core.Tests/Microsoft.Graph.Cli.Core.Tests.csproj @@ -19,14 +19,11 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - + - \ No newline at end of file + From 852b0b7e61660c9aaaa7ae4c4bd5525e72d61337 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Mon, 6 Nov 2023 11:39:55 +0300 Subject: [PATCH 20/21] Exclude sample project from sonarcloud exclusions. --- .github/workflows/sonarcloud.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 07438f09..f76ff9bd 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -71,7 +71,7 @@ jobs: CoverletOutputFormat: 'opencover' # https://github.com/microsoft/vstest/issues/4014#issuecomment-1307913682 shell: pwsh run: | - ./.sonar/scanner/dotnet-sonarscanner begin /k:"microsoftgraph_msgraph-cli-core" /o:"microsoftgraph2" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/*.Tests/**/coverage.opencover.xml" + ./.sonar/scanner/dotnet-sonarscanner begin /k:"microsoftgraph_msgraph-cli-core" /o:"microsoftgraph2" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/*.Tests/**/coverage.opencover.xml" /d:sonar.coverage.exclusions="src/sample/**" dotnet workload restore dotnet build dotnet test msgraph-cli-core.sln --no-build --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=opencover From e147e822666653792ee1e8f83aabf23a9b1bc065 Mon Sep 17 00:00:00 2001 From: Caleb Kiage <747955+calebkiage@users.noreply.github.com> Date: Mon, 6 Nov 2023 12:58:47 +0300 Subject: [PATCH 21/21] Add a me alias to users to show in help --- src/Microsoft.Graph.Cli.Core/Microsoft.Graph.Cli.Core.csproj | 2 +- src/sample/Program.cs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Graph.Cli.Core/Microsoft.Graph.Cli.Core.csproj b/src/Microsoft.Graph.Cli.Core/Microsoft.Graph.Cli.Core.csproj index 7dc12f56..1c302bf9 100644 --- a/src/Microsoft.Graph.Cli.Core/Microsoft.Graph.Cli.Core.csproj +++ b/src/Microsoft.Graph.Cli.Core/Microsoft.Graph.Cli.Core.csproj @@ -25,7 +25,7 @@ ../35MSSharedLib1024.snk false false - true + false true diff --git a/src/sample/Program.cs b/src/sample/Program.cs index 8d741376..412b4f56 100644 --- a/src/sample/Program.cs +++ b/src/sample/Program.cs @@ -146,6 +146,11 @@ static CommandLineBuilder BuildCommandLine() rootCommand.Add(new LoginCommand(builder)); rootCommand.AddGlobalOption(debugOption); + if (rootCommand.Subcommands.FirstOrDefault(static c => c.Name == "users") is {} usersCmd) + { + usersCmd.AddAlias("me"); + } + return builder; }