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

Possible bug while bundling

Open bal-stan opened this issue 3 years ago • 5 comments

Describe the bug The bundle command does not bundle schemas and parameters properly

To Reproduce

  1. Extract attached zip openapi.zip
  2. Run:
docker run --rm -v $PWD:/spec redocly/openapi-cli bundle /spec/openapi-zip/Openapi.yaml -o /spec/openapi-zip/_build/Openapi.yaml --lint

Expected behavior File is bundled so that no $ref are present under components.schemas.Pet and components.parameters.PetId

Logs Output of docker command:

No configurations were defined in extends -- using built in recommended configuration by default.
[openapi.zip](https://github.com/Redocly/openapi-cli/files/8554891/openapi.zip)

Woohoo! Your OpenAPI definitions are valid. 🎉

bundling /spec/openapi/Openapi.yaml...
📦 Created a bundle for /spec/openapi-zip/Openapi.yaml at /spec/openapi-zip/_build/Openapi.yaml 55ms.

OpenAPI definition OpenApi 3.0.3

openapi-cli Version(s) latest docker image as of date of posting this issue

Node.js Version(s) N/A

Additional context N/A

bal-stan avatar Apr 25 '22 13:04 bal-stan

I don't think this is a bug bundling (perhaps a bug linting).

Source: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#componentsObject

Excerpt from the OpenAPI definition:

components:
  schemas:
    $ref: "./schemas/_index.yaml"
  parameters:
    $ref: "./parameters/_index.yaml"

In the snippet above, schemas and parameters are part of components and should contain a map of strings to schemas or reference objects.

It would be correct like this:

components:
  schemas:
    Pet:
      $ref: ./schemas/Pet.yaml
  parameters:
    PetId:
      $ref: ./parameters/PetId.yaml

On the other hand, bundle will dynamically create the components if they are used as $ref to files from your operations. For example, your operation is already set up like this:

get:
  tags:
    - pet
  summary: Info for a specific pet
  operationId: showPetById
  parameters:
    - $ref: '../parameters/PetId.yaml'
  responses:
    '200':
      description: Expected response to a valid request
      content:
        application/json:
          schema:
            $ref: "../schemas/Pet.yaml"
    '400':
      description: Error

If we remove components from the root file (I commented it out here):

openapi: 3.0.3
servers:
  - url: 'http://example.com/v1'
info:
  description: >-
    Petstore
  version: 0.1.0
  title: Petstore
  license:
    name: license
    url: 'https://example.com'
tags:
  - name: pet
    description: pet store
paths:
  /pets/{petId}:
    $ref: "./paths/Pet.yaml"
# components:
#   schemas:
#     $ref: "./schemas/_index.yaml"
#   parameters:
#     $ref: "./parameters/_index.yaml"

Then the result of bundle is:

bundling Openapi.yaml...
openapi: 3.0.3
servers:
  - url: http://example.com/v1
info:
  description: Petstore
  version: 0.1.0
  title: Petstore
  license:
    name: liscense
    url: https://example.com
tags:
  - name: pet
    description: pet store
paths:
  /pets/{petId}:
    get:
      tags:
        - pet
      summary: Info for a specific pet
      operationId: showPetById
      parameters:
        - $ref: '#/components/parameters/PetId'
      responses:
        '200':
          description: Expected response to a valid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Pet'
        '400':
          description: Error
components:
  parameters:
    PetId:
      name: petId
      in: path
      required: true
      description: The id of the pet to retrieve
      schema:
        type: string
  schemas:
    Pet:
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        tag:
          type: string

adamaltman avatar Apr 25 '22 18:04 adamaltman

Thanks for taking the time to look into this.

I did try your solutions.

  1. When I replaced components like this:
components:
  schemas:
    Pet:
      $ref: ./schemas/Pet.yaml
  parameters:
    PetId:
      $ref: ./parameters/PetId.yaml

I got duplicated components:

components:
  schemas:
    Pet:
      type: object
      required:
        ...
      properties:
        ...
    Pet-2:
      type: object
      required:
        ...
      properties:
        ...
  parameters:
    PetId:
      name: petId
      ...
    PetId-2:
      name: petId
      ...

The bundler spits out the following warning:

bundling /spec/openapi/spec/openapi.yaml...
[1] openapi/spec/paths/Pet.yaml:7:7 at #/get/parameters/0

Two schemas are referenced with the same name but different content. Renamed PetId to PetId-2.

5 | operationId: showPetById
6 | parameters:
7 |   - $ref: '../parameters/PetId.yaml'
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8 | responses:
9 |   '200':

Warning was generated by the bundler rule.

[2] openapi/spec/paths/Pet.yaml:14:13 at #/get/responses/200/content/application~1json/schema

Two schemas are referenced with the same name but different content. Renamed Pet to Pet-2.

12 | application/json:
13 |   schema:
14 |     $ref: "../schemas/Pet.yaml"
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
  1. Commenting out the components and letting them be generated works

  2. I also tried adding the -d option to the CLI arguments - this produced the same result as 2 but without having to comment out the components section.

Furthermore, both 2 and 3 produce a strange bundle with a bunch of &refs and *refs:

paths:
  /pets/{petId}:
    get:
      tags:
        - pet
      summary: Info for a specific pet
      operationId: showPetById
      parameters:
        - name: petId
          ...
          schema: &ref_0
            type: string
      responses:
        '200':
          description: Expected response to a valid request
          content:
            application/json:
              schema:
                type: object
                required: &ref_1
                 ...
                properties: &ref_2
                 ...
components:
  parameters:
    PetId:
      name: petId
     ...
      schema: *ref_0
  schemas:
    Pet:
      type: object
      required: *ref_1
      properties: *ref_2

But OpenAPI generator seems to parse it without errors.

bal-stan avatar Apr 28 '22 09:04 bal-stan

@bal-stan you did not quite try my solution. Do not put this:

components:
  schemas:
    Pet:
      $ref: ./schemas/Pet.yaml
  parameters:
    PetId:
      $ref: ./parameters/PetId.yaml

Those will be generated automatically when they are recognized as referenced during the bundling process. If there is a naming collision, we add the -2, etc... You can see from my resulting bundle above there is no double schemas.

adamaltman avatar Apr 28 '22 12:04 adamaltman

@adamaltman i tried that - that works. See 2. in my previous comment.

bal-stan avatar May 05 '22 09:05 bal-stan

Chances are, this will be resolved with this.

tatomyr avatar Jun 14 '22 09:06 tatomyr

Should be fixed in v1.0.0-beta.127.

tatomyr avatar May 25 '23 14:05 tatomyr