Skip to content

Commit

Permalink
Merge pull request #1543 from microsoft/vnext
Browse files Browse the repository at this point in the history
Release Hidi and Libs
  • Loading branch information
MaggieKimani1 authored Jan 29, 2024
2 parents 79f59bf + d16d3bc commit 8973a58
Show file tree
Hide file tree
Showing 61 changed files with 613 additions and 92 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ name: CI/CD Pipeline

on: [push, pull_request, workflow_dispatch]

permissions:
contents: write

jobs:
ci:
name: Continuous Integration
Expand Down
9 changes: 7 additions & 2 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ on:
types: [opened, synchronize, reopened]
paths-ignore: ['.vscode/**']


permissions:
contents: read
pull-requests: read

env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

Expand Down Expand Up @@ -46,14 +51,14 @@ jobs:
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Cache SonarCloud packages
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache SonarCloud scanner
id: cache-sonar-scanner
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ./.sonar/scanner
key: ${{ runner.os }}-sonar-scanner
Expand Down
6 changes: 3 additions & 3 deletions src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
Expand All @@ -9,7 +9,7 @@
<Nullable>enable</Nullable>
<ToolCommandName>hidi</ToolCommandName>
<PackageOutputPath>./../../artifacts</PackageOutputPath>
<Version>1.3.7</Version>
<Version>1.3.8</Version>
<Description>OpenAPI.NET CLI tool for slicing OpenAPI documents</Description>
<SignAssembly>true</SignAssembly>
<!-- https://github.com/dotnet/sourcelink/blob/main/docs/README.md#embeduntrackedsources -->
Expand All @@ -35,7 +35,7 @@
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageReference Include="Microsoft.OData.Edm" Version="7.20.0" />
<PackageReference Include="Microsoft.OpenApi.OData" Version="1.6.0-preview.2" />
<PackageReference Include="Microsoft.OpenApi.OData" Version="1.6.0-preview.4" />
<PackageReference Include="Microsoft.OpenApi.ApiManifest" Version="0.5.0-preview" />
<PackageReference Include="System.CommandLine.Hosting" Version="0.4.0-alpha.22272.1" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>1.6.12</Version>
<Version>1.6.13</Version>
<Description>OpenAPI.NET Readers for JSON and YAML documents</Description>
<SignAssembly>true</SignAssembly>
<!-- https://github.com/dotnet/sourcelink/blob/main/docs/README.md#embeduntrackedsources -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Xml.Linq;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Models;
Expand Down Expand Up @@ -194,7 +195,8 @@ internal static OpenApiRequestBody CreateRequestBody(
k => k,
_ => new OpenApiMediaType
{
Schema = bodyParameter.Schema
Schema = bodyParameter.Schema,
Examples = bodyParameter.Examples
}),
Extensions = bodyParameter.Extensions
};
Expand Down
21 changes: 20 additions & 1 deletion src/Microsoft.OpenApi.Readers/V2/OpenApiParameterDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,17 @@ internal static partial class OpenApiV2Deserializer
"schema",
(o, n) => o.Schema = LoadSchema(n)
},
{
"x-examples",
LoadParameterExamplesExtension
},
};

private static readonly PatternFieldMap<OpenApiParameter> _parameterPatternFields =
new()
{
{s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))}
{s => s.StartsWith("x-") && !s.Equals(OpenApiConstants.ExamplesExtension, StringComparison.OrdinalIgnoreCase),
(o, p, n) => o.AddExtension(p, LoadExtension(p, n))}
};

private static readonly AnyFieldMap<OpenApiParameter> _parameterAnyFields =
Expand Down Expand Up @@ -166,6 +171,12 @@ private static void LoadStyle(OpenApiParameter p, string v)
}
}

private static void LoadParameterExamplesExtension(OpenApiParameter parameter, ParseNode node)
{
var examples = LoadExamplesExtension(node);
node.Context.SetTempStorage(TempStorageKeys.Examples, examples, parameter);
}

private static OpenApiSchema GetOrCreateSchema(OpenApiParameter p)
{
if (p.Schema == null)
Expand Down Expand Up @@ -250,6 +261,14 @@ public static OpenApiParameter LoadParameter(ParseNode node, bool loadRequestBod
node.Context.SetTempStorage("schema", null);
}

// load examples from storage and add them to the parameter
var examples = node.Context.GetFromTempStorage<Dictionary<string, OpenApiExample>>(TempStorageKeys.Examples, parameter);
if (examples != null)
{
parameter.Examples = examples;
node.Context.SetTempStorage("examples", null);
}

var isBodyOrFormData = (bool)node.Context.GetFromTempStorage<object>(TempStorageKeys.ParameterIsBodyOrFormData);
if (isBodyOrFormData && !loadRequestBody)
{
Expand Down
62 changes: 56 additions & 6 deletions src/Microsoft.OpenApi.Readers/V2/OpenApiResponseDeserializer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System;
using System.Collections.Generic;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Models;
Expand Down Expand Up @@ -28,6 +29,10 @@ internal static partial class OpenApiV2Deserializer
"examples",
LoadExamples
},
{
"x-examples",
LoadResponseExamplesExtension
},
{
"schema",
(o, n) => n.Context.SetTempStorage(TempStorageKeys.ResponseSchema, LoadSchema(n), o)
Expand All @@ -37,7 +42,8 @@ internal static partial class OpenApiV2Deserializer
private static readonly PatternFieldMap<OpenApiResponse> _responsePatternFields =
new()
{
{s => s.StartsWith("x-"), (o, p, n) => o.AddExtension(p, LoadExtension(p, n))}
{s => s.StartsWith("x-") && !s.Equals(OpenApiConstants.ExamplesExtension, StringComparison.OrdinalIgnoreCase),
(o, p, n) => o.AddExtension(p, LoadExtension(p, n))}
};

private static readonly AnyFieldMap<OpenApiMediaType> _mediaTypeAnyFields =
Expand Down Expand Up @@ -69,6 +75,8 @@ private static void ProcessProduces(MapNode mapNode, OpenApiResponse response, P
?? context.DefaultContentType ?? new List<string> { "application/octet-stream" };

var schema = context.GetFromTempStorage<OpenApiSchema>(TempStorageKeys.ResponseSchema, response);
var examples = context.GetFromTempStorage<Dictionary<string, OpenApiExample>>(TempStorageKeys.Examples, response)
?? new Dictionary<string, OpenApiExample>();

foreach (var produce in produces)
{
Expand All @@ -84,20 +92,64 @@ private static void ProcessProduces(MapNode mapNode, OpenApiResponse response, P
{
var mediaType = new OpenApiMediaType
{
Schema = schema
Schema = schema,
Examples = examples
};

response.Content.Add(produce, mediaType);
}
}

context.SetTempStorage(TempStorageKeys.ResponseSchema, null, response);
context.SetTempStorage(TempStorageKeys.Examples, null, response);
context.SetTempStorage(TempStorageKeys.ResponseProducesSet, true, response);
}

private static void LoadResponseExamplesExtension(OpenApiResponse response, ParseNode node)
{
var examples = LoadExamplesExtension(node);
node.Context.SetTempStorage(TempStorageKeys.Examples, examples, response);
}

private static Dictionary<string, OpenApiExample> LoadExamplesExtension(ParseNode node)
{
var mapNode = node.CheckMapNode(OpenApiConstants.ExamplesExtension);
var examples = new Dictionary<string, OpenApiExample>();

foreach (var examplesNode in mapNode)
{
// Load the media type node as an OpenApiExample object
var example = new OpenApiExample();
var exampleNode = examplesNode.Value.CheckMapNode(examplesNode.Name);
foreach (var valueNode in exampleNode)
{
switch (valueNode.Name.ToLowerInvariant())
{
case "summary":
example.Summary = valueNode.Value.GetScalarValue();
break;
case "description":
example.Description = valueNode.Value.GetScalarValue();
break;
case "value":
example.Value = OpenApiAnyConverter.GetSpecificOpenApiAny(valueNode.Value.CreateAny());
break;
case "externalValue":
example.ExternalValue = valueNode.Value.GetScalarValue();
break;
}
}

examples.Add(examplesNode.Name, example);
}

return examples;
}

private static void LoadExamples(OpenApiResponse response, ParseNode node)
{
var mapNode = node.CheckMapNode("examples");

foreach (var mediaTypeNode in mapNode)
{
LoadExample(response, mediaTypeNode.Name, mediaTypeNode.Value);
Expand All @@ -108,10 +160,7 @@ private static void LoadExample(OpenApiResponse response, string mediaType, Pars
{
var exampleNode = node.CreateAny();

if (response.Content == null)
{
response.Content = new Dictionary<string, OpenApiMediaType>();
}
response.Content ??= new Dictionary<string, OpenApiMediaType>();

OpenApiMediaType mediaTypeObject;
if (response.Content.TryGetValue(mediaType, out var value))
Expand Down Expand Up @@ -141,6 +190,7 @@ public static OpenApiResponse LoadResponse(ParseNode node)
}

var response = new OpenApiResponse();

foreach (var property in mapNode)
{
property.ParseField(response, _responseFixedFields, _responsePatternFields);
Expand Down
1 change: 1 addition & 0 deletions src/Microsoft.OpenApi.Readers/V2/TempStorageKeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ internal static class TempStorageKeys
public const string GlobalConsumes = "globalConsumes";
public const string GlobalProduces = "globalProduces";
public const string ParameterIsBodyOrFormData = "parameterIsBodyOrFormData";
public const string Examples = "examples";
}
}
2 changes: 1 addition & 1 deletion src/Microsoft.OpenApi/Microsoft.OpenApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>Latest</LangVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>1.6.12</Version>
<Version>1.6.13</Version>
<Description>.NET models with JSON and YAML writers for OpenAPI specification</Description>
<SignAssembly>true</SignAssembly>
<!-- https://github.com/dotnet/sourcelink/blob/main/docs/README.md#embeduntrackedsources -->
Expand Down
5 changes: 5 additions & 0 deletions src/Microsoft.OpenApi/Models/OpenApiConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,11 @@ public static class OpenApiConstants
/// </summary>
public const string BodyName = "x-bodyName";

/// <summary>
/// Field: Examples Extension
/// </summary>
public const string ExamplesExtension = "x-examples";

/// <summary>
/// Field: version3_0_0
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.OpenApi/Models/OpenApiDocument.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System;
Expand Down
12 changes: 11 additions & 1 deletion src/Microsoft.OpenApi/Models/OpenApiExample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@ public OpenApiExample GetEffective(OpenApiDocument doc)
/// Serialize to OpenAPI V3 document without using reference.
/// </summary>
public void SerializeAsV3WithoutReference(IOpenApiWriter writer)
{
Serialize(writer, OpenApiSpecVersion.OpenApi3_0);
}

/// <summary>
/// Writes out existing examples in a mediatype object
/// </summary>
/// <param name="writer"></param>
/// <param name="version"></param>
public void Serialize(IOpenApiWriter writer, OpenApiSpecVersion version)
{
writer.WriteStartObject();

Expand All @@ -134,7 +144,7 @@ public void SerializeAsV3WithoutReference(IOpenApiWriter writer)
writer.WriteProperty(OpenApiConstants.ExternalValue, ExternalValue);

// extensions
writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0);
writer.WriteExtensions(Extensions, version);

writer.WriteEndObject();
}
Expand Down
24 changes: 16 additions & 8 deletions src/Microsoft.OpenApi/Models/OpenApiParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Interfaces;
Expand Down Expand Up @@ -204,14 +205,7 @@ public void SerializeAsV3(IOpenApiWriter writer)
/// <returns>OpenApiParameter</returns>
public OpenApiParameter GetEffective(OpenApiDocument doc)
{
if (this.Reference != null)
{
return doc.ResolveReferenceTo<OpenApiParameter>(this.Reference);
}
else
{
return this;
}
return Reference != null ? doc.ResolveReferenceTo<OpenApiParameter>(Reference) : this;
}

/// <summary>
Expand Down Expand Up @@ -394,6 +388,20 @@ public void SerializeAsV2WithoutReference(IOpenApiWriter writer)
}
}

//examples
if (Examples != null && Examples.Any())
{
writer.WritePropertyName(OpenApiConstants.ExamplesExtension);
writer.WriteStartObject();

foreach (var example in Examples)
{
writer.WritePropertyName(example.Key);
example.Value.Serialize(writer, OpenApiSpecVersion.OpenApi2_0);
}
writer.WriteEndObject();
}

// extensions
writer.WriteExtensions(extensionsClone, OpenApiSpecVersion.OpenApi2_0);

Expand Down
13 changes: 4 additions & 9 deletions src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,7 @@ public void SerializeAsV3(IOpenApiWriter writer)
/// <returns>OpenApiRequestBody</returns>
public OpenApiRequestBody GetEffective(OpenApiDocument doc)
{
if (this.Reference != null)
{
return doc.ResolveReferenceTo<OpenApiRequestBody>(this.Reference);
}
else
{
return this;
}
return Reference != null ? doc.ResolveReferenceTo<OpenApiRequestBody>(Reference) : this;
}

/// <summary>
Expand Down Expand Up @@ -153,6 +146,7 @@ internal OpenApiBodyParameter ConvertToBodyParameter()
// To allow round-tripping we use an extension to hold the name
Name = "body",
Schema = Content.Values.FirstOrDefault()?.Schema ?? new OpenApiSchema(),
Examples = Content.Values.FirstOrDefault()?.Examples,
Required = Required,
Extensions = Extensions.ToDictionary(static k => k.Key, static v => v.Value) // Clone extensions so we can remove the x-bodyName extensions from the output V2 model.
};
Expand Down Expand Up @@ -184,7 +178,8 @@ internal IEnumerable<OpenApiFormDataParameter> ConvertToFormDataParameters()
Description = property.Value.Description,
Name = property.Key,
Schema = property.Value,
Required = Content.First().Value.Schema.Required.Contains(property.Key)
Examples = Content.Values.FirstOrDefault()?.Examples,
Required = Content.First().Value.Schema.Required?.Contains(property.Key) ?? false
};
}
}
Expand Down
Loading

0 comments on commit 8973a58

Please sign in to comment.