Skip to content

Add support for OpenAPI v3.1#349

Merged
christianhelle merged 18 commits intomainfrom
microsoft-openapi-v3
Mar 20, 2026
Merged

Add support for OpenAPI v3.1#349
christianhelle merged 18 commits intomainfrom
microsoft-openapi-v3

Conversation

@christianhelle
Copy link
Copy Markdown
Owner

@christianhelle christianhelle commented Mar 20, 2026

fixes #331
fixes #332
fixes #333
fixes #334

This pull request refactors the codebase to replace the usage of Microsoft's OpenApi libraries with the OasReader package for OpenAPI document handling. This change streamlines OpenAPI file reading and parsing, simplifies code for handling different OpenAPI versions, and updates method signatures to use new interfaces from OasReader. It also updates the test suite to reflect the new validation logic.

Dependency and library updates:

  • Removed dependencies on Microsoft.OpenApi, Microsoft.OpenApi.Readers, and related packages, and added the OasReader package to both HttpGenerator.Core and HttpGenerator projects. [1] [2]

Core logic refactoring for OpenAPI reading and parsing:

  • Replaced all usages of OpenApiDocument, OpenApiParameter, OpenApiSchema, etc., with their OasReader interface equivalents (such as IOpenApiParameter, IOpenApiSchema, and IOpenApiPathItem) throughout the codebase, including method signatures and internal logic in HttpFileGenerator.cs, OpenApiStats.cs, and related files. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]

  • Refactored OpenAPI document loading to use OpenApiMultiFileReader.Read, removing custom logic for HTTP/file handling, OpenAPI version downgrading, and decompression. This simplifies the code and improves support for OpenAPI 3.1 and multi-file specs. [1] [2] [3]

Validation and test updates:

  • Updated the OpenAPI validation logic to use the new reader and visitor pattern, and adjusted the test suite so that certain OpenAPI 3.1 specs now pass validation as expected. [1] [2] [3]

General code cleanup:

  • Removed unused imports and obsolete code related to the old OpenAPI libraries. [1] [2] [3] [4] [5]

These changes modernize the codebase, reduce maintenance overhead, and improve compatibility with newer OpenAPI specifications.

Summary by CodeRabbit

  • New Features

    • Improved OpenAPI multi-file/spec parsing and validation.
  • Bug Fixes

    • More robust handling of missing or nullable parameter names in generated requests.
  • Refactor

    • Migrated internal OpenAPI handling to interface-based abstractions.
    • Simplified OpenAPI loading flow and removed legacy fallback logic.
  • Tests

    • Added extensive unit and edge-case tests for generation, validation, stats, and content output.
  • Documentation

    • Added repository commit policy entries disallowing co-author trailers.

@christianhelle christianhelle self-assigned this Mar 20, 2026
@christianhelle christianhelle added the enhancement New feature or request label Mar 20, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 20, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8627ead0-4f1e-4782-987f-64ac0f8bec3c

📥 Commits

Reviewing files that changed from the base of the PR and between 136cc61 and 098c6af.

📒 Files selected for processing (19)
  • .github/copilot-instructions.md
  • .squad/agents/bishop/charter.md
  • .squad/agents/bishop/history.md
  • .squad/agents/hicks/charter.md
  • .squad/agents/hicks/history.md
  • .squad/agents/hudson/charter.md
  • .squad/agents/ripley/charter.md
  • .squad/agents/scribe/charter.md
  • .squad/decisions.md
  • src/HttpGenerator.Tests/GeneratedContentTests.cs
  • src/HttpGenerator.Tests/HttpFileGeneratorEdgeCasesTests.cs
  • src/HttpGenerator.Tests/OpenApiStatsTests.cs
  • src/HttpGenerator.Tests/OpenApiValidatorTests.cs
  • src/HttpGenerator.Tests/PrivacyHelperTests.cs
  • src/HttpGenerator.Tests/StringExtensionsTests.cs
  • src/HttpGenerator.Tests/SupportKeyInitializerTests.cs
  • src/HttpGenerator/GenerateCommand.cs
  • src/HttpGenerator/Validation/OpenApiValidator.cs
  • test/smoke-tests.ps1

📝 Walkthrough

Walkthrough

The PR migrates the OpenAPI reader pipeline to the OasReader/OpenApiMultiFileReader API, replaces concrete Microsoft.OpenApi model types with their interface counterparts (IOpenApi*), updates parameter-name and schema-type sampling logic, removes manual 3.1→3.0 downgrade/read helpers, and adds/adjusts many unit tests covering generation and validation behaviors.

Changes

Cohort / File(s) Summary
Package Dependencies
src/HttpGenerator.Core/HttpGenerator.Core.csproj, src/HttpGenerator/HttpGenerator.csproj
Removed legacy Microsoft.OpenApi.* and Microsoft.OpenApi.Readers/OData refs; added/pointed to OasReader/OpenApi v3 package set.
Document Parsing / Reader
src/HttpGenerator.Core/OpenApiDocumentFactory.cs, src/HttpGenerator/Validation/OpenApiValidator.cs
Replaced manual stream/http/TLS parsing and OpenApiStreamReader-based logic with OpenApiMultiFileReader.Read(...); removed fallback/downgrade and helper methods used for parsing.
Generator: request/parameter & schema sampling
src/HttpGenerator.Core/HttpFileGenerator.cs
Switched signatures and internals from concrete types to interfaces (IOpenApiPathItem, IOpenApiParameter, IOpenApiSchema?); tolerate null/unnamed parameters by synthesizing keys; replaced string-based schema type checks with JsonSchemaType flag checks and updated sample/default value helpers.
Visitor / Stats / Validation types
src/HttpGenerator/Validation/OpenApiStats.cs, src/HttpGenerator/Validation/OpenApiValidationResult.cs
Visitor overrides and type usages updated to use IOpenApi* interfaces; adjusted reader/namespace imports to new package naming.
Operation naming & CLI glue
src/HttpGenerator.Core/OperationNameGenerator.cs, src/HttpGenerator/GenerateCommand.cs
Null-safe handling for operation.OperationId; updated using directives and introduced OpenApiValidator alias usage in CLI validation path; added coverage exclusion attribute on TryWriteLine.
Tests — validator / generator / content / edge cases
src/HttpGenerator.Tests/... (many new/modified files, e.g., GeneratedContentTests.cs, HttpFileGeneratorEdgeCasesTests.cs, OpenApiStatsTests.cs, OpenApiValidatorTests.cs, GenerateCommandTests.cs, PrivacyHelperTests.cs, StringExtensionsTests.cs, SupportKeyInitializerTests.cs)
Added extensive tests: generation content checks (default values, headers, content types, IntelliJ tests), edge-case filename collision and BaseUrl/template handling, OpenApi stats and validator behavior; adjusted a GenerateCommand test expectation.
Repo docs & policies
.github/copilot-instructions.md, .squad/*/charter.md, .squad/*/history.md, .squad/decisions.md, test/smoke-tests.ps1
Added/updated commit-message policy entries forbidding Co-authored-by trailers; appended decision/history entries and expanded smoke-test script with targeted generation scenarios.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐇 I swapped concrete shells for interface art,
OpenApiMultiFileReader gave parsing a start.
Names that were missing now get a key,
Samples read types by flags, not a stringy plea —
Hop, hop, I celebrate this tidy depart! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely describes the primary objective: adding support for OpenAPI v3.1, which aligns with the main architectural change of migrating to the OasReader package.
Linked Issues check ✅ Passed All three linked issues (#331, #332, #333) are addressed: reader pipeline migrated to OasReader with interface-based abstractions [#331], visitor/statistics updated to use OpenAPI interfaces [#332], and generator/CLI code updated with parameter handling improvements [#333].
Out of Scope Changes check ✅ Passed All code changes are within scope of the three linked issues: dependency replacements, interface migrations, schema type inference refactoring, and validation behavior updates align with stated objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch microsoft-openapi-v3

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 20, 2026

Codecov Report

❌ Patch coverage is 67.64706% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.02%. Comparing base (8522277) to head (098c6af).
⚠️ Report is 21 commits behind head on main.

Files with missing lines Patch % Lines
src/HttpGenerator.Core/HttpFileGenerator.cs 63.33% 5 Missing and 6 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #349      +/-   ##
==========================================
+ Coverage   81.92%   85.02%   +3.10%     
==========================================
  Files          12       12              
  Lines         603      521      -82     
  Branches       92      103      +11     
==========================================
- Hits          494      443      -51     
+ Misses         83       56      -27     
+ Partials       26       22       -4     
Flag Coverage Δ
unittests 85.02% <67.64%> (+3.10%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/HttpGenerator.Core/HttpFileGenerator.cs (1)

445-456: ⚠️ Potential issue | 🟠 Major

Use a stable synthetic key for unnamed parameters.

The new null-name path still doesn't actually tolerate unnamed parameters safely: parameter.ToString() can leak a CLR/debug string into query keys and @variables, and the non-OneRequestPerFile branch still produces names like Operation_ when parameter.Name is blank. That can generate malformed .http files instead of a best-effort placeholder.

💡 One way to stabilize the fallback
+    private static string GetParameterKey(IOpenApiParameter parameter, ref int unnamedIndex)
+        => string.IsNullOrWhiteSpace(parameter.Name)
+            ? $"param{++unnamedIndex}"
+            : parameter.Name!;
+
     private static Dictionary<string, string> AppendParameters(
         OpenApiDocument document,
         KeyValuePair<string, IOpenApiPathItem> operationPath,
         GeneratorSettings settings,
         OpenApiOperation operation,
@@
-        var parameterNameMap = new Dictionary<string, string>();
+        var parameterNameMap = new Dictionary<string, string>();
+        var unnamedIndex = 0;
         foreach (var parameter in parameters)
         {
+            var parameterKey = GetParameterKey(parameter, ref unnamedIndex);
             var parameterName = GetParameterName(
                 settings,
                 document,
                 operation,
                 operationNameGenerator,
                 verb,
                 operationPath.Key,
-                parameter);
-            parameterNameMap[parameter.Name ?? parameter.ToString()] = parameterName;
+                parameter,
+                parameterKey);
+            parameterNameMap[parameterKey] = parameterName;
@@
     private static string GetParameterName(
         GeneratorSettings settings,
         OpenApiDocument document,
         OpenApiOperation operation,
         IOperationNameGenerator operationNameGenerator,
         string verb,
         string operationPathKey,
-        IOpenApiParameter parameter)
+        IOpenApiParameter parameter,
+        string parameterKey)
     {
         if (settings.OutputType == OutputType.OneRequestPerFile)
-            return parameter.Name ?? parameter.ToString();
+            return parameterKey;
@@
-        return $"{name}_{parameter.Name}";
+        return $"{name}_{parameterKey}";
     }

Also applies to: 488-506

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/HttpGenerator.Core/HttpFileGenerator.cs` around lines 445 - 456, The
issue is that unnamed parameters use unstable fallbacks (parameter.ToString())
and produce empty or duplicate parameter names (e.g., "Operation_") leading to
malformed .http files; instead, use a stable synthetic key and placeholder name:
when building parameterNameMap in HttpFileGenerator (the parameters loop that
calls GetParameterName) replace parameter.Name ?? parameter.ToString() with a
deterministic key like $"_unnamed_{parameterIndex}" (use the loop index or a
running counter) and ensure GetParameterName returns a non-empty placeholder
(e.g., "param_{index}" or "unnamed_{index}") for blank names so both the
parameterNameMap and the non-OneRequestPerFile branch produce stable, valid
identifiers; apply the same change to the corresponding code block around the
other occurrence (the 488-506 region).
🧹 Nitpick comments (1)
src/HttpGenerator.Tests/GenerateCommandTests.cs (1)

86-99: Rename this test now that it asserts success.

Should_Fail_Validating_V31_Spec now expects exit code 0, so the test name documents the opposite behavior. Renaming it (and keeping a separate invalid-spec case if you still want a negative assertion here) will make the new 3.1 validation behavior much easier to read.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/HttpGenerator.Tests/GenerateCommandTests.cs` around lines 86 - 99, The
test method Should_Fail_Validating_V31_Spec currently asserts a success exit
code (0); rename the test to reflect the new expectation (e.g.,
Should_Pass_Validating_V31_Spec or Should_Succeed_Validating_V31_Spec) and
update any references/usages accordingly; keep the test body
(settings.SkipValidation, TestFile.CreateSwaggerFile, and the call to
sut.ExecuteAsync(context, settings, ...).Should().Be(0)) unchanged, and if you
still need a negative coverage case add a separate test that asserts a non-zero
exit for an invalid spec.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/HttpGenerator.Core/HttpFileGenerator.cs`:
- Around line 509-516: The switch on parameter.Schema.Type in
GetParameterDefaultValue is using ToString() which fails for flagged
JsonSchemaType values (e.g., String|Null); update the logic to handle flag enums
by extracting identifiers via OpenApiTypeMapper.ToIdentifiers(schema.Type) or by
testing flags with schema.Type.HasFlag(JsonSchemaType.Null) and similar checks,
then base the switch/selection on those identifiers (lowercased) or flag checks
to return correct defaults for nullable/combined types; adjust the related
switch blocks in GetParameterDefaultValue and any other schema-type switches
mentioned so they use the identifiers or HasFlag approach rather than
ToString().

---

Outside diff comments:
In `@src/HttpGenerator.Core/HttpFileGenerator.cs`:
- Around line 445-456: The issue is that unnamed parameters use unstable
fallbacks (parameter.ToString()) and produce empty or duplicate parameter names
(e.g., "Operation_") leading to malformed .http files; instead, use a stable
synthetic key and placeholder name: when building parameterNameMap in
HttpFileGenerator (the parameters loop that calls GetParameterName) replace
parameter.Name ?? parameter.ToString() with a deterministic key like
$"_unnamed_{parameterIndex}" (use the loop index or a running counter) and
ensure GetParameterName returns a non-empty placeholder (e.g., "param_{index}"
or "unnamed_{index}") for blank names so both the parameterNameMap and the
non-OneRequestPerFile branch produce stable, valid identifiers; apply the same
change to the corresponding code block around the other occurrence (the 488-506
region).

---

Nitpick comments:
In `@src/HttpGenerator.Tests/GenerateCommandTests.cs`:
- Around line 86-99: The test method Should_Fail_Validating_V31_Spec currently
asserts a success exit code (0); rename the test to reflect the new expectation
(e.g., Should_Pass_Validating_V31_Spec or Should_Succeed_Validating_V31_Spec)
and update any references/usages accordingly; keep the test body
(settings.SkipValidation, TestFile.CreateSwaggerFile, and the call to
sut.ExecuteAsync(context, settings, ...).Should().Be(0)) unchanged, and if you
still need a negative coverage case add a separate test that asserts a non-zero
exit for an invalid spec.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 874708f1-ac2d-45c5-a68f-d4efdc8cd8d4

📥 Commits

Reviewing files that changed from the base of the PR and between 4c4c124 and a0f38eb.

📒 Files selected for processing (10)
  • src/HttpGenerator.Core/HttpFileGenerator.cs
  • src/HttpGenerator.Core/HttpGenerator.Core.csproj
  • src/HttpGenerator.Core/OpenApiDocumentFactory.cs
  • src/HttpGenerator.Core/OperationNameGenerator.cs
  • src/HttpGenerator.Tests/GenerateCommandTests.cs
  • src/HttpGenerator/GenerateCommand.cs
  • src/HttpGenerator/HttpGenerator.csproj
  • src/HttpGenerator/Validation/OpenApiStats.cs
  • src/HttpGenerator/Validation/OpenApiValidationResult.cs
  • src/HttpGenerator/Validation/OpenApiValidator.cs
💤 Files with no reviewable changes (1)
  • src/HttpGenerator/HttpGenerator.csproj

Comment thread src/HttpGenerator.Core/HttpFileGenerator.cs Outdated
- Test BaseUrl environment variable templates
- Test SkipHeaders flag
- Test authorization header loading from environment
- Test custom authorization variable name
- Test unique filename generation for duplicate operations
- Test custom content type
- Test empty specs and operations
…Extensions, OpenApiValidator

- PrivacyHelper: test empty input, non-authorization text passthrough, multiple headers
- SupportKeyInitializer: test non-ISupportProperties telemetry path
- StringExtensions: test empty strings, null inputs, empty prefix
- OpenApiValidator: test IsValid property true/false branches
- Add GenerateWithSpecificArgs function for targeted tests
- Test authorization header with Bearer token
- Test loading authorization from environment variable
- Test skip-headers flag
- Test custom content-type (XML)
- Test environment variable base URL template
- Apply additional tests to petstore fixtures for v2.0 and v3.0
- Test sample JSON generation for request bodies
- Test query parameter variable generation
- Test parameter default values (integer, number, boolean, string)
- Test custom headers in generated content
- Test IntelliJ test generation
@sonarqubecloud
Copy link
Copy Markdown

@christianhelle christianhelle merged commit d97368b into main Mar 20, 2026
15 of 16 checks passed
@christianhelle christianhelle deleted the microsoft-openapi-v3 branch March 20, 2026 22:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

1 participant