Fix #357: ignore changes inside readOnly properties in requests

IN
3d ago
+1113-0

Summary

Fixes #357.

Per the OpenAPI spec, readOnly properties are only sent in responses, never in requests. Changes nested inside a readOnly property of a requestBody therefore cannot affect the request contract and must not be reported as breaking.

Previously the property-level diff already filtered added/removed readOnly properties (isPropertyApplicable in SchemaDiffResult), but changes inside a shared readOnly property were still diffed: the nested ChangedSchema entries ended up in ChangedOpenApi#getChangedSchemas and flagged the whole diff backward incompatible, while the rendered report showed nothing ("broke backward compatibility" with an empty change log).

Change

In SchemaDiffResult.diff, the shared-property loop now skips the schema diff for properties marked readOnly on both sides in a request context, mirroring how the existing isPropertyApplicable pattern treats readOnly/writeOnly for added/removed properties:

  • The readOnly flag itself is still compared: when it differs between old and new, one side is not readOnly and the property is recursed into as before, so the existing REQUEST_READONLY_INCREASED / REQUEST_READONLY_REQUIRED_DECREASED back-compat checks (covered by ReadOnlyBCTest) keep working.
  • Response-side behavior is unchanged: a readOnly property in a response and a writeOnly property in a response are still reported (locked with tests).
  • Nested readOnly objects are covered: skipping the diff at the outermost readOnly property prunes the whole subtree, so no recursion is added.

Repro from the issue (before/after)

Before:

==========================================================================
==                            API CHANGE LOG                            ==
==========================================================================
                                   API                                    
--------------------------------------------------------------------------
--                                Result                                --
--------------------------------------------------------------------------
                 API changes broke backward compatibility                 
--------------------------------------------------------------------------

After:

No differences. Specifications are equivalent

Tests

New Issue357Test (fixtures from the issue):

  • changesInsideReadOnlyPropertyInRequestAreIgnored — the issue's old/new specs now produce no changed operations, no changed schemas, and an unchanged result.
  • changesInsideWriteOnlyPropertyInResponseAreStillReported — counter-case locking current behavior: a change inside a writeOnly property of a response schema is still reported and flagged incompatible.
  • changesInsideReadOnlyPropertyInResponseAreStillReported — guards the response side: a change inside a readOnly property of a response schema is still reported.

Full core module: mvn -pl core test — 273 tests, 0 failures (2 pre-existing skips in Swagger2CompatibilityTest).


Summary by cubic

Fixes #357 by ignoring changes nested inside readOnly properties in request bodies, which per the OpenAPI spec are never sent by clients and therefore can't affect the request contract.

  • Skips schema diffing for shared properties marked readOnly on both sides in a request context, resolving $ref wrappers before checking the flag.
  • Also drops the skipped property from the parent required diff, so adding a response-only field to required no longer flags the request as breaking.
  • When the readOnly flag itself differs between old and new, the property is still recursed into so the existing back-compat checks keep working.
  • Response-side behavior is unchanged: changes inside readOnly or writeOnly response properties are still reported.
  • Adds Issue357Test covering the issue repro, required/$ref variants, readOnly flag transitions, and response counter-cases.