зеркало из https://github.com/microsoft/kiota.git
Merge pull request #5028 from microsoft/andrueastman/cleanupExtensions
Exclude the `x-openai-isConsequential` extension from plugin cleanup
This commit is contained in:
Коммит
1983ca4d02
|
@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Fixed a bug where the copilot teams toolkit integration would serialize empty declarative copilots. [#4974](https://github.com/microsoft/kiota/issues/4974)
|
||||
- Fixed a bug for the docker image where the volume path would not match the expected configuration for the description.
|
||||
- Fixed a bug in Go where certain namespaces were escaped unexpectedly. [#5012](https://github.com/microsoft/kiota/issues/5012)
|
||||
- Exclude the `x-openai-isConsequential` extension from cleanup. [#4962](https://github.com/microsoft/kiota/issues/4962)
|
||||
- Fixed file name and namespace sanitization when generating plugins. [#5019](https://github.com/microsoft/kiota/issues/5019)
|
||||
|
||||
## [1.16.0] - 2024-07-05
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Kiota.Builder.OpenApiExtensions;
|
||||
using Microsoft.OpenApi.Readers;
|
||||
|
||||
|
@ -18,4 +20,24 @@ public static class OpenApiSettingsExtensions
|
|||
settings.ExtensionParsers.TryAdd(OpenApiAiReasoningInstructionsExtension.Name, static (i, _) => OpenApiAiReasoningInstructionsExtension.Parse(i));
|
||||
settings.ExtensionParsers.TryAdd(OpenApiAiRespondingInstructionsExtension.Name, static (i, _) => OpenApiAiRespondingInstructionsExtension.Parse(i));
|
||||
}
|
||||
|
||||
public static void AddGenerationExtensions(this OpenApiReaderSettings settings)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(settings);
|
||||
settings.AddMicrosoftExtensionParsers();
|
||||
settings.ExtensionParsers.TryAdd(OpenApiKiotaExtension.Name, static (i, _) => OpenApiKiotaExtension.Parse(i));
|
||||
}
|
||||
|
||||
public static HashSet<string> KiotaSupportedExtensions()
|
||||
{
|
||||
var dummySettings = new OpenApiReaderSettings();
|
||||
dummySettings.AddGenerationExtensions();
|
||||
dummySettings.AddPluginsExtensions();
|
||||
|
||||
var supportedExtensions = dummySettings.ExtensionParsers.Keys.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
supportedExtensions.Add("x-openai-isConsequential");// add extension we don't parse to the list
|
||||
|
||||
return supportedExtensions;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,10 +112,12 @@ internal class OpenApiDocumentDownloadService
|
|||
{
|
||||
RuleSet = ruleSet,
|
||||
};
|
||||
settings.AddMicrosoftExtensionParsers();
|
||||
|
||||
// Add all extensions for generation
|
||||
settings.AddGenerationExtensions();
|
||||
if (config.IsPluginConfiguration)
|
||||
settings.AddPluginsExtensions();
|
||||
settings.ExtensionParsers.TryAdd(OpenApiKiotaExtension.Name, static (i, _) => OpenApiKiotaExtension.Parse(i));
|
||||
settings.AddPluginsExtensions();// Add all extensions for plugins
|
||||
|
||||
try
|
||||
{
|
||||
var rawUri = config.OpenAPIFilePath.TrimEnd(KiotaBuilder.ForwardSlash);
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Kiota.Builder.Extensions;
|
||||
using Microsoft.OpenApi.Interfaces;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.Services;
|
||||
|
||||
namespace Kiota.Builder.Plugins;
|
||||
|
||||
public class OpenApiPluginWalker : OpenApiVisitorBase
|
||||
{
|
||||
private static readonly HashSet<string> SupportedExtensions = OpenApiSettingsExtensions.KiotaSupportedExtensions();
|
||||
|
||||
/// <summary>
|
||||
/// Visits <see cref="OpenApiSchema"/>
|
||||
/// </summary>
|
||||
public override void Visit(IOpenApiExtensible openApiExtensible)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(openApiExtensible);
|
||||
// remove any extensions we do not support
|
||||
foreach (var extension in openApiExtensible.Extensions.Where(static extension => !SupportedExtensions.Contains(extension.Key)))
|
||||
{
|
||||
openApiExtensible.Extensions.Remove(extension.Key);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Visits the operations.
|
||||
/// </summary>
|
||||
public override void Visit(IDictionary<OperationType, OpenApiOperation> operations)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(operations);
|
||||
|
||||
// Cleanup responses for the operation
|
||||
foreach (var operation in operations.Values)
|
||||
{
|
||||
var responseDescription = operation.Responses.Values.Select(static response => response.Description)
|
||||
.FirstOrDefault(static desc => !string.IsNullOrEmpty(desc)) ?? "Api Response";
|
||||
|
||||
operation.Responses = new OpenApiResponses()
|
||||
{
|
||||
{
|
||||
"2XX",new OpenApiResponse
|
||||
{
|
||||
Description = responseDescription,
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
"text/plain", new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Type = "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -192,35 +192,11 @@ public partial class PluginsGenerationService
|
|||
if (string.IsNullOrEmpty(doc.Info?.Version)) // filtering fails if there's no version.
|
||||
doc.Info!.Version = "1.0";
|
||||
|
||||
//empty out all the responses with a single empty 2XX
|
||||
foreach (var operation in doc.Paths.SelectMany(static item => item.Value.Operations.Values))
|
||||
{
|
||||
var responseDescription = operation.Responses.Values.Select(static response => response.Description)
|
||||
.FirstOrDefault(static desc => !string.IsNullOrEmpty(desc)) ?? "Api Response";
|
||||
operation.Responses = new OpenApiResponses()
|
||||
{
|
||||
{
|
||||
"2XX",new OpenApiResponse
|
||||
{
|
||||
Description = responseDescription,
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
"text/plain", new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Type = "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
//empty out all the responses with a single empty 2XX and cleanup the extensions
|
||||
var openApiWalker = new OpenApiWalker(new OpenApiPluginWalker());
|
||||
openApiWalker.Walk(doc);
|
||||
|
||||
// remove unused components using the OpenApi.Net
|
||||
// remove unused components using the OpenApi.Net library
|
||||
var requestUrls = new Dictionary<string, List<string>>();
|
||||
var basePath = doc.GetAPIRootUrl(Configuration.OpenAPIFilePath);
|
||||
foreach (var path in doc.Paths.Where(static path => path.Value.Operations.Count > 0))
|
||||
|
|
|
@ -685,6 +685,7 @@ paths:
|
|||
/test:
|
||||
get:
|
||||
description: description for test path
|
||||
x-random-extension: true
|
||||
responses:
|
||||
'200':
|
||||
description: test
|
||||
|
@ -694,6 +695,7 @@ paths:
|
|||
get:
|
||||
description: description for test path with id
|
||||
operationId: test.WithId
|
||||
x-openai-isConsequential: true
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
|
@ -764,7 +766,9 @@ components:
|
|||
Assert.Single(originalDocument.Extensions); // single unsupported extension at root
|
||||
Assert.Equal(2, originalDocument.Paths.Count); // document has only two paths
|
||||
Assert.Equal(2, originalDocument.Paths["/test"].Operations[OperationType.Get].Responses.Count); // 2 responses originally
|
||||
Assert.Single(originalDocument.Paths["/test"].Operations[OperationType.Get].Extensions); // 1 UNsupported extension
|
||||
Assert.Equal(2, originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Count); // 2 responses originally
|
||||
Assert.Single(originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Extensions); // 1 supported extension
|
||||
|
||||
// Validate the output open api file
|
||||
var resultOpenApiFile = File.OpenRead(Path.Combine(outputDirectory, OpenApiFileName));
|
||||
|
@ -777,7 +781,9 @@ components:
|
|||
Assert.Equal(2, resultDocument.Paths.Count); // document has only two paths
|
||||
Assert.Single(resultDocument.Paths["/test"].Operations[OperationType.Get].Responses); // other responses are removed from the document
|
||||
Assert.NotEmpty(resultDocument.Paths["/test"].Operations[OperationType.Get].Responses["2XX"].Description); // response description string is not empty
|
||||
Assert.Empty(resultDocument.Paths["/test"].Operations[OperationType.Get].Extensions); // NO UNsupported extension
|
||||
Assert.Single(resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses); // 2 responses originally
|
||||
Assert.NotEmpty(resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses["2XX"].Description);// response description string is not empty
|
||||
Assert.Single(resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Extensions); // 1 supported extension still present in operation
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче