redocly-cli icon indicating copy to clipboard operation
redocly-cli copied to clipboard

Lint: inaccurate examples warning produced when using inheritance + extension

Open denver-HJS opened this issue 3 years ago • 2 comments

Describe the bug The lint rule no-invalid-media-type-examples is inaccurately reported as being violated when using a combination of schema inheritance and extension.

To Reproduce Steps to reproduce the behavior:

  1. Given this .redocly.yaml file
lint:
  rules:
    no-unused-components: false
  1. And this OpenAPI file(s) -- scratch.oas3.yaml used in step 3.
openapi: 3.0.3
servers:
  - url: '//petstore.swagger.io/v2'
info:
  description: >-
    This is a sample server Petstore server.  You can find out more about
    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
    #swagger](http://swagger.io/irc/).  For this sample, you can use the api key
    `special-key` to test the authorization filters.
  version: 1.0.0
  title: Swagger Petstore
  termsOfService: 'http://swagger.io/terms/'
  contact:
    email: [email protected]
  license:
    name: Apache 2.0
    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
tags:
  - name: pet
    description: Everything about your Pets
    externalDocs:
      description: Find out more
      url: 'http://swagger.io'
  - name: store
    description: Access to Petstore orders
  - name: user
    description: Operations about user
    externalDocs:
      description: Find out more about our store
      url: 'http://swagger.io'
paths:
  /pet:
    post:
      tags:
        - pet
      summary: Add a new pet to the store
      description: ''
      operationId: addPet
      responses:
        '200':
          description: OK
          content:
            application/xml:
              schema:
                $ref: '#/components/schemas/PetBase'
            application/json:
              schema:
                $ref: '#/components/schemas/PetBase'
              examples:
                value:
                  $ref: "#/components/examples/ExamplePet"
        '405':
          description: Invalid input
      security:
        - petstore_auth:
            - 'write:pets'
            - 'read:pets'
      requestBody:
        $ref: '#/components/requestBodies/Pet'
    put:
      tags:
        - pet
      summary: Update an existing pet
      description: ''
      operationId: updatePet
      responses:
        '200':
          description: OK
        '400':
          description: Invalid ID supplied
        '404':
          description: Pet not found
        '405':
          description: Validation exception
      security:
        - petstore_auth:
            - 'write:pets'
            - 'read:pets'
      requestBody:
        $ref: '#/components/requestBodies/Pet'
  '/pet/{petId}':
    get:
      tags:
        - pet
      summary: Find pet by ID
      description: Returns a single pet
      operationId: getPetById
      parameters:
        - name: petId
          in: path
          description: ID of pet to return
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: successful operation
          content:
            application/xml:
              schema:
                $ref: '#/components/schemas/PetBase'
            application/json:
              schema:
                $ref: '#/components/schemas/PetBase'
        '400':
          description: Invalid ID supplied
        '404':
          description: Pet not found
      security:
        - api_key: []
    post:
      tags:
        - pet
      summary: Updates a pet in the store with form data
      description: ''
      operationId: updatePetWithForm
      parameters:
        - name: petId
          in: path
          description: ID of pet that needs to be updated
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: OK
        '405':
          description: Invalid input
      security:
        - petstore_auth:
            - 'write:pets'
            - 'read:pets'
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                name:
                  description: Updated name of the pet
                  type: string
                status:
                  description: Updated status of the pet
                  type: string
    delete:
      tags:
        - pet
      summary: Deletes a pet
      description: ''
      operationId: deletePet
      parameters:
        - name: api_key
          in: header
          required: false
          schema:
            type: string
        - name: petId
          in: path
          description: Pet id to delete
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: OK
        '400':
          description: Invalid ID supplied
        '404':
          description: Pet not found
      security:
        - petstore_auth:
            - 'write:pets'
            - 'read:pets'
  /cat:
    post:
      tags:
        - pet
      summary: Add a new cat to the store
      description: ''
      operationId: addCat
      responses:
        '200':
          description: OK
          content:
            application/xml:
              schema:
                $ref: '#/components/schemas/PetBase'
            application/json:
              schema:
                $ref: '#/components/schemas/Cat'
              examples:
                value:
                  $ref: "#/components/examples/ExampleCat"
        '405':
          description: Invalid input
      security:
        - petstore_auth:
            - 'write:pets'
            - 'read:pets'
      requestBody:
        $ref: '#/components/requestBodies/Pet'
externalDocs:
  description: Find out more about Swagger
  url: 'http://swagger.io'
components:
  responses:
    PetResponse:
      description: successful operation
      content:
        application/xml:
          schema:
            type: array
            items:
              $ref: '#/components/schemas/PetBase'
        application/json:
          schema:
            type: array
            items:
              $ref: '#/components/schemas/PetBase'
  requestBodies:
    Pet:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PetBase'
        application/xml:
          schema:
            $ref: '#/components/schemas/PetBase'
      description: Pet object that needs to be added to the store
      required: true
  securitySchemes:
    petstore_auth:
      type: oauth2
      flows:
        implicit:
          authorizationUrl: 'http://petstore.swagger.io/oauth/dialog'
          scopes:
            'write:pets': modify pets in your account
            'read:pets': read your pets
    api_key:
      type: apiKey
      name: api_key
      in: header
  schemas:
    PetBase:
      type: object
      required:
        - name
        - photoUrls
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
          example: doggie
        photoUrls:
          type: array
          xml:
            name: photoUrl
            wrapped: true
          items:
            type: string
      xml:
        name: Pet
    Cat:
      allOf:
        - $ref: "#/components/schemas/PetBase"
        - type: "object"
          properties:
            age:
              type: number
            breed:
              type: string
              enum:
                - domestic short hair
                - domestic long hair
           required:
              - breed
              - age
    ApiResponse:
      type: object
      properties:
        code:
          type: integer
          format: int32
        type:
          type: string
        message:
          type: string
  examples:
    ExamplePet:
      description: A pet
      value:
        name: Bernard
        photoUrls:
          - '/assets/bernard.jpg'
    ExampleCat:
      description: A feline
      value:
        name: Roger
        age: 12
        breed: domestic short hair
        photoUrls:
          - '/assets/roger.jpg'
  1. Run this command with these arguments... openapi ... npx openapi lint ./scratch.oas3.yml
  2. See error
No configurations were defined in extends -- using built in recommended configuration by default.

validating ./scratch.oas3.yml...
[1] scratch.oas3.yml:305:9 at #/components/examples/ExampleCat/value/age

Example value must conform to the schema: must NOT have additional properties `age`.

303 | value:
304 |   name: Roger
305 |   age: 12
306 |   breed: domestic short hair
307 |   photoUrls:

referenced from scratch.oas3.yml:192:15

Warning was generated by the no-invalid-media-type-examples rule.


[2] scratch.oas3.yml:306:9 at #/components/examples/ExampleCat/value/breed

Example value must conform to the schema: must NOT have additional properties `breed`.

304 | name: Roger
305 | age: 12
306 | breed: domestic short hair
307 | photoUrls:
308 |   - '/assets/roger.jpg'

referenced from scratch.oas3.yml:192:15

Warning was generated by the no-invalid-media-type-examples rule.


[3] scratch.oas3.yml:304:9 at #/components/examples/ExampleCat/value/name

Example value must conform to the schema: must NOT have additional properties `name`.

302 | description: A feline
303 | value:
304 |   name: Roger
305 |   age: 12
306 |   breed: domestic short hair

referenced from scratch.oas3.yml:192:15

Warning was generated by the no-invalid-media-type-examples rule.


[4] scratch.oas3.yml:307:9 at #/components/examples/ExampleCat/value/photoUrls

Example value must conform to the schema: must NOT have additional properties `photoUrls`.

305 | age: 12
306 | breed: domestic short hair
307 | photoUrls:
308 |   - '/assets/roger.jpg'
309 |

referenced from scratch.oas3.yml:192:15

Warning was generated by the no-invalid-media-type-examples rule.


./scratch.oas3.yml: validated in 74ms

Woohoo! Your OpenAPI definition is valid. 🎉
You have 4 warnings.

Expected behavior There should be no warnings related to the no-invalid-media-type-examples rule, since the ExampleCat example contains only known properties of the PetBase schema which Cat inherits from.

OpenAPI definition The attached zip file contains the OAS3 YAML file (v3.0.3) and the .redocly.yaml config being used

openapi-cli Version(s) @redocly/[email protected]

Node.js Version(s) v14.17.0

denver-HJS avatar Feb 09 '22 18:02 denver-HJS

I'm having the same issue. It seems the error stems from the linting trying to evaluate each schema separately instead of creating a schema including all the properties of the schemas invoked in the allOf.

alexcosta97 avatar Mar 07 '22 15:03 alexcosta97

Hi @alexcosta97 @denver-HJS ,

It seems the error stems from the linting trying to evaluate each schema separately instead of creating a schema including all the properties of the schemas invoked in the allOf.

This is exactly how the JSON schema specification describes it. And your schema is valid. The issue is we automatically enable: additionalProperties: false for schema validations. Usually people forget to enable this way a lot of issues will be not caught.

It is indeed a problem when using allOf. We will probably disable this inside of allOf statements.

Meanwhile, you can disable this behaviour with and it should validate just fine:

lint:
  rules:
    no-invalid-media-type-examples:
      disallowAdditionalProperties: false

Sorry it took so long to answer this. 🙈

RomanHotsiy avatar Mar 19 '22 05:03 RomanHotsiy

Hi @denver-HJS! This issue fixed in 1.0.0.beta-110 version. Please, let us know if it works for you, thx)

SmoliyY avatar Sep 26 '22 07:09 SmoliyY