From 03aed8ad2a220b72bf2891de9b73edd5f0a7a6c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 21:26:12 +0000 Subject: [PATCH 01/24] Bump docker/build-push-action from 4.1.1 to 4.2.1 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4.1.1 to 4.2.1. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v4.1.1...v4.2.1) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index c9094388f..daee21546 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -30,13 +30,13 @@ jobs: id: getversion - name: Push to GitHub Packages - Nightly if: ${{ github.ref == 'refs/heads/vnext' }} - uses: docker/build-push-action@v4.1.1 + uses: docker/build-push-action@v4.2.1 with: push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly - name: Push to GitHub Packages - Release if: ${{ github.ref == 'refs/heads/master' }} - uses: docker/build-push-action@v4.1.1 + uses: docker/build-push-action@v4.2.1 with: push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.getversion.outputs.version }} From 928483615a1393bb73f47214b8f03b768c235f72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 21:43:31 +0000 Subject: [PATCH 02/24] Bump Verify.Xunit from 21.0.0 to 21.1.1 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 21.0.0 to 21.1.1. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/21.0.0...21.1.1) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 2bb427c7b..f643e43b2 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -28,7 +28,7 @@ - + all From 0e67b93fadea80778c7d708251e1c6946546f18e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 21:59:07 +0000 Subject: [PATCH 03/24] Bump Microsoft.Windows.Compatibility from 7.0.4 to 7.0.5 Bumps [Microsoft.Windows.Compatibility](https://github.com/dotnet/runtime) from 7.0.4 to 7.0.5. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v7.0.4...v7.0.5) --- updated-dependencies: - dependency-name: Microsoft.Windows.Compatibility dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../Microsoft.OpenApi.Workbench.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj b/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj index 70c120ca0..e2d75c96a 100644 --- a/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj +++ b/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj @@ -11,7 +11,7 @@ all - + From b1d174a82576c92859c6bdf183d47b27cc377896 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Sep 2023 21:43:42 +0000 Subject: [PATCH 04/24] Bump Verify.Xunit from 21.1.1 to 21.1.3 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 21.1.1 to 21.1.3. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/21.1.1...21.1.3) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index f643e43b2..a028227ef 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -28,7 +28,7 @@ - + all From 681454232dea9bd0a27ba4b44489309befa431ba Mon Sep 17 00:00:00 2001 From: waldekmastykarz Date: Thu, 14 Sep 2023 16:36:38 +0200 Subject: [PATCH 05/24] Fixes null reference exception. Closes #1342 --- src/Microsoft.OpenApi.Hidi/OpenApiService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index 78f48cd4c..9797ecd65 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -151,7 +151,7 @@ private static OpenApiDocument ApplyFilters(HidiOptions options, ILogger logger, } else if (postmanCollection != null) { - requestUrls = EnumerateJsonDocument(postmanCollection.RootElement, requestUrls); + requestUrls = EnumerateJsonDocument(postmanCollection.RootElement, new()); logger.LogTrace("Finished fetching the list of paths and Http methods defined in the Postman collection."); } From ee526e7528c0a945ab616dc1e639ea71adba1155 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 14 Sep 2023 15:25:53 -0400 Subject: [PATCH 06/24] - enables NRT for main hidi project --- .vscode/settings.json | 5 +- .../Extensions/OpenApiExtensibleExtensions.cs | 4 +- .../Extensions/StringExtensions.cs | 9 +- .../Formatters/PowerShellFormatter.cs | 6 +- .../Handlers/PluginCommandHandler.cs | 3 +- .../Handlers/ShowCommandHandler.cs | 3 +- .../Handlers/TransformCommandHandler.cs | 3 +- .../Handlers/ValidateCommandHandler.cs | 4 +- .../Microsoft.OpenApi.Hidi.csproj | 11 ++- src/Microsoft.OpenApi.Hidi/OpenApiService.cs | 94 ++++++++++--------- .../Options/FilterOptions.cs | 8 +- .../Options/HidiOptions.cs | 23 ++--- .../Utilities/SettingsUtilities.cs | 7 +- .../Microsoft.OpenApi.Readers.csproj | 7 ++ .../Extensions/OpenApiExtensibleExtensions.cs | 3 +- .../Microsoft.OpenApi.csproj | 7 ++ .../Models/OpenApiParameter.cs | 3 + .../Writers/OpenApiWriterSettings.cs | 1 + .../Services/OpenApiFilterServiceTests.cs | 2 +- .../Services/OpenApiServiceTests.cs | 16 ++-- .../V2Tests/OpenApiServerTests.cs | 28 +++--- .../Models/OpenApiSchemaTests.cs | 2 +- .../Services/OpenApiUrlTreeNodeTests.cs | 6 +- 23 files changed, 150 insertions(+), 105 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 0313280bf..ec27390f9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,5 +3,8 @@ "activityBar.background": "#03323C", "titleBar.activeBackground": "#054754", "titleBar.activeForeground": "#F0FCFE" - } + }, + "cSpell.words": [ + "Hidi" + ] } \ No newline at end of file diff --git a/src/Microsoft.OpenApi.Hidi/Extensions/OpenApiExtensibleExtensions.cs b/src/Microsoft.OpenApi.Hidi/Extensions/OpenApiExtensibleExtensions.cs index 194d122b8..faf03c3f0 100644 --- a/src/Microsoft.OpenApi.Hidi/Extensions/OpenApiExtensibleExtensions.cs +++ b/src/Microsoft.OpenApi.Hidi/Extensions/OpenApiExtensibleExtensions.cs @@ -12,13 +12,13 @@ internal static class OpenApiExtensibleExtensions /// A dictionary of . /// The key corresponding to the . /// A value matching the provided extensionKey. Return null when extensionKey is not found. - public static string GetExtension(this IDictionary extensions, string extensionKey) + internal static string GetExtension(this IDictionary extensions, string extensionKey) { if (extensions.TryGetValue(extensionKey, out var value) && value is OpenApiString castValue) { return castValue.Value; } - return default; + return string.Empty; } } } diff --git a/src/Microsoft.OpenApi.Hidi/Extensions/StringExtensions.cs b/src/Microsoft.OpenApi.Hidi/Extensions/StringExtensions.cs index e5c4b81c4..99208a1d4 100644 --- a/src/Microsoft.OpenApi.Hidi/Extensions/StringExtensions.cs +++ b/src/Microsoft.OpenApi.Hidi/Extensions/StringExtensions.cs @@ -12,13 +12,16 @@ internal static class StringExtensions /// /// Checks if the specified searchValue is equal to the target string based on the specified . /// - /// The target string to commpare to. + /// The target string to compare to. /// The search string to seek. /// The to use. This defaults to . /// true if the searchValue parameter occurs within this string; otherwise, false. - public static bool IsEquals(this string target, string searchValue, StringComparison comparison = StringComparison.OrdinalIgnoreCase) + public static bool IsEquals(this string? target, string? searchValue, StringComparison comparison = StringComparison.OrdinalIgnoreCase) { - if (string.IsNullOrWhiteSpace(target) || string.IsNullOrWhiteSpace(searchValue)) + if (string.IsNullOrWhiteSpace(target) && string.IsNullOrWhiteSpace(searchValue)) + { + return true; + } else if (string.IsNullOrWhiteSpace(target)) { return false; } diff --git a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs index 02a2e1947..f876e4008 100644 --- a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs +++ b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs @@ -191,9 +191,8 @@ private void AddAdditionalPropertiesToSchema(OpenApiSchema schema) private static void ResolveOneOfSchema(OpenApiSchema schema) { - if (schema.OneOf?.Any() ?? false) + if (schema.OneOf?.FirstOrDefault() is {} newSchema) { - var newSchema = schema.OneOf.FirstOrDefault(); schema.OneOf = null; FlattenSchema(schema, newSchema); } @@ -201,9 +200,8 @@ private static void ResolveOneOfSchema(OpenApiSchema schema) private static void ResolveAnyOfSchema(OpenApiSchema schema) { - if (schema.AnyOf?.Any() ?? false) + if (schema.AnyOf?.FirstOrDefault() is {} newSchema) { - var newSchema = schema.AnyOf.FirstOrDefault(); schema.AnyOf = null; FlattenSchema(schema, newSchema); } diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/PluginCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/PluginCommandHandler.cs index aae0285f0..ae090207c 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/PluginCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/PluginCommandHandler.cs @@ -5,6 +5,7 @@ using System.CommandLine.Invocation; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Hidi.Options; @@ -24,7 +25,7 @@ public int Invoke(InvocationContext context) public async Task InvokeAsync(InvocationContext context) { HidiOptions hidiOptions = new HidiOptions(context.ParseResult, CommandOptions); - CancellationToken cancellationToken = (CancellationToken)context.BindingContext.GetService(typeof(CancellationToken)); + CancellationToken cancellationToken = (CancellationToken)context.BindingContext.GetRequiredService(typeof(CancellationToken)); using var loggerFactory = Logger.ConfigureLogger(hidiOptions.LogLevel); var logger = loggerFactory.CreateLogger(); diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/ShowCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/ShowCommandHandler.cs index eea087e36..7db17fea9 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/ShowCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/ShowCommandHandler.cs @@ -5,6 +5,7 @@ using System.CommandLine.Invocation; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Hidi.Options; @@ -24,7 +25,7 @@ public int Invoke(InvocationContext context) public async Task InvokeAsync(InvocationContext context) { HidiOptions hidiOptions = new HidiOptions(context.ParseResult, CommandOptions); - CancellationToken cancellationToken = (CancellationToken)context.BindingContext.GetService(typeof(CancellationToken)); + CancellationToken cancellationToken = (CancellationToken)context.BindingContext.GetRequiredService(typeof(CancellationToken)); using var loggerFactory = Logger.ConfigureLogger(hidiOptions.LogLevel); var logger = loggerFactory.CreateLogger(); diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs index 85e9c05f6..440c20e0b 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs @@ -5,6 +5,7 @@ using System.CommandLine.Invocation; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Hidi.Options; @@ -24,7 +25,7 @@ public int Invoke(InvocationContext context) public async Task InvokeAsync(InvocationContext context) { HidiOptions hidiOptions = new HidiOptions(context.ParseResult, CommandOptions); - CancellationToken cancellationToken = (CancellationToken)context.BindingContext.GetService(typeof(CancellationToken)); + CancellationToken cancellationToken = (CancellationToken)context.BindingContext.GetRequiredService(typeof(CancellationToken)); using var loggerFactory = Logger.ConfigureLogger(hidiOptions.LogLevel); var logger = loggerFactory.CreateLogger(); diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs index 29e0a9518..8bb5676bc 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs @@ -5,6 +5,7 @@ using System.CommandLine.Invocation; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Hidi.Options; @@ -26,11 +27,12 @@ public int Invoke(InvocationContext context) public async Task InvokeAsync(InvocationContext context) { HidiOptions hidiOptions = new HidiOptions(context.ParseResult, CommandOptions); - CancellationToken cancellationToken = (CancellationToken)context.BindingContext.GetService(typeof(CancellationToken)); + CancellationToken cancellationToken = (CancellationToken)context.BindingContext.GetRequiredService(typeof(CancellationToken)); using var loggerFactory = Logger.ConfigureLogger(hidiOptions.LogLevel); var logger = loggerFactory.CreateLogger(); try { + if (hidiOptions.OpenApi is null) throw new InvalidOperationException("OpenApi file is required"); await OpenApiService.ValidateOpenApiDocument(hidiOptions.OpenApi, logger, cancellationToken); return 0; } diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index fd0d9325e..7e8c8937c 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -3,8 +3,10 @@ Exe net7.0 - 9.0 + latest + true true + enable http://go.microsoft.com/fwlink/?LinkID=288890 https://github.com/Microsoft/OpenAPI.NET MIT @@ -26,6 +28,9 @@ true true + NU5048 + true + readme.md @@ -62,4 +67,8 @@ + + + + diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index 9797ecd65..71a0ff2f7 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -23,6 +23,7 @@ using Microsoft.OpenApi.ApiManifest; using Microsoft.OpenApi.ApiManifest.OpenAI; using Microsoft.OpenApi.Extensions; +using Microsoft.OpenApi.Hidi.Extensions; using Microsoft.OpenApi.Hidi.Formatters; using Microsoft.OpenApi.Hidi.Options; using Microsoft.OpenApi.Hidi.Utilities; @@ -69,20 +70,18 @@ public static async Task TransformOpenApiDocument(HidiOptions options, ILogger l OpenApiSpecVersion openApiVersion = options.Version != null ? TryParseOpenApiSpecVersion(options.Version) : OpenApiSpecVersion.OpenApi3_0; // If ApiManifest is provided, set the referenced OpenAPI document - var apiDependency = await FindApiDependency(options.FilterOptions?.FilterByApiManifest, logger, cancellationToken); + var apiDependency = await FindApiDependency(options.FilterOptions.FilterByApiManifest, logger, cancellationToken); if (apiDependency != null) { options.OpenApi = apiDependency.ApiDescripionUrl; } // If Postman Collection is provided, load it - JsonDocument postmanCollection = null; - if (!String.IsNullOrEmpty(options.FilterOptions?.FilterByCollection)) + JsonDocument? postmanCollection = null; + if (!string.IsNullOrEmpty(options.FilterOptions?.FilterByCollection)) { - using (var collectionStream = await GetStream(options.FilterOptions.FilterByCollection, logger, cancellationToken)) - { - postmanCollection = JsonDocument.Parse(collectionStream); - } + using var collectionStream = await GetStream(options.FilterOptions.FilterByCollection, logger, cancellationToken); + postmanCollection = JsonDocument.Parse(collectionStream); } // Load OpenAPI document @@ -94,7 +93,7 @@ public static async Task TransformOpenApiDocument(HidiOptions options, ILogger l } var languageFormat = options.SettingsConfig?.GetSection("LanguageFormat")?.Value; - if (Extensions.StringExtensions.IsEquals(languageFormat, "PowerShell")) + if ("PowerShell".IsEquals(languageFormat)) { // PowerShell Walker. var powerShellFormatter = new PowerShellFormatter(); @@ -117,16 +116,16 @@ public static async Task TransformOpenApiDocument(HidiOptions options, ILogger l } } - private static async Task FindApiDependency(string apiManifestPath, ILogger logger, CancellationToken cancellationToken) + private static async Task FindApiDependency(string? apiManifestPath, ILogger logger, CancellationToken cancellationToken) { - ApiDependency apiDependency = null; + ApiDependency? apiDependency = null; // If API Manifest is provided, load it, use it get the OpenAPI path - ApiManifestDocument apiManifest = null; + ApiManifestDocument? apiManifest = null; if (!string.IsNullOrEmpty(apiManifestPath)) { // Extract fragment identifier if passed as the name of the ApiDependency var apiManifestRef = apiManifestPath.Split('#'); - string apiDependencyName = null; + var apiDependencyName = string.Empty; if (apiManifestRef.Length > 1) { apiDependencyName = apiManifestRef[1]; @@ -136,15 +135,15 @@ private static async Task FindApiDependency(string apiManifestPat apiManifest = ApiManifestDocument.Load(JsonDocument.Parse(fileStream).RootElement); } - apiDependency = apiDependencyName != null ? apiManifest.ApiDependencies[apiDependencyName] : apiManifest.ApiDependencies.First().Value; + apiDependency = !string.IsNullOrEmpty(apiDependencyName) && apiManifest.ApiDependencies.TryGetValue(apiDependencyName, out var dependency) ? dependency : apiManifest.ApiDependencies.First().Value; } return apiDependency; } - private static OpenApiDocument ApplyFilters(HidiOptions options, ILogger logger, ApiDependency apiDependency, JsonDocument postmanCollection, OpenApiDocument document) + private static OpenApiDocument ApplyFilters(HidiOptions options, ILogger logger, ApiDependency? apiDependency, JsonDocument? postmanCollection, OpenApiDocument document) { - Dictionary> requestUrls = null; + Dictionary> requestUrls; if (apiDependency != null) { requestUrls = GetRequestUrlsFromManifest(apiDependency); @@ -154,6 +153,11 @@ private static OpenApiDocument ApplyFilters(HidiOptions options, ILogger logger, requestUrls = EnumerateJsonDocument(postmanCollection.RootElement, new()); logger.LogTrace("Finished fetching the list of paths and Http methods defined in the Postman collection."); } + else + { + requestUrls = new(); + logger.LogTrace("No filter options provided."); + } logger.LogTrace("Creating predicate from filter options."); var predicate = FilterOpenApiDocument(options.FilterOptions.FilterByOperationIds, @@ -177,6 +181,7 @@ private static void WriteOpenApi(HidiOptions options, OpenApiFormat openApiForma { using (logger.BeginScope("Output")) { + if (options.Output is null) throw new InvalidOperationException("Output file path is null"); using var outputStream = options.Output.Create(); var textWriter = new StreamWriter(outputStream); @@ -206,7 +211,7 @@ private static void WriteOpenApi(HidiOptions options, OpenApiFormat openApiForma } // Get OpenAPI document either from OpenAPI or CSDL - private static async Task GetOpenApi(HidiOptions options, ILogger logger, CancellationToken cancellationToken, string metadataVersion = null) + private static async Task GetOpenApi(HidiOptions options, ILogger logger, CancellationToken cancellationToken, string? metadataVersion = null) { OpenApiDocument document; @@ -219,14 +224,13 @@ private static async Task GetOpenApi(HidiOptions options, ILogg { stopwatch.Start(); stream = await GetStream(options.Csdl, logger, cancellationToken); - Stream filteredStream = null; + Stream? filteredStream = null; if (!string.IsNullOrEmpty(options.CsdlFilter)) { XslCompiledTransform transform = GetFilterTransform(); filteredStream = ApplyFilterToCsdl(stream, options.CsdlFilter, transform); filteredStream.Position = 0; stream.Dispose(); - stream = null; } document = await ConvertCsdlToOpenApi(filteredStream ?? stream, metadataVersion, options.SettingsConfig, cancellationToken); @@ -234,40 +238,41 @@ private static async Task GetOpenApi(HidiOptions options, ILogg logger.LogTrace("{timestamp}ms: Generated OpenAPI with {paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths.Count); } } - else + else if (!string.IsNullOrEmpty(options.OpenApi)) { stream = await GetStream(options.OpenApi, logger, cancellationToken); var result = await ParseOpenApi(options.OpenApi, options.InlineExternal, logger, stream, cancellationToken); document = result.OpenApiDocument; } + else throw new InvalidOperationException("No input file path or URL provided"); return document; } - private static Func FilterOpenApiDocument(string filterbyoperationids, string filterbytags, Dictionary> requestUrls, OpenApiDocument document, ILogger logger) + private static Func? FilterOpenApiDocument(string? filterByOperationIds, string? filterByTags, Dictionary> requestUrls, OpenApiDocument document, ILogger logger) { - Func predicate = null; + Func? predicate = null; using (logger.BeginScope("Create Filter")) { // Check if filter options are provided, then slice the OpenAPI document - if (!string.IsNullOrEmpty(filterbyoperationids) && !string.IsNullOrEmpty(filterbytags)) + if (!string.IsNullOrEmpty(filterByOperationIds) && !string.IsNullOrEmpty(filterByTags)) { throw new InvalidOperationException("Cannot filter by operationIds and tags at the same time."); } - if (!string.IsNullOrEmpty(filterbyoperationids)) + if (!string.IsNullOrEmpty(filterByOperationIds)) { logger.LogTrace("Creating predicate based on the operationIds supplied."); - predicate = OpenApiFilterService.CreatePredicate(tags: filterbyoperationids); + predicate = OpenApiFilterService.CreatePredicate(tags: filterByOperationIds); } - if (!string.IsNullOrEmpty(filterbytags)) + if (!string.IsNullOrEmpty(filterByTags)) { logger.LogTrace("Creating predicate based on the tags supplied."); - predicate = OpenApiFilterService.CreatePredicate(tags: filterbytags); + predicate = OpenApiFilterService.CreatePredicate(tags: filterByTags); } - if (requestUrls != null) + if (requestUrls.Any()) { logger.LogTrace("Creating predicate based on the paths and Http methods defined in the Postman collection."); predicate = OpenApiFilterService.CreatePredicate(requestUrls: requestUrls, source: document); @@ -281,13 +286,13 @@ private static Dictionary> GetRequestUrlsFromManifest(ApiDe { // Get the request URLs from the API Dependencies in the API manifest var requests = apiDependency - .Requests.Where(static r => !r.Exclude) - .Select(static r => new { UriTemplate = r.UriTemplate, Method = r.Method }) + .Requests.Where(static r => !r.Exclude && !string.IsNullOrEmpty(r.UriTemplate) && !string.IsNullOrEmpty(r.Method)) + .Select(static r => new { UriTemplate = r.UriTemplate!, Method = r.Method! }) .GroupBy(static r => r.UriTemplate) .ToDictionary(static g => g.Key, static g => g.Select(static r => r.Method).ToList()); // This makes the assumption that the UriTemplate in the ApiManifest matches exactly the UriTemplate in the OpenAPI document // This does not need to be the case. The URI template in the API manifest could map to a set of OpenAPI paths. - // Additional logic will be required to handle this scenario. I sugggest we build this into the OpenAPI.Net library at some point. + // Additional logic will be required to handle this scenario. I suggest we build this into the OpenAPI.Net library at some point. return requests; } @@ -295,7 +300,7 @@ private static XslCompiledTransform GetFilterTransform() { XslCompiledTransform transform = new(); Assembly assembly = typeof(OpenApiService).GetTypeInfo().Assembly; - Stream xslt = assembly.GetManifestResourceStream("Microsoft.OpenApi.Hidi.CsdlFilter.xslt"); + using var xslt = assembly.GetManifestResourceStream("Microsoft.OpenApi.Hidi.CsdlFilter.xslt") ?? throw new InvalidOperationException("Could not find the Microsoft.OpenApi.Hidi.CsdlFilter.xslt file in the assembly. Check build configuration."); transform.Load(new XmlTextReader(new StreamReader(xslt))); return transform; } @@ -318,20 +323,20 @@ private static Stream ApplyFilterToCsdl(Stream csdlStream, string entitySetOrSin /// Implementation of the validate command /// public static async Task ValidateOpenApiDocument( - string openapi, + string openApi, ILogger logger, CancellationToken cancellationToken) { - if (string.IsNullOrEmpty(openapi)) + if (string.IsNullOrEmpty(openApi)) { - throw new ArgumentNullException(nameof(openapi)); + throw new ArgumentNullException(nameof(openApi)); } try { - using var stream = await GetStream(openapi, logger, cancellationToken); + using var stream = await GetStream(openApi, logger, cancellationToken); - var result = await ParseOpenApi(openapi, false, logger, stream, cancellationToken); + var result = await ParseOpenApi(openApi, false, logger, stream, cancellationToken); using (logger.BeginScope("Calculating statistics")) { @@ -384,7 +389,7 @@ private static async Task ParseOpenApi(string openApiFile, bool inli /// /// The CSDL stream. /// An OpenAPI document. - public static async Task ConvertCsdlToOpenApi(Stream csdl, string metadataVersion = null, IConfiguration settings = null, CancellationToken token = default) + public static async Task ConvertCsdlToOpenApi(Stream csdl, string? metadataVersion = null, IConfiguration? settings = null, CancellationToken token = default) { using var reader = new StreamReader(csdl); var csdlText = await reader.ReadToEndAsync(token); @@ -535,9 +540,9 @@ private static OpenApiFormat GetOpenApiFormat(string input, ILogger logger) return !input.StartsWith("http") && Path.GetExtension(input) == ".json" ? OpenApiFormat.Json : OpenApiFormat.Yaml; } - private static string GetInputPathExtension(string openapi = null, string csdl = null) + private static string GetInputPathExtension(string? openapi = null, string? csdl = null) { - var extension = String.Empty; + var extension = string.Empty; if (!string.IsNullOrEmpty(openapi)) { extension = Path.GetExtension(openapi); @@ -550,7 +555,7 @@ private static string GetInputPathExtension(string openapi = null, string csdl = return extension; } - internal static async Task ShowOpenApiDocument(HidiOptions options, ILogger logger, CancellationToken cancellationToken) + internal static async Task ShowOpenApiDocument(HidiOptions options, ILogger logger, CancellationToken cancellationToken) { try { @@ -564,6 +569,11 @@ internal static async Task ShowOpenApiDocument(HidiOptions options, ILog using (logger.BeginScope("Creating diagram")) { // If output is null, create a HTML file in the user's temporary directory + var sourceUrl = (string.IsNullOrEmpty(options.OpenApi), string.IsNullOrEmpty(options.Csdl)) switch { + (false, _) => options.OpenApi!, + (_, false) => options.Csdl!, + _ => throw new InvalidOperationException("No input file path or URL provided") + }; if (options.Output == null) { var tempPath = Path.GetTempPath() + "/hidi/"; @@ -578,7 +588,7 @@ internal static async Task ShowOpenApiDocument(HidiOptions options, ILog using (var file = new FileStream(output.FullName, FileMode.Create)) { using var writer = new StreamWriter(file); - WriteTreeDocumentAsHtml(options.OpenApi ?? options.Csdl, document, writer); + WriteTreeDocumentAsHtml(sourceUrl, document, writer); } logger.LogTrace("Created Html document with diagram "); @@ -595,7 +605,7 @@ internal static async Task ShowOpenApiDocument(HidiOptions options, ILog using (var file = new FileStream(options.Output.FullName, FileMode.Create)) { using var writer = new StreamWriter(file); - WriteTreeDocumentAsMarkdown(options.OpenApi ?? options.Csdl, document, writer); + WriteTreeDocumentAsMarkdown(sourceUrl, document, writer); } logger.LogTrace("Created markdown document with diagram "); return options.Output.FullName; diff --git a/src/Microsoft.OpenApi.Hidi/Options/FilterOptions.cs b/src/Microsoft.OpenApi.Hidi/Options/FilterOptions.cs index ffdb568de..d82a064f7 100644 --- a/src/Microsoft.OpenApi.Hidi/Options/FilterOptions.cs +++ b/src/Microsoft.OpenApi.Hidi/Options/FilterOptions.cs @@ -5,9 +5,9 @@ namespace Microsoft.OpenApi.Hidi.Options { internal class FilterOptions { - public string FilterByOperationIds { get; internal set; } - public string FilterByTags { get; internal set; } - public string FilterByCollection { get; internal set; } - public string FilterByApiManifest { get; internal set; } + public string? FilterByOperationIds { get; internal set; } + public string? FilterByTags { get; internal set; } + public string? FilterByCollection { get; internal set; } + public string? FilterByApiManifest { get; internal set; } } } diff --git a/src/Microsoft.OpenApi.Hidi/Options/HidiOptions.cs b/src/Microsoft.OpenApi.Hidi/Options/HidiOptions.cs index a7f16d872..9f5a109f7 100644 --- a/src/Microsoft.OpenApi.Hidi/Options/HidiOptions.cs +++ b/src/Microsoft.OpenApi.Hidi/Options/HidiOptions.cs @@ -11,21 +11,22 @@ namespace Microsoft.OpenApi.Hidi.Options { internal class HidiOptions { - public string OpenApi { get; set; } - public string Csdl { get; set; } - public string CsdlFilter { get; set; } - public FileInfo Output { get; set; } - public string OutputFolder { get; set; } + private const string defaultOutputFolderValue = "./"; + public string? OpenApi { get; set; } + public string? Csdl { get; set; } + public string? CsdlFilter { get; set; } + public FileInfo? Output { get; set; } + public string OutputFolder { get; set; } = defaultOutputFolderValue; public bool CleanOutput { get; set; } - public string Version { get; set; } - public string MetadataVersion { get; set; } + public string? Version { get; set; } + public string? MetadataVersion { get; set; } public OpenApiFormat? OpenApiFormat { get; set; } public bool TerseOutput { get; set; } - public IConfiguration SettingsConfig { get; set; } + public IConfiguration? SettingsConfig { get; set; } public LogLevel LogLevel { get; set; } public bool InlineLocal { get; set; } public bool InlineExternal { get; set; } - public FilterOptions FilterOptions { get; set; } + public FilterOptions FilterOptions { get; set; } = new(); public HidiOptions(ParseResult parseResult, CommandOptions options) { @@ -43,13 +44,13 @@ private void ParseHidiOptions(ParseResult parseResult, CommandOptions options) CsdlFilter = parseResult.GetValueForOption(options.CsdlFilterOption); Csdl = parseResult.GetValueForOption(options.CsdlOption); Output = parseResult.GetValueForOption(options.OutputOption); - OutputFolder = parseResult.GetValueForOption(options.OutputFolderOption); + OutputFolder = parseResult.GetValueForOption(options.OutputFolderOption) is string outputFolderOptionValue && !string.IsNullOrEmpty(outputFolderOptionValue) ? outputFolderOptionValue : defaultOutputFolderValue; CleanOutput = parseResult.GetValueForOption(options.CleanOutputOption); Version = parseResult.GetValueForOption(options.VersionOption); MetadataVersion = parseResult.GetValueForOption(options.MetadataVersionOption); OpenApiFormat = parseResult.GetValueForOption(options.FormatOption); TerseOutput = parseResult.GetValueForOption(options.TerseOutputOption); - SettingsConfig = SettingsUtilities.GetConfiguration(parseResult.GetValueForOption(options.SettingsFileOption)); + SettingsConfig = parseResult.GetValueForOption(options.SettingsFileOption) is string configOptionValue && !string.IsNullOrEmpty(configOptionValue) ? SettingsUtilities.GetConfiguration(configOptionValue) : null; LogLevel = parseResult.GetValueForOption(options.LogLevelOption); InlineLocal = parseResult.GetValueForOption(options.InlineLocalOption); InlineExternal = parseResult.GetValueForOption(options.InlineExternalOption); diff --git a/src/Microsoft.OpenApi.Hidi/Utilities/SettingsUtilities.cs b/src/Microsoft.OpenApi.Hidi/Utilities/SettingsUtilities.cs index 6e00e2ba3..1d261e5f3 100644 --- a/src/Microsoft.OpenApi.Hidi/Utilities/SettingsUtilities.cs +++ b/src/Microsoft.OpenApi.Hidi/Utilities/SettingsUtilities.cs @@ -8,9 +8,10 @@ namespace Microsoft.OpenApi.Hidi.Utilities { internal static class SettingsUtilities { - internal static IConfiguration GetConfiguration(string settingsFile = null) + internal static IConfiguration GetConfiguration(string? settingsFile = null) { - settingsFile ??= "appsettings.json"; + if (string.IsNullOrEmpty(settingsFile)) + settingsFile = "appsettings.json"; IConfiguration config = new ConfigurationBuilder() .AddJsonFile(settingsFile, true) @@ -19,7 +20,7 @@ internal static IConfiguration GetConfiguration(string settingsFile = null) return config; } - internal static OpenApiConvertSettings GetOpenApiConvertSettings(IConfiguration config, string metadataVersion = null) + internal static OpenApiConvertSettings GetOpenApiConvertSettings(IConfiguration config, string? metadataVersion = null) { if (config == null) { throw new System.ArgumentNullException(nameof(config)); } var settings = new OpenApiConvertSettings(); diff --git a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj index 4f6b336f9..609b16a09 100644 --- a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj +++ b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj @@ -22,6 +22,9 @@ true true + NU5048 + true + README.md @@ -61,4 +64,8 @@ SRResource.Designer.cs + + + + \ No newline at end of file diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiExtensibleExtensions.cs b/src/Microsoft.OpenApi/Extensions/OpenApiExtensibleExtensions.cs index aee0d44a5..7656aad89 100644 --- a/src/Microsoft.OpenApi/Extensions/OpenApiExtensibleExtensions.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiExtensibleExtensions.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Exceptions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; @@ -10,7 +9,7 @@ namespace Microsoft.OpenApi.Extensions { /// - /// Extension methods to verify validatity and add an extension to Extensions property. + /// Extension methods to verify validity and add an extension to Extensions property. /// public static class OpenApiExtensibleExtensions { diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj index d7220bf6f..739d34354 100644 --- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj +++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj @@ -22,6 +22,9 @@ true true + NU5048 + true + README.md @@ -48,4 +51,8 @@ SRResource.Designer.cs + + + + diff --git a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs index 2efd0c747..06e5749e6 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs @@ -16,6 +16,9 @@ namespace Microsoft.OpenApi.Models public class OpenApiParameter : IOpenApiSerializable, IOpenApiReferenceable, IEffective, IOpenApiExtensible { private bool? _explode; + /// + /// The style of the parameter. + /// public ParameterStyle? _style; /// diff --git a/src/Microsoft.OpenApi/Writers/OpenApiWriterSettings.cs b/src/Microsoft.OpenApi/Writers/OpenApiWriterSettings.cs index cf00c1339..06fcd0246 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiWriterSettings.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiWriterSettings.cs @@ -31,6 +31,7 @@ public enum ReferenceInlineSetting /// public class OpenApiWriterSettings { + [Obsolete("Use InlineLocalReference and InlineExternalReference settings instead")] private ReferenceInlineSetting referenceInline = ReferenceInlineSetting.DoNotInlineReferences; internal LoopDetector LoopDetector { get; } = new LoopDetector(); diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs index 3c039b9aa..34cdd3a0a 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs @@ -183,7 +183,7 @@ public void ReturnsPathParametersOnSlicingBasedOnOperationIdsOrTags(string opera foreach (var pathItem in subsetOpenApiDocument.Paths) { Assert.True(pathItem.Value.Parameters.Any()); - Assert.Equal(1, pathItem.Value.Parameters.Count); + Assert.Single(pathItem.Value.Parameters); } } } diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs index 49f1bbd96..647cac321 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs @@ -228,7 +228,7 @@ public async Task TransformCommandConvertsOpenApi() [Fact] - public async Task TransformCommandConvertsOpenApiWithDefaultOutputname() + public async Task TransformCommandConvertsOpenApiWithDefaultOutputName() { HidiOptions options = new HidiOptions { @@ -246,7 +246,7 @@ public async Task TransformCommandConvertsOpenApiWithDefaultOutputname() } [Fact] - public async Task TransformCommandConvertsCsdlWithDefaultOutputname() + public async Task TransformCommandConvertsCsdlWithDefaultOutputName() { HidiOptions options = new HidiOptions { @@ -264,7 +264,7 @@ public async Task TransformCommandConvertsCsdlWithDefaultOutputname() } [Fact] - public async Task TransformCommandConvertsOpenApiWithDefaultOutputnameAndSwitchFormat() + public async Task TransformCommandConvertsOpenApiWithDefaultOutputNameAndSwitchFormat() { HidiOptions options = new HidiOptions { @@ -367,10 +367,12 @@ public void InvokePluginCommand() using var jsDoc = JsonDocument.Parse(File.ReadAllText("ai-plugin.json")); var openAiManifest = OpenAIPluginManifest.Load(jsDoc.RootElement); - - Assert.Equal("Mastodon - Subset", openAiManifest?.NameForHuman); - Assert.Equal("openapi", openAiManifest?.Api.Type); - Assert.Equal("./openapi.json", openAiManifest?.Api.Url); + + Assert.NotNull(openAiManifest); + Assert.Equal("Mastodon - Subset", openAiManifest.NameForHuman); + Assert.NotNull(openAiManifest.Api); + Assert.Equal("openapi", openAiManifest.Api.Type); + Assert.Equal("./openapi.json", openAiManifest.Api.Url); } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiServerTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiServerTests.cs index 1b917fde7..bf0fe7b78 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiServerTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiServerTests.cs @@ -1,11 +1,7 @@ using FluentAssertions; -using Microsoft.OpenApi.Exceptions; using Microsoft.OpenApi.Models; using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using Xunit; namespace Microsoft.OpenApi.Readers.Tests.V2Tests @@ -49,7 +45,7 @@ public void JustSchemeNoDefault() var doc = reader.Read(input, out var diagnostic); - Assert.Equal(0, doc.Servers.Count); + Assert.Empty(doc.Servers); } [Fact] @@ -67,10 +63,10 @@ public void JustHostNoDefault() { }); - var doc = reader.Read(input, out var diagnostic); + var doc = reader.Read(input, out var _); var server = doc.Servers.First(); - Assert.Equal(1, doc.Servers.Count); + Assert.Single(doc.Servers); Assert.Equal("//www.foo.com", server.Url); } @@ -95,7 +91,7 @@ public void NoBasePath() var doc = reader.Read(input, out var diagnostic); var server = doc.Servers.First(); - Assert.Equal(1, doc.Servers.Count); + Assert.Single(doc.Servers); Assert.Equal("http://www.foo.com", server.Url); } @@ -117,7 +113,7 @@ public void JustBasePathNoDefault() var doc = reader.Read(input, out var diagnostic); var server = doc.Servers.First(); - Assert.Equal(1, doc.Servers.Count); + Assert.Single(doc.Servers); Assert.Equal("/baz", server.Url); } @@ -141,7 +137,7 @@ public void JustSchemeWithCustomHost() var doc = reader.Read(input, out var diagnostic); var server = doc.Servers.First(); - Assert.Equal(1, doc.Servers.Count); + Assert.Single(doc.Servers); Assert.Equal("http://bing.com/foo", server.Url); } @@ -165,7 +161,7 @@ public void JustSchemeWithCustomHostWithEmptyPath() var doc = reader.Read(input, out var diagnostic); var server = doc.Servers.First(); - Assert.Equal(1, doc.Servers.Count); + Assert.Single(doc.Servers); Assert.Equal("http://bing.com", server.Url); } @@ -188,7 +184,7 @@ public void JustBasePathWithCustomHost() var doc = reader.Read(input, out var diagnostic); var server = doc.Servers.First(); - Assert.Equal(1, doc.Servers.Count); + Assert.Single(doc.Servers); Assert.Equal("https://bing.com/api", server.Url); } @@ -211,7 +207,7 @@ public void JustHostWithCustomHost() var doc = reader.Read(input, out var diagnostic); var server = doc.Servers.First(); - Assert.Equal(1, doc.Servers.Count); + Assert.Single(doc.Servers); Assert.Equal("https://www.example.com", server.Url); } @@ -231,10 +227,10 @@ public void JustHostWithCustomHostWithApi() BaseUrl = new Uri("https://dev.bing.com/api/description.yaml") }); - var doc = reader.Read(input, out var diagnostic); + var doc = reader.Read(input, out var _); var server = doc.Servers.First(); - Assert.Equal(1, doc.Servers.Count); + Assert.Single(doc.Servers); Assert.Equal("https://prod.bing.com", server.Url); } @@ -283,7 +279,7 @@ public void LocalHostWithCustomHost() var doc = reader.Read(input, out var diagnostic); var server = doc.Servers.First(); - Assert.Equal(1, doc.Servers.Count); + Assert.Single(doc.Servers); Assert.Equal("https://localhost:23232", server.Url); } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs index 2a0dd0039..9d84ab63d 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs @@ -495,7 +495,7 @@ public void CloningSchemaExtensionsWorks() // Act && Assert var schemaCopy = new OpenApiSchema(schema); - Assert.Equal(1, schemaCopy.Extensions.Count); + Assert.Single(schemaCopy.Extensions); // Act && Assert schemaCopy.Extensions = new Dictionary diff --git a/test/Microsoft.OpenApi.Tests/Services/OpenApiUrlTreeNodeTests.cs b/test/Microsoft.OpenApi.Tests/Services/OpenApiUrlTreeNodeTests.cs index d251c99c1..cf9f0b0c6 100644 --- a/test/Microsoft.OpenApi.Tests/Services/OpenApiUrlTreeNodeTests.cs +++ b/test/Microsoft.OpenApi.Tests/Services/OpenApiUrlTreeNodeTests.cs @@ -78,7 +78,7 @@ public void CreateSingleRootWorks() Assert.NotNull(rootNode); Assert.NotNull(rootNode.PathItems); Assert.False(rootNode.HasOperations(label)); - Assert.Equal(0, rootNode.Children.Count); + Assert.Empty(rootNode.Children); } [Fact] @@ -97,7 +97,7 @@ public void CreatePathWithoutRootWorks() Assert.NotNull(rootNode); Assert.NotNull(rootNode.PathItems); - Assert.Equal(1, rootNode.Children.Count); + Assert.Single(rootNode.Children); Assert.Equal("houses", rootNode.Children["houses"].Segment); Assert.NotNull(rootNode.Children["houses"].PathItems); Assert.False(rootNode.Children["houses"].HasOperations("cabin")); @@ -339,7 +339,7 @@ public void SegmentIsParameterWorks() var rootNode = OpenApiUrlTreeNode.Create(doc, label); Assert.NotNull(rootNode); - Assert.Equal(1, rootNode.Children.Count); + Assert.Single(rootNode.Children); Assert.NotNull(rootNode.Children["houses"].Children["apartments"].Children["{apartment-id}"].PathItems); Assert.True(rootNode.Children["houses"].Children["apartments"].Children["{apartment-id}"].IsParameter); Assert.Equal("{apartment-id}", rootNode.Children["houses"].Children["apartments"].Children["{apartment-id}"].Segment); From 104f5f58e80011b6fb16f120c9c12b60781ef222 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 14 Sep 2023 16:00:22 -0400 Subject: [PATCH 07/24] - enables all mode analysis Signed-off-by: Vincent Biret --- .vscode/settings.json | 1 + .../Formatters/PowerShellFormatter.cs | 4 +- .../Handlers/PluginCommandHandler.cs | 2 +- .../Handlers/ShowCommandHandler.cs | 2 +- .../Handlers/TransformCommandHandler.cs | 2 +- .../Handlers/ValidateCommandHandler.cs | 2 +- src/Microsoft.OpenApi.Hidi/Logger.cs | 2 +- .../Microsoft.OpenApi.Hidi.csproj | 3 +- src/Microsoft.OpenApi.Hidi/OpenApiService.cs | 88 +++++++++---------- src/Microsoft.OpenApi.Hidi/Program.cs | 2 +- src/Microsoft.OpenApi.Hidi/StatsVisitor.cs | 18 ++-- .../Microsoft.OpenApi.Hidi.Tests.csproj | 3 + .../Services/OpenApiServiceTests.cs | 24 +++-- 13 files changed, 81 insertions(+), 72 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index ec27390f9..186b10bea 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,6 +5,7 @@ "titleBar.activeForeground": "#F0FCFE" }, "cSpell.words": [ + "csdl", "Hidi" ] } \ No newline at end of file diff --git a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs index f876e4008..450a05d21 100644 --- a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs +++ b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs @@ -88,7 +88,7 @@ public override void Visit(OpenApiOperation operation) private static string ResolveVerbSegmentInOpertationId(string operationId) { var charPos = operationId.LastIndexOf('.', operationId.Length - 1); - if (operationId.Contains('_') || charPos < 0) + if (operationId.Contains('_', StringComparison.OrdinalIgnoreCase) || charPos < 0) return operationId; var newOperationId = new StringBuilder(operationId); newOperationId[charPos] = '_'; @@ -99,7 +99,7 @@ private static string ResolveVerbSegmentInOpertationId(string operationId) private static string ResolvePutOperationId(string operationId) { return operationId.Contains(DefaultPutPrefix, StringComparison.OrdinalIgnoreCase) ? - operationId.Replace(DefaultPutPrefix, PowerShellPutPrefix) : operationId; + operationId.Replace(DefaultPutPrefix, PowerShellPutPrefix, StringComparison.Ordinal) : operationId; } private static string ResolveByRefOperationId(string operationId) diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/PluginCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/PluginCommandHandler.cs index ae090207c..0fcb86df2 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/PluginCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/PluginCommandHandler.cs @@ -31,7 +31,7 @@ public async Task InvokeAsync(InvocationContext context) var logger = loggerFactory.CreateLogger(); try { - await OpenApiService.PluginManifest(hidiOptions, logger, cancellationToken); + await OpenApiService.PluginManifest(hidiOptions, logger, cancellationToken).ConfigureAwait(false); return 0; } diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/ShowCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/ShowCommandHandler.cs index 7db17fea9..a6a161dc2 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/ShowCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/ShowCommandHandler.cs @@ -31,7 +31,7 @@ public async Task InvokeAsync(InvocationContext context) var logger = loggerFactory.CreateLogger(); try { - await OpenApiService.ShowOpenApiDocument(hidiOptions, logger, cancellationToken); + await OpenApiService.ShowOpenApiDocument(hidiOptions, logger, cancellationToken).ConfigureAwait(false); return 0; } diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs index 440c20e0b..f173024cc 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs @@ -31,7 +31,7 @@ public async Task InvokeAsync(InvocationContext context) var logger = loggerFactory.CreateLogger(); try { - await OpenApiService.TransformOpenApiDocument(hidiOptions, logger, cancellationToken); + await OpenApiService.TransformOpenApiDocument(hidiOptions, logger, cancellationToken).ConfigureAwait(false); return 0; } diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs index 8bb5676bc..153ec707e 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs @@ -33,7 +33,7 @@ public async Task InvokeAsync(InvocationContext context) try { if (hidiOptions.OpenApi is null) throw new InvalidOperationException("OpenApi file is required"); - await OpenApiService.ValidateOpenApiDocument(hidiOptions.OpenApi, logger, cancellationToken); + await OpenApiService.ValidateOpenApiDocument(hidiOptions.OpenApi, logger, cancellationToken).ConfigureAwait(false); return 0; } catch (Exception ex) diff --git a/src/Microsoft.OpenApi.Hidi/Logger.cs b/src/Microsoft.OpenApi.Hidi/Logger.cs index 2b02e9600..717ca1a41 100644 --- a/src/Microsoft.OpenApi.Hidi/Logger.cs +++ b/src/Microsoft.OpenApi.Hidi/Logger.cs @@ -5,7 +5,7 @@ namespace Microsoft.OpenApi.Hidi { - public class Logger + public static class Logger { public static ILoggerFactory ConfigureLogger(LogLevel logLevel) { diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 7e8c8937c..b02f89003 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -28,9 +28,10 @@ true true - NU5048 + NU5048;CA1848; true readme.md + All diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index 71a0ff2f7..809e3ecf9 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -70,7 +70,7 @@ public static async Task TransformOpenApiDocument(HidiOptions options, ILogger l OpenApiSpecVersion openApiVersion = options.Version != null ? TryParseOpenApiSpecVersion(options.Version) : OpenApiSpecVersion.OpenApi3_0; // If ApiManifest is provided, set the referenced OpenAPI document - var apiDependency = await FindApiDependency(options.FilterOptions.FilterByApiManifest, logger, cancellationToken); + var apiDependency = await FindApiDependency(options.FilterOptions.FilterByApiManifest, logger, cancellationToken).ConfigureAwait(false); if (apiDependency != null) { options.OpenApi = apiDependency.ApiDescripionUrl; @@ -80,12 +80,12 @@ public static async Task TransformOpenApiDocument(HidiOptions options, ILogger l JsonDocument? postmanCollection = null; if (!string.IsNullOrEmpty(options.FilterOptions?.FilterByCollection)) { - using var collectionStream = await GetStream(options.FilterOptions.FilterByCollection, logger, cancellationToken); + using var collectionStream = await GetStream(options.FilterOptions.FilterByCollection, logger, cancellationToken).ConfigureAwait(false); postmanCollection = JsonDocument.Parse(collectionStream); } // Load OpenAPI document - OpenApiDocument document = await GetOpenApi(options, logger, cancellationToken, options.MetadataVersion); + OpenApiDocument document = await GetOpenApi(options, logger, cancellationToken, options.MetadataVersion).ConfigureAwait(false); if (options.FilterOptions != null) { @@ -104,7 +104,7 @@ public static async Task TransformOpenApiDocument(HidiOptions options, ILogger l } catch (TaskCanceledException) { - Console.Error.WriteLine("CTRL+C pressed, aborting the operation."); + await Console.Error.WriteLineAsync("CTRL+C pressed, aborting the operation.").ConfigureAwait(false); } catch (IOException) { @@ -130,7 +130,7 @@ public static async Task TransformOpenApiDocument(HidiOptions options, ILogger l { apiDependencyName = apiManifestRef[1]; } - using (var fileStream = await GetStream(apiManifestRef[0], logger, cancellationToken)) + using (var fileStream = await GetStream(apiManifestRef[0], logger, cancellationToken).ConfigureAwait(false)) { apiManifest = ApiManifestDocument.Load(JsonDocument.Parse(fileStream).RootElement); } @@ -171,7 +171,7 @@ private static OpenApiDocument ApplyFilters(HidiOptions options, ILogger logger, stopwatch.Start(); document = OpenApiFilterService.CreateFilteredDocument(document, predicate); stopwatch.Stop(); - logger.LogTrace("{timestamp}ms: Creating filtered OpenApi document with {paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths.Count); + logger.LogTrace("{Timestamp}ms: Creating filtered OpenApi document with {Paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths.Count); } return document; @@ -183,7 +183,7 @@ private static void WriteOpenApi(HidiOptions options, OpenApiFormat openApiForma { if (options.Output is null) throw new InvalidOperationException("Output file path is null"); using var outputStream = options.Output.Create(); - var textWriter = new StreamWriter(outputStream); + using var textWriter = new StreamWriter(outputStream); var settings = new OpenApiWriterSettings() { @@ -205,7 +205,7 @@ private static void WriteOpenApi(HidiOptions options, OpenApiFormat openApiForma document.Serialize(writer, openApiVersion); stopwatch.Stop(); - logger.LogTrace($"Finished serializing in {stopwatch.ElapsedMilliseconds}ms"); + logger.LogTrace("Finished serializing in {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds); textWriter.Flush(); } } @@ -220,28 +220,28 @@ private static async Task GetOpenApi(HidiOptions options, ILogg if (!string.IsNullOrEmpty(options.Csdl)) { var stopwatch = new Stopwatch(); - using (logger.BeginScope("Convert CSDL: {csdl}", options.Csdl)) + using (logger.BeginScope("Convert CSDL: {Csdl}", options.Csdl)) { stopwatch.Start(); - stream = await GetStream(options.Csdl, logger, cancellationToken); + stream = await GetStream(options.Csdl, logger, cancellationToken).ConfigureAwait(false); Stream? filteredStream = null; if (!string.IsNullOrEmpty(options.CsdlFilter)) { XslCompiledTransform transform = GetFilterTransform(); filteredStream = ApplyFilterToCsdl(stream, options.CsdlFilter, transform); filteredStream.Position = 0; - stream.Dispose(); + await stream.DisposeAsync().ConfigureAwait(false); } - document = await ConvertCsdlToOpenApi(filteredStream ?? stream, metadataVersion, options.SettingsConfig, cancellationToken); + document = await ConvertCsdlToOpenApi(filteredStream ?? stream, metadataVersion, options.SettingsConfig, cancellationToken).ConfigureAwait(false); stopwatch.Stop(); - logger.LogTrace("{timestamp}ms: Generated OpenAPI with {paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths.Count); + logger.LogTrace("{Timestamp}ms: Generated OpenAPI with {Paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths.Count); } } else if (!string.IsNullOrEmpty(options.OpenApi)) { - stream = await GetStream(options.OpenApi, logger, cancellationToken); - var result = await ParseOpenApi(options.OpenApi, options.InlineExternal, logger, stream, cancellationToken); + stream = await GetStream(options.OpenApi, logger, cancellationToken).ConfigureAwait(false); + var result = await ParseOpenApi(options.OpenApi, options.InlineExternal, logger, stream, cancellationToken).ConfigureAwait(false); document = result.OpenApiDocument; } else throw new InvalidOperationException("No input file path or URL provided"); @@ -301,22 +301,22 @@ private static XslCompiledTransform GetFilterTransform() XslCompiledTransform transform = new(); Assembly assembly = typeof(OpenApiService).GetTypeInfo().Assembly; using var xslt = assembly.GetManifestResourceStream("Microsoft.OpenApi.Hidi.CsdlFilter.xslt") ?? throw new InvalidOperationException("Could not find the Microsoft.OpenApi.Hidi.CsdlFilter.xslt file in the assembly. Check build configuration."); - transform.Load(new XmlTextReader(new StreamReader(xslt))); + using var streamReader = new StreamReader(xslt); + using var textReader = new XmlTextReader(streamReader); + transform.Load(textReader); return transform; } private static Stream ApplyFilterToCsdl(Stream csdlStream, string entitySetOrSingleton, XslCompiledTransform transform) { - Stream stream; using StreamReader inputReader = new(csdlStream, leaveOpen: true); - XmlReader inputXmlReader = XmlReader.Create(inputReader); + using XmlReader inputXmlReader = XmlReader.Create(inputReader); MemoryStream filteredStream = new(); - StreamWriter writer = new(filteredStream); + using StreamWriter writer = new(filteredStream, leaveOpen: true); XsltArgumentList args = new(); args.AddParam("entitySetOrSingleton", "", entitySetOrSingleton); transform.Transform(inputXmlReader, args, writer); - stream = filteredStream; - return stream; + return filteredStream; } /// @@ -334,9 +334,9 @@ public static async Task ValidateOpenApiDocument( try { - using var stream = await GetStream(openApi, logger, cancellationToken); + using var stream = await GetStream(openApi, logger, cancellationToken).ConfigureAwait(false); - var result = await ParseOpenApi(openApi, false, logger, stream, cancellationToken); + var result = await ParseOpenApi(openApi, false, logger, stream, cancellationToken).ConfigureAwait(false); using (logger.BeginScope("Calculating statistics")) { @@ -345,12 +345,14 @@ public static async Task ValidateOpenApiDocument( walker.Walk(result.OpenApiDocument); logger.LogTrace("Finished walking through the OpenApi document. Generating a statistics report.."); + #pragma warning disable CA2254 logger.LogInformation(statsVisitor.GetStatisticsReport()); + #pragma warning restore CA2254 } } catch (TaskCanceledException) { - Console.Error.WriteLine("CTRL+C pressed, aborting the operation."); + await Console.Error.WriteLineAsync("CTRL+C pressed, aborting the operation.").ConfigureAwait(false); } catch (Exception ex) { @@ -362,7 +364,7 @@ private static async Task ParseOpenApi(string openApiFile, bool inli { ReadResult result; Stopwatch stopwatch = Stopwatch.StartNew(); - using (logger.BeginScope("Parsing OpenAPI: {openApiFile}", openApiFile)) + using (logger.BeginScope("Parsing OpenAPI: {OpenApiFile}", openApiFile)) { stopwatch.Start(); @@ -373,9 +375,9 @@ private static async Task ParseOpenApi(string openApiFile, bool inli new Uri(openApiFile) : new Uri("file://" + new FileInfo(openApiFile).DirectoryName + Path.DirectorySeparatorChar) } - ).ReadAsync(stream, cancellationToken); + ).ReadAsync(stream, cancellationToken).ConfigureAwait(false); - logger.LogTrace("{timestamp}ms: Completed parsing.", stopwatch.ElapsedMilliseconds); + logger.LogTrace("{Timestamp}ms: Completed parsing.", stopwatch.ElapsedMilliseconds); LogErrors(logger, result); stopwatch.Stop(); @@ -392,7 +394,7 @@ private static async Task ParseOpenApi(string openApiFile, bool inli public static async Task ConvertCsdlToOpenApi(Stream csdl, string? metadataVersion = null, IConfiguration? settings = null, CancellationToken token = default) { using var reader = new StreamReader(csdl); - var csdlText = await reader.ReadToEndAsync(token); + var csdlText = await reader.ReadToEndAsync(token).ConfigureAwait(false); var edmModel = CsdlReader.Parse(XElement.Parse(csdlText).CreateReader()); settings ??= SettingsUtilities.GetConfiguration(); @@ -485,19 +487,15 @@ private static async Task GetStream(string input, ILogger logger, Cancel var stopwatch = new Stopwatch(); stopwatch.Start(); - if (input.StartsWith("http")) + if (input.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { try { - var httpClientHandler = new HttpClientHandler() - { - SslProtocols = System.Security.Authentication.SslProtocols.Tls12, - }; - using var httpClient = new HttpClient(httpClientHandler) + using var httpClient = new HttpClient { DefaultRequestVersion = HttpVersion.Version20 }; - stream = await httpClient.GetStreamAsync(input, cancellationToken); + stream = await httpClient.GetStreamAsync(new Uri(input), cancellationToken).ConfigureAwait(false); } catch (HttpRequestException ex) { @@ -523,7 +521,7 @@ ex is SecurityException || } } stopwatch.Stop(); - logger.LogTrace("{timestamp}ms: Read file {input}", stopwatch.ElapsedMilliseconds, input); + logger.LogTrace("{Timestamp}ms: Read file {Input}", stopwatch.ElapsedMilliseconds, input); } return stream; } @@ -537,7 +535,7 @@ ex is SecurityException || private static OpenApiFormat GetOpenApiFormat(string input, ILogger logger) { logger.LogTrace("Getting the OpenApi format"); - return !input.StartsWith("http") && Path.GetExtension(input) == ".json" ? OpenApiFormat.Json : OpenApiFormat.Yaml; + return !input.StartsWith("http", StringComparison.OrdinalIgnoreCase) && Path.GetExtension(input) == ".json" ? OpenApiFormat.Json : OpenApiFormat.Yaml; } private static string GetInputPathExtension(string? openapi = null, string? csdl = null) @@ -564,7 +562,7 @@ private static string GetInputPathExtension(string? openapi = null, string? csdl throw new ArgumentException("Please input a file path or URL"); } - var document = await GetOpenApi(options, logger, cancellationToken); + var document = await GetOpenApi(options, logger, cancellationToken).ConfigureAwait(false); using (logger.BeginScope("Creating diagram")) { @@ -614,7 +612,7 @@ private static string GetInputPathExtension(string? openapi = null, string? csdl } catch (TaskCanceledException) { - Console.Error.WriteLine("CTRL+C pressed, aborting the operation."); + await Console.Error.WriteLineAsync("CTRL+C pressed, aborting the operation.").ConfigureAwait(false); } catch (Exception ex) { @@ -632,7 +630,7 @@ private static void LogErrors(ILogger logger, ReadResult result) { foreach (var error in context.Errors) { - logger.LogError("Detected error during parsing: {error}", error.ToString()); + logger.LogError("Detected error during parsing: {Error}", error.ToString()); } } } @@ -650,7 +648,7 @@ internal static void WriteTreeDocumentAsMarkdown(string openapiUrl, OpenApiDocum // write a span for each mermaidcolorscheme foreach (var style in OpenApiUrlTreeNode.MermaidNodeStyles) { - writer.WriteLine($"{style.Key.Replace("_", " ")}"); + writer.WriteLine($"{style.Key.Replace("_", " ", StringComparison.OrdinalIgnoreCase)}"); } writer.WriteLine(""); writer.WriteLine(); @@ -683,7 +681,7 @@ internal static void WriteTreeDocumentAsHtml(string sourceUrl, OpenApiDocument d // write a span for each mermaidcolorscheme foreach (var style in OpenApiUrlTreeNode.MermaidNodeStyles) { - writer.WriteLine($"{style.Key.Replace("_", " ")}"); + writer.WriteLine($"{style.Key.Replace("_", " ", StringComparison.OrdinalIgnoreCase)}"); } writer.WriteLine(""); writer.WriteLine("
"); @@ -708,17 +706,17 @@ internal static void WriteTreeDocumentAsHtml(string sourceUrl, OpenApiDocument d writer.WriteLine(" Main(string[] args) var rootCommand = CreateRootCommand(); // Parse the incoming args and invoke the handler - return await rootCommand.InvokeAsync(args); + return await rootCommand.InvokeAsync(args).ConfigureAwait(false); } internal static RootCommand CreateRootCommand() diff --git a/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs b/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs index b05b0de7c..871f88dca 100644 --- a/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs +++ b/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs @@ -10,63 +10,63 @@ namespace Microsoft.OpenApi.Hidi { internal class StatsVisitor : OpenApiVisitorBase { - public int ParameterCount { get; set; } = 0; + public int ParameterCount { get; set; } public override void Visit(OpenApiParameter parameter) { ParameterCount++; } - public int SchemaCount { get; set; } = 0; + public int SchemaCount { get; set; } public override void Visit(OpenApiSchema schema) { SchemaCount++; } - public int HeaderCount { get; set; } = 0; + public int HeaderCount { get; set; } public override void Visit(IDictionary headers) { HeaderCount++; } - public int PathItemCount { get; set; } = 0; + public int PathItemCount { get; set; } public override void Visit(OpenApiPathItem pathItem) { PathItemCount++; } - public int RequestBodyCount { get; set; } = 0; + public int RequestBodyCount { get; set; } public override void Visit(OpenApiRequestBody requestBody) { RequestBodyCount++; } - public int ResponseCount { get; set; } = 0; + public int ResponseCount { get; set; } public override void Visit(OpenApiResponses response) { ResponseCount++; } - public int OperationCount { get; set; } = 0; + public int OperationCount { get; set; } public override void Visit(OpenApiOperation operation) { OperationCount++; } - public int LinkCount { get; set; } = 0; + public int LinkCount { get; set; } public override void Visit(OpenApiLink operation) { LinkCount++; } - public int CallbackCount { get; set; } = 0; + public int CallbackCount { get; set; } public override void Visit(OpenApiCallback callback) { diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj index ebe55934f..4f37314b1 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj +++ b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj @@ -6,6 +6,9 @@ enable false + true + All + CA2007 diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs index 647cac321..b1fcd24d3 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs @@ -17,13 +17,14 @@ namespace Microsoft.OpenApi.Hidi.Tests { - public class OpenApiServiceTests + public sealed class OpenApiServiceTests : IDisposable { private readonly ILogger _logger; + private readonly LoggerFactory _loggerFactory = new(); public OpenApiServiceTests() { - _logger = new Logger(new LoggerFactory()); + _logger = new Logger(_loggerFactory); } [Fact] @@ -105,7 +106,7 @@ public void ShowCommandGeneratesMermaidDiagramAsMarkdown() stream.Position = 0; using var reader = new StreamReader(stream); var output = reader.ReadToEnd(); - Assert.Contains("graph LR", output); + Assert.Contains("graph LR", output, StringComparison.Ordinal); } [Fact] @@ -126,7 +127,7 @@ public void ShowCommandGeneratesMermaidDiagramAsHtml() stream.Position = 0; using var reader = new StreamReader(stream); var output = reader.ReadToEnd(); - Assert.Contains("graph LR", output); + Assert.Contains("graph LR", output, StringComparison.Ordinal); } @@ -144,7 +145,7 @@ public async Task ShowCommandGeneratesMermaidMarkdownFileWithMermaidDiagram() await OpenApiService.ShowOpenApiDocument(options, _logger, new CancellationToken()); var output = File.ReadAllText(options.Output.FullName); - Assert.Contains("graph LR", output); + Assert.Contains("graph LR", output, StringComparison.Ordinal); } [Fact] @@ -172,7 +173,7 @@ public async Task ShowCommandGeneratesMermaidMarkdownFileFromCsdlWithMermaidDiag await OpenApiService.ShowOpenApiDocument(options, _logger, new CancellationToken()); var output = File.ReadAllText(options.Output.FullName); - Assert.Contains("graph LR", output); + Assert.Contains("graph LR", output, StringComparison.Ordinal); } [Fact] @@ -341,8 +342,8 @@ public void InvokeTransformCommand() public void InvokeShowCommand() { var rootCommand = Program.CreateRootCommand(); - var openapi = Path.Combine(".", "UtilityFiles", "SampleOpenApi.yml"); - var args = new string[] { "show", "-d", openapi, "-o", "sample.md" }; + var openApi = Path.Combine(".", "UtilityFiles", "SampleOpenApi.yml"); + var args = new string[] { "show", "-d", openApi, "-o", "sample.md" }; var parseResult = rootCommand.Parse(args); var handler = rootCommand.Subcommands.Where(c => c.Name == "show").First().Handler; var context = new InvocationContext(parseResult); @@ -350,7 +351,7 @@ public void InvokeShowCommand() handler!.Invoke(context); var output = File.ReadAllText("sample.md"); - Assert.Contains("graph LR", output); + Assert.Contains("graph LR", output, StringComparison.Ordinal); } [Fact] @@ -383,5 +384,10 @@ public void CreateRootCommand() var rootCommand = Program.CreateRootCommand(); Assert.NotNull(rootCommand); } + + public void Dispose() + { + _loggerFactory.Dispose(); + } } } From c099ebe6fe6014d794858d82d00e3d2eb21a03d7 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 15 Sep 2023 08:10:48 -0400 Subject: [PATCH 08/24] - fixes hidi release build --- .../Handlers/PluginCommandHandler.cs | 8 ++++++++ .../Handlers/ShowCommandHandler.cs | 8 ++++++++ .../Handlers/TransformCommandHandler.cs | 8 ++++++++ .../Handlers/ValidateCommandHandler.cs | 10 +++++++++- 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/PluginCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/PluginCommandHandler.cs index 0fcb86df2..2c7e921bb 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/PluginCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/PluginCommandHandler.cs @@ -35,16 +35,24 @@ public async Task InvokeAsync(InvocationContext context) return 0; } +#if RELEASE +#pragma warning disable CA1031 // Do not catch general exception types +#endif catch (Exception ex) { #if DEBUG logger.LogCritical(ex, "Command failed"); throw; // so debug tools go straight to the source of the exception when attached #else +#pragma warning disable CA2254 logger.LogCritical(ex.Message); +#pragma warning restore CA2254 return 1; #endif } +#if RELEASE +#pragma warning restore CA1031 // Do not catch general exception types +#endif } } } diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/ShowCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/ShowCommandHandler.cs index a6a161dc2..054912302 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/ShowCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/ShowCommandHandler.cs @@ -35,16 +35,24 @@ public async Task InvokeAsync(InvocationContext context) return 0; } +#if RELEASE +#pragma warning disable CA1031 // Do not catch general exception types +#endif catch (Exception ex) { #if DEBUG logger.LogCritical(ex, "Command failed"); throw; // so debug tools go straight to the source of the exception when attached #else +#pragma warning disable CA2254 logger.LogCritical( ex.Message); +#pragma warning restore CA2254 return 1; #endif } +#if RELEASE +#pragma warning restore CA1031 // Do not catch general exception types +#endif } } } diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs index f173024cc..293fefec9 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs @@ -35,16 +35,24 @@ public async Task InvokeAsync(InvocationContext context) return 0; } +#if RELEASE +#pragma warning disable CA1031 // Do not catch general exception types +#endif catch (Exception ex) { #if DEBUG logger.LogCritical(ex, "Command failed"); throw; // so debug tools go straight to the source of the exception when attached #else +#pragma warning disable CA2254 logger.LogCritical( ex.Message); +#pragma warning restore CA2254 return 1; #endif } +#if RELEASE +#pragma warning restore CA1031 // Do not catch general exception types +#endif } } } diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs index 153ec707e..4351a04cb 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/ValidateCommandHandler.cs @@ -36,16 +36,24 @@ public async Task InvokeAsync(InvocationContext context) await OpenApiService.ValidateOpenApiDocument(hidiOptions.OpenApi, logger, cancellationToken).ConfigureAwait(false); return 0; } +#if RELEASE +#pragma warning disable CA1031 // Do not catch general exception types +#endif catch (Exception ex) { #if DEBUG logger.LogCritical(ex, "Command failed"); throw; // so debug tools go straight to the source of the exception when attached #else - logger.LogCritical( ex.Message); +#pragma warning disable CA2254 + logger.LogCritical(ex.Message); +#pragma warning restore CA2254 return 1; #endif } +#if RELEASE +#pragma warning restore CA1031 // Do not catch general exception types +#endif } } } From fa032dd7e74211417b23e47176d59b069e7314d2 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 18 Sep 2023 09:50:12 -0400 Subject: [PATCH 09/24] - removes publish trimmed since it'd break functionality Signed-off-by: Vincent Biret --- .azure-pipelines/ci-build.yml | 2 +- src/Microsoft.OpenApi.Hidi/Utilities/SettingsUtilities.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index 4ce92b8e9..43612060c 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -216,7 +216,7 @@ stages: displayName: publish Hidi as executable inputs: command: 'publish' - arguments: -c Release --runtime win-x64 /p:PublishSingleFile=true --self-contained --output $(Build.ArtifactStagingDirectory)/Microsoft.OpenApi.Hidi-v$(hidiversion) -p:PublishTrimmed=true + arguments: -c Release --runtime win-x64 /p:PublishSingleFile=true --self-contained --output $(Build.ArtifactStagingDirectory)/Microsoft.OpenApi.Hidi-v$(hidiversion) projects: 'src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj' publishWebProjects: False zipAfterPublish: false diff --git a/src/Microsoft.OpenApi.Hidi/Utilities/SettingsUtilities.cs b/src/Microsoft.OpenApi.Hidi/Utilities/SettingsUtilities.cs index 1d261e5f3..6264270a6 100644 --- a/src/Microsoft.OpenApi.Hidi/Utilities/SettingsUtilities.cs +++ b/src/Microsoft.OpenApi.Hidi/Utilities/SettingsUtilities.cs @@ -20,7 +20,7 @@ internal static IConfiguration GetConfiguration(string? settingsFile = null) return config; } - internal static OpenApiConvertSettings GetOpenApiConvertSettings(IConfiguration config, string? metadataVersion = null) + internal static OpenApiConvertSettings GetOpenApiConvertSettings(IConfiguration config, string? metadataVersion) { if (config == null) { throw new System.ArgumentNullException(nameof(config)); } var settings = new OpenApiConvertSettings(); From 4c558a886605f6f3b6f8db53e5594a61d4619998 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 21:01:18 +0000 Subject: [PATCH 10/24] Bump xunit.runner.visualstudio from 2.5.0 to 2.5.1 Bumps [xunit.runner.visualstudio](https://github.com/xunit/xunit) from 2.5.0 to 2.5.1. - [Commits](https://github.com/xunit/xunit/compare/2.5.0...2.5.1) --- updated-dependencies: - dependency-name: xunit.runner.visualstudio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../Microsoft.OpenApi.Hidi.Tests.csproj | 2 +- .../Microsoft.OpenApi.Readers.Tests.csproj | 4 ++-- .../Microsoft.OpenApi.SmokeTests.csproj | 2 +- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj index ebe55934f..8c6bdd9c0 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj +++ b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj @@ -16,7 +16,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj index 98ac3a206..c173d2ad2 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj +++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj @@ -1,4 +1,4 @@ - + net7.0 false @@ -281,7 +281,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Microsoft.OpenApi.SmokeTests/Microsoft.OpenApi.SmokeTests.csproj b/test/Microsoft.OpenApi.SmokeTests/Microsoft.OpenApi.SmokeTests.csproj index c1355fec4..89dc9d666 100644 --- a/test/Microsoft.OpenApi.SmokeTests/Microsoft.OpenApi.SmokeTests.csproj +++ b/test/Microsoft.OpenApi.SmokeTests/Microsoft.OpenApi.SmokeTests.csproj @@ -19,7 +19,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index a028227ef..8461b3ee6 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -30,7 +30,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From da91427a0dc62b298960d95bec4263b2667ceedd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 21:05:44 +0000 Subject: [PATCH 11/24] Bump xunit from 2.5.0 to 2.5.1 Bumps [xunit](https://github.com/xunit/xunit) from 2.5.0 to 2.5.1. - [Commits](https://github.com/xunit/xunit/compare/2.5.0...2.5.1) --- updated-dependencies: - dependency-name: xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../Microsoft.OpenApi.Hidi.Tests.csproj | 2 +- .../Microsoft.OpenApi.Readers.Tests.csproj | 2 +- .../Microsoft.OpenApi.SmokeTests.csproj | 2 +- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj index 8c6bdd9c0..706e899f1 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj +++ b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj @@ -15,7 +15,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj index c173d2ad2..7669e2fcf 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj +++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj @@ -279,7 +279,7 @@ - + all diff --git a/test/Microsoft.OpenApi.SmokeTests/Microsoft.OpenApi.SmokeTests.csproj b/test/Microsoft.OpenApi.SmokeTests/Microsoft.OpenApi.SmokeTests.csproj index 89dc9d666..2d72104ad 100644 --- a/test/Microsoft.OpenApi.SmokeTests/Microsoft.OpenApi.SmokeTests.csproj +++ b/test/Microsoft.OpenApi.SmokeTests/Microsoft.OpenApi.SmokeTests.csproj @@ -18,7 +18,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 8461b3ee6..7c0411500 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -29,7 +29,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From e4acf0951784c566695539ffc15f41950092632f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 21:27:58 +0000 Subject: [PATCH 12/24] Bump docker/build-push-action from 4.2.1 to 5.0.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4.2.1 to 5.0.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v4.2.1...v5.0.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index daee21546..103e77df0 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -30,13 +30,13 @@ jobs: id: getversion - name: Push to GitHub Packages - Nightly if: ${{ github.ref == 'refs/heads/vnext' }} - uses: docker/build-push-action@v4.2.1 + uses: docker/build-push-action@v5.0.0 with: push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly - name: Push to GitHub Packages - Release if: ${{ github.ref == 'refs/heads/master' }} - uses: docker/build-push-action@v4.2.1 + uses: docker/build-push-action@v5.0.0 with: push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.getversion.outputs.version }} From adbbe34f46da91ea7ed9aae150a6d3cbe84a56d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 21:28:03 +0000 Subject: [PATCH 13/24] Bump docker/login-action from 2.2.0 to 3.0.0 Bumps [docker/login-action](https://github.com/docker/login-action) from 2.2.0 to 3.0.0. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v2.2.0...v3.0.0) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index daee21546..c6c3eb95f 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -17,7 +17,7 @@ jobs: - name: Check out the repo uses: actions/checkout@v4 - name: Login to GitHub package feed - uses: docker/login-action@v2.2.0 + uses: docker/login-action@v3.0.0 with: username: ${{ secrets.ACR_USERNAME }} password: ${{ secrets.ACR_PASSWORD }} From cca1bb917ebf01373045832676f168cb9620354c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 19 Sep 2023 07:56:02 -0400 Subject: [PATCH 14/24] - fixes readme path to the correct hidi readme --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index b02f89003..3d20c3d9f 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -69,7 +69,7 @@ - + From 5c3230192140c8b4e078c5721f039891de59969d Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 19 Sep 2023 08:03:48 -0400 Subject: [PATCH 15/24] - adds auto merge dependabot workflow --- .github/workflows/auto-merge-dependabot.yml | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/auto-merge-dependabot.yml diff --git a/.github/workflows/auto-merge-dependabot.yml b/.github/workflows/auto-merge-dependabot.yml new file mode 100644 index 000000000..6e5953f56 --- /dev/null +++ b/.github/workflows/auto-merge-dependabot.yml @@ -0,0 +1,32 @@ +name: Auto-merge dependabot updates + +on: + pull_request: + branches: [ main ] + +permissions: + pull-requests: write + contents: write + +jobs: + + dependabot-merge: + + runs-on: ubuntu-latest + + if: ${{ github.actor == 'dependabot[bot]' }} + + steps: + - name: Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v1.6.0 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + + - name: Enable auto-merge for Dependabot PRs + # Only if version bump is not a major version change + if: ${{steps.metadata.outputs.update-type != 'version-update:semver-major'}} + run: gh pr merge --auto --merge "$PR_URL" + env: + PR_URL: ${{github.event.pull_request.html_url}} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} From 65b7e7eb0d8376148e802e0d187f59fab3e99e83 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 19 Sep 2023 09:29:44 -0400 Subject: [PATCH 16/24] - fixes an issue where executable release would fail because of warn as error --- .azure-pipelines/ci-build.yml | 2 +- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index 43612060c..244797588 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -216,7 +216,7 @@ stages: displayName: publish Hidi as executable inputs: command: 'publish' - arguments: -c Release --runtime win-x64 /p:PublishSingleFile=true --self-contained --output $(Build.ArtifactStagingDirectory)/Microsoft.OpenApi.Hidi-v$(hidiversion) + arguments: -c Release --runtime win-x64 /p:PublishSingleFile=true /p:PackAsTool=false --self-contained --output $(Build.ArtifactStagingDirectory)/Microsoft.OpenApi.Hidi-v$(hidiversion) projects: 'src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj' publishWebProjects: False zipAfterPublish: false diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 3d20c3d9f..f1ac21781 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -28,7 +28,7 @@ true true - NU5048;CA1848; + $(NoWarn);NU5048;NU5104;CA1848; true readme.md All From e07a980b14543a07dbdaa912262cf1ef53845ac1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Sep 2023 21:17:31 +0000 Subject: [PATCH 17/24] Bump Verify.Xunit from 21.1.3 to 21.1.4 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 21.1.3 to 21.1.4. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/21.1.3...21.1.4) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 7c0411500..d9f34b2bc 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -28,7 +28,7 @@ - + all From 0bb8a93525379479d209e279729b0515a9161c70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Sep 2023 21:46:23 +0000 Subject: [PATCH 18/24] Bump Verify.Xunit from 21.1.4 to 21.1.5 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 21.1.4 to 21.1.5. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/21.1.4...21.1.5) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index d9f34b2bc..55e99d880 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -28,7 +28,7 @@ - + all From 33ff05480f754eda46e393bddecef3b7cc642d72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Sep 2023 21:01:48 +0000 Subject: [PATCH 19/24] Bump Verify.Xunit from 21.1.5 to 21.2.0 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 21.1.5 to 21.2.0. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/commits) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 55e99d880..214b2f017 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -28,7 +28,7 @@ - + all From 73c11c53e81adfd7c7878b349c871a1d36e69744 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 26 Sep 2023 10:41:45 +0300 Subject: [PATCH 20/24] Add a DefaultContentType setting to OpenApiReaderSettings --- src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs | 5 +++++ src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs | 3 ++- src/Microsoft.OpenApi.Readers/ParsingContext.cs | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs b/src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs index 56001e295..25bcbca6f 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs @@ -62,6 +62,11 @@ public class OpenApiReaderSettings ///
public Uri BaseUrl { get; set; } + /// + /// Allows clients to define a custom DefaultContentType if produces array is empty + /// + public List DefaultContentType { get; set; } + /// /// Function used to provide an alternative loader for accessing external references. /// diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs index 5b87ab7ae..4a120cbbf 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlDocumentReader.cs @@ -47,7 +47,8 @@ public OpenApiDocument Read(YamlDocument input, out OpenApiDiagnostic diagnostic var context = new ParsingContext(diagnostic) { ExtensionParsers = _settings.ExtensionParsers, - BaseUrl = _settings.BaseUrl + BaseUrl = _settings.BaseUrl, + DefaultContentType = _settings.DefaultContentType }; OpenApiDocument document = null; diff --git a/src/Microsoft.OpenApi.Readers/ParsingContext.cs b/src/Microsoft.OpenApi.Readers/ParsingContext.cs index 6c4dece2f..0cd98c67e 100644 --- a/src/Microsoft.OpenApi.Readers/ParsingContext.cs +++ b/src/Microsoft.OpenApi.Readers/ParsingContext.cs @@ -29,6 +29,7 @@ public class ParsingContext internal RootNode RootNode { get; set; } internal List Tags { get; private set; } = new List(); internal Uri BaseUrl { get; set; } + internal List DefaultContentType { get; set; } /// /// Diagnostic object that returns metadata about the parsing process. From 07202317c7cdee148941ac1ea0fd5d83faf529eb Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 26 Sep 2023 10:42:35 +0300 Subject: [PATCH 21/24] Use the setting passed as the default content type if global and local produces are missing --- src/Microsoft.OpenApi.Readers/V2/OpenApiResponseDeserializer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiResponseDeserializer.cs index 5734ff19d..182def419 100644 --- a/src/Microsoft.OpenApi.Readers/V2/OpenApiResponseDeserializer.cs +++ b/src/Microsoft.OpenApi.Readers/V2/OpenApiResponseDeserializer.cs @@ -74,7 +74,7 @@ private static void ProcessProduces(MapNode mapNode, OpenApiResponse response, P var produces = context.GetFromTempStorage>(TempStorageKeys.OperationProduces) ?? context.GetFromTempStorage>(TempStorageKeys.GlobalProduces) - ?? new List { "application/octet-stream" }; + ?? context.DefaultContentType ?? new List { "application/octet-stream" }; var schema = context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response); From f359565dfcba4ddbe97901b3939bdce4a8cf255c Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 26 Sep 2023 10:43:03 +0300 Subject: [PATCH 22/24] Add test to validate --- .../Microsoft.OpenApi.Readers.Tests.csproj | 5 +++- .../V2Tests/OpenApiDocumentTests.cs | 30 ++++++++++++------- .../V2Tests/Samples/docWithEmptyProduces.yaml | 20 +++++++++++++ 3 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/docWithEmptyProduces.yaml diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj index 7669e2fcf..ee9240603 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj +++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj @@ -36,7 +36,10 @@ Never - + + Never + + PreserveNewest diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs index 0b35d43e8..ac5f99a86 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs @@ -409,19 +409,27 @@ public void ShouldAssignSchemaToAllResponses() [Fact] public void ShouldAllowComponentsThatJustContainAReference() { - using (var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "ComponentRootReference.json"))) + using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "ComponentRootReference.json")); + OpenApiStreamReader reader = new OpenApiStreamReader(); + OpenApiDocument doc = reader.Read(stream, out OpenApiDiagnostic diags); + OpenApiSchema schema1 = doc.Components.Schemas["AllPets"]; + Assert.False(schema1.UnresolvedReference); + OpenApiSchema schema2 = doc.ResolveReferenceTo(schema1.Reference); + if (schema2.UnresolvedReference && schema1.Reference.Id == schema2.Reference.Id) { - OpenApiStreamReader reader = new OpenApiStreamReader(); - OpenApiDocument doc = reader.Read(stream, out OpenApiDiagnostic diags); - OpenApiSchema schema1 = doc.Components.Schemas["AllPets"]; - Assert.False(schema1.UnresolvedReference); - OpenApiSchema schema2 = doc.ResolveReferenceTo(schema1.Reference); - if (schema2.UnresolvedReference && schema1.Reference.Id == schema2.Reference.Id) - { - // detected a cycle - this code gets triggered - Assert.Fail("A cycle should not be detected"); - } + // detected a cycle - this code gets triggered + Assert.Fail("A cycle should not be detected"); } } + + [Fact] + public void ParseDocumentWithDefaultContentTypeSettingShouldSucceed() + { + using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "docWithEmptyProduces.yaml")); + var doc = new OpenApiStreamReader(new OpenApiReaderSettings { DefaultContentType = new List { "application/json" } }) + .Read(stream, out OpenApiDiagnostic diags); + var mediaType = doc.Paths["/example"].Operations[OperationType.Get].Responses["200"].Content; + Assert.Contains("application/json", mediaType); + } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/docWithEmptyProduces.yaml b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/docWithEmptyProduces.yaml new file mode 100644 index 000000000..ba9213c08 --- /dev/null +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/docWithEmptyProduces.yaml @@ -0,0 +1,20 @@ +swagger: '2.0' +info: + title: Sample API + version: 1.0.0 +paths: + /example: + get: + summary: Get Example + description: Retrieves an example resource. + produces: [] + responses: + 200: + description: Successful response + schema: + format: binary, + description: The content of the file., + type: string, + x-ms-summary: File Content +components: {} + \ No newline at end of file From 3d6c85e9f0d95335de58194c325f6bdaa74bbcdb Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 26 Sep 2023 16:43:26 +0300 Subject: [PATCH 23/24] Bump lib versions --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 2 +- src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj | 2 +- src/Microsoft.OpenApi/Microsoft.OpenApi.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index f1ac21781..ced9d9c3c 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -17,7 +17,7 @@ Microsoft.OpenApi.Hidi hidi ./../../artifacts - 1.2.9 + 1.3.0 OpenAPI.NET CLI tool for slicing OpenAPI documents © Microsoft Corporation. All rights reserved. OpenAPI .NET diff --git a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj index 609b16a09..49dde408e 100644 --- a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj +++ b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj @@ -11,7 +11,7 @@ Microsoft Microsoft.OpenApi.Readers Microsoft.OpenApi.Readers - 1.6.8 + 1.6.9 OpenAPI.NET Readers for JSON and YAML documents © Microsoft Corporation. All rights reserved. OpenAPI .NET diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj index 739d34354..7372332c1 100644 --- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj +++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj @@ -11,7 +11,7 @@ Microsoft Microsoft.OpenApi Microsoft.OpenApi - 1.6.8 + 1.6.9 .NET models with JSON and YAML writers for OpenAPI specification © Microsoft Corporation. All rights reserved. OpenAPI .NET From b2544025fe63cf1e5c9bad7ced2d1aa86b75e2f2 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 26 Sep 2023 17:06:15 +0300 Subject: [PATCH 24/24] Fix grammatical error in ReadMe --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 60cc5e2f7..358d0a686 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ var document = new OpenApiDocument }; ``` -Reading and writing a OpenAPI description +Reading and writing an OpenAPI description ```C# var httpClient = new HttpClient