Map [Obsolete] attribute to deprecated in OpenAPI documents - #66355
Conversation
Add built-in support for mapping ObsoleteAttribute to the OpenAPI deprecated flag on operations, schemas, and schema properties. - Operations: endpoints with [Obsolete] on the method or added via WithMetadata(new ObsoleteAttribute()) now emit deprecated: true - Schemas: types decorated with [Obsolete] produce deprecated: true on the component schema - Properties: [Obsolete] on properties sets deprecated: true on the property schema (inline) or on the schema reference (componentized) Addresses dotnet#63494 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds first-class support in the OpenAPI document generator for mapping .NET [Obsolete] metadata to the OpenAPI deprecated: true flag across operations and JSON schemas, reducing the need for custom transformers.
Changes:
- Mark OpenAPI operations as deprecated when
ObsoleteAttributeis present in endpoint metadata. - Mark component schemas and inline property schemas as deprecated when the underlying type/property is
[Obsolete]. - Support referenced-property deprecation via a new
x-ref-deprecatedannotation, plus corresponding parsing and tests.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/OpenApi/src/Services/Schemas/OpenApiSchemaService.cs | Maps [Obsolete] on types/properties to schema-level deprecated or to a ref-specific annotation for componentized properties. |
| src/OpenApi/src/Services/OpenApiDocumentService.cs | Sets OpenApiOperation.Deprecated based on ObsoleteAttribute in endpoint metadata. |
| src/OpenApi/src/Services/OpenApiConstants.cs | Adds x-ref-deprecated constant for ref-only schema deprecation. |
| src/OpenApi/src/Schemas/OpenApiSchemaKeywords.cs | Adds the deprecated JSON schema keyword constant. |
| src/OpenApi/src/Schemas/OpenApiJsonSchema.Helpers.cs | Parses deprecated and x-ref-deprecated when reading schema JSON into OpenApiSchema. |
| src/OpenApi/src/Extensions/OpenApiDocumentExtensions.cs | Propagates x-ref-deprecated metadata onto OpenApiSchemaReference.Deprecated. |
| src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiSchemaService/OpenApiSchemaService.Annotations.cs | Adds tests for type/property deprecation (inline + referenced). |
| src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiDocumentService/OpenApiDocumentServiceTests.Operations.cs | Adds tests for operation deprecation via attribute, metadata, and MVC action attribute. |
|
@dotnet-policy-service agree company="Microsoft" |
Avoid calling GetCustomAttributes(inherit: false) twice on the same type by caching the result in a local variable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Looks like this PR hasn't been active for some time and the codebase could have been changed in the meantime. |
mikekistler
left a comment
There was a problem hiding this comment.
Looks good to me! 👍
But I'll defer to the eng team on the details.
…penapi # Conflicts: # src/OpenApi/src/Services/Schemas/OpenApiSchemaService.cs
| if (typeAttributes.OfType<ObsoleteAttribute>().Any()) | ||
| { | ||
| schema[OpenApiSchemaKeywords.DeprecatedKeyword] = true; | ||
| } |
There was a problem hiding this comment.
This part here might not be needed when we get dotnet/runtime#130665, I think.
There was a problem hiding this comment.
Looks like both PRs are for the same thing, unless I'm misreading?
There was a problem hiding this comment.
Ah, didn't realize that one was in the runtime instead.
| if (propertyAttributes.OfType<ObsoleteAttribute>().Any()) | ||
| { | ||
| schema[OpenApiSchemaKeywords.DeprecatedKeyword] = true; | ||
| } |
There was a problem hiding this comment.
Same here, I think this won't be needed when dotnet/runtime#130665 gets in.
There was a problem hiding this comment.
Do you know when that will be merged? This PR has been open since April, so not sure if the right move is to merge now and then remove this if it becomes redundant or just wait further.
There was a problem hiding this comment.
The PR was opened this week. It's merged now, so hopefully in couple of days or something we will get an updated runtime here with this change.
There was a problem hiding this comment.
Apologies, by "this PR" I was referring to the current one, #66355. I know the one you linked is recent :)
I guess we need to wait for the runtime version specified in the aspnetcore deps to be bumped to a version with your PR changes and then remove the now-duplicate logic updating the schema?
Is the runtime version an automatic or manual change?
There was a problem hiding this comment.
@fickleEfrit Oh sorry. I thought you had doubts about when the dotnet/runtime PR will get merged.
The version update is automatic. There are automatic pipelines and insertions that will flow the dotnet/runtime changes to dotnet/dotnet repo (known as VMR - Virtual Mono Repo). And once a new full .NET SDK is built from dotnet/dotnet, we get an insertion PR here that updates to that. Usually it doesn't take long.
Meanwhile, could you address the test improvements please so that the tests show the full document?
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 76a02683-9c07-4c55-bb01-9b0cefc90bb0
| } | ||
|
|
||
| [Fact] | ||
| public async Task SchemaDeprecated_HandlesObsoletePropertyWithSchemaReference() |
There was a problem hiding this comment.
I'm realizing that I might haven't got this test case correctly in the implementation I did in STJ, which I'm going to revisit.
I'm going to merge as-is for now but we should remember to clean up the implementation once the STJ change (potentially with a follow-up fix) flows.
|
/backport to release/11.0-preview7 |
|
Started backporting to |
|
@Youssef1313 backporting to git am output$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patch
Applying: Map [Obsolete] attribute to deprecated in OpenAPI documents
Applying: Cache type-level GetCustomAttributes call
error: sha1 information is lacking or useless (src/OpenApi/src/Services/Schemas/OpenApiSchemaService.cs).
error: could not build fake ancestor
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0002 Cache type-level GetCustomAttributes call
Error: The process '/usr/bin/git' failed with exit code 128 |
… documents Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com>
… documents (#67953) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com>
Map
[Obsolete]attribute todeprecatedin OpenAPI documentsMap
ObsoleteAttributetodeprecated: trueon OpenAPI operations, schemas, and schema properties.Description
Adds built-in support for mapping
ObsoleteAttributeto the OpenAPIdeprecatedflag on operations, schemas, and schema properties. Previously, users had to write customIOpenApiSchemaTransformerorIOpenApiOperationTransformerimplementations to achieve this.Operations
Endpoints with
[Obsolete]on the handler method (minimal APIs) or action method (MVC controllers), or added via.WithMetadata(new ObsoleteAttribute()), now automatically emitdeprecated: trueon the OpenAPI operation.Schemas (types)
Types decorated with
[Obsolete]producedeprecated: trueon the component schema.Schema properties
[Obsolete]on a property setsdeprecated: truedirectly on the property schema.[Obsolete]on a property whose type is componentized setsdeprecated: trueon theOpenApiSchemaReference, leaving the underlying component schema unchanged. This follows the same pattern used for[Description]→x-ref-description.Design notes
[Description]→descriptionand[Required]→required, which are all automatic with no opt-out.inherit: falseonGetCustomAttributesfor type-level checks, so a derived type does not inheritdeprecatedfrom an obsolete base class.IOpenApiSchemaTransformerorIOpenApiOperationTransformerto setDeprecated = false.Breaking change consideration
This is a behavioral change. Existing users with
[Obsolete]on types, properties, or endpoints will seedeprecated: trueappear in their generated OpenAPI documents after upgrading. This could affect downstream codegen tools. However, we believe this is the correct default — if something is marked obsolete in .NET, it should be reflected as deprecated in the API contract.If the team prefers an opt-in/opt-out mechanism (e.g., a property on
OpenApiOptions), that can be added.Tests
Fixes #63494