OpenAPITools / openapi-diff

Utility for comparing two OpenAPI specifications.
Apache License 2.0
810 stars 154 forks source link

Adding/Removing/Changing extensions is not detected #487

Closed michael-schnell closed 1 year ago

michael-schnell commented 1 year ago

Adding below "x-bar", removing "x-foo" and changing the content of "x-extensible-enum" is not detected.

V1

application/json:
  schema:
    type: string
    x-extensible-enum: [one, two]
    x-foo: Foo

V2

application/json:
  schema:
    type: string
    x-extensible-enum: [one, two, three]
    x-bar: Bar
michael-schnell commented 1 year ago

Seems the Problem is that all Extensions require a dedicated `ExtensionDiff" implementation. Otherwise nothing is detected.

My expectation was, that at least some generic variants for basic types are available. So just compare two strings in case there is no dedicated ExtensionDiff service is available.

It would be a kind of "fallback" in case no specific service extension is available.

michael-schnell commented 1 year ago

For the poor souls arrving at this closed issue, here a description what to do:

1) Add a file src/main/resources/META-INF/services/org.openapitools.openapidiff.core.compare.ExtensionDiff in your Maven project 2) In that file add a line with the FQN of every custom ExtensionDiff implementation you require (Like org.my.domain.xenumvalue.XEnumExtensionDiff) 3) Create a class that implements Changed for your extension type

    public class ChangedXEnum<T> extends ChangedList<T> {
        public ChangedXEnum(List<T> oldValue, List<T> newValue, DiffContext context) {
            super(oldValue, newValue, context);
        }
        @Override
        public DiffResult isItemsChanged() {
            if (context.isRequest() && getMissing().isEmpty()
                    || context.isResponse() && getIncreased().isEmpty()) {
                return DiffResult.COMPATIBLE;
            }
            return DiffResult.INCOMPATIBLE;
        }
    }
  1. Create a class that implements ExtensionDiff and returns the Changed implementation you created in step 3) - Caution: Must be exactly the package and name you added in the META-INF file in step 1)

    public class XEnumExtensionDiff implements ExtensionDiff {
    
        private OpenApiDiff openApiDiff;
    
        @Override
        public ExtensionDiff setOpenApiDiff(OpenApiDiff openApiDiff) {
            this.openApiDiff = openApiDiff;
            return this;
        }
        @Override
        public String getName() {
            return "extensible-enum"; // Name as in JSON/YAML, without "x-"
        }
        @Override
        public Changed diff(Change<?> change, DiffContext context) {
            // Change contains the raw old/new data from JSON/YAML (like `List` in the case of enum literals)
            final List<?> oldList = change.getOldValue() == null ? Collections.emptyList() : (List<?>) change.getOldValue();
            final List<?> newList = change.getNewValue() == null ? Collections.emptyList() : (List<?>) change.getNewValue();
            return ListDiff.diff(new ChangedXEnum(oldList, newList, context));
        }
    }

    Now openapi-diff should be able to detect changes of your custom x-tension.