Redocly / redocly-cli

⚒️ Redocly CLI makes OpenAPI easy. Lint/validate to any standard, generate beautiful docs, and more.
https://redocly.com/docs/cli/
MIT License
852 stars 129 forks source link

`spec-strict-ref` rule failing when $ref used in components section #1523

Closed danielbecroft closed 4 weeks ago

danielbecroft commented 2 months ago

We're starting to implement the redocly-cli linter into our API documentation.

We have separated out our API definition, specifically with the components section into separate files, but the @redocly/cli lint command is failing on rule spec-strict-rules.

In our openapi.yaml file we have:

components:
  parameters:
    $ref: "./parameters/_index.yaml"
  securitySchemes:
    $ref: "./security-schemes.yaml"
  schemas:
    $ref: "./schemas/_index.yaml"
  examples:
    $ref: "./examples/_index.yaml"

The bundle etc commands all reference these files correctly and pull in the information, but the linter rule is failing.

I'm not sure if this is a bug with the lint rule itself, or an issue with how we have defined our documentation (although given all other operations work, my feeling is it's with the rule).

tatomyr commented 2 months ago

Do you mean the spec-strict-refs rule? What is the error? What OpenAPI and Redocy CLI versions are?

danielbecroft commented 2 months ago

Sorry @tatomyr , yes I meant the spec-strict-refs rule. My openapi.yaml version is 3.1.0 (but also fails on 3.0.0), and my Redocly CLI version is 1.11.0.

A set of files that demonstrates the problem is below:

openapi.yaml

openapi: 3.0.0
info:
  version: v1
  title: Example

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

paths:
  /foo:
    get:
      responses:
        "200": 
          description: The list of foo.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/FooModel"

schemas.yaml

FooModel:
  type: object
  properties:
`    Id:
      type: number
    Name:
      type: string
    DateOfBirth:
      type: string
      format: date

redocly.yaml

extends: []

rules:
  spec: error
  spec-strict-refs: error

Running redocly bundle openapi.yaml, correctly expands the $ref under the components/schemas:

> redocly bundle openapi.yaml
(node:38808) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
bundling .\openapi.yaml...
openapi: 3.0.0
info:
  version: v1
  title: Example
paths:
  /foo:
    get:
      responses:
        '200':
          description: The list of foo.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/FooModel'
components:
  schemas:
    FooModel:
      type: object
      properties:
        Id:
          type: number
        Name:
          type: string
        DateOfBirth:
          type: string
          format: date

Running redocly lint throws the error on the spec-strict-refs rule:

(node:71364) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
validating .\openapi.yaml...
[1] openapi.yaml:8:5 at #/components/schemas/$ref

Field $ref is not expected here.

 6 | components:
 7 |   schemas:
 8 |     $ref: "./schemas.yaml"
 9 |
10 | paths:

Error was generated by the spec-strict-refs rule.

.\openapi.yaml: validated in 11ms

❌ Validation failed with 1 error.
run `redocly lint --generate-ignore-file` to add all problems to the ignore file.
tatomyr commented 2 months ago

According to the OAS 3/3.1 specification, the schemas property inside the components must be a map of schema objects (not a $ref): https://spec.openapis.org/oas/v3.1.0#components-object. Although Redocly CLI correctly resolves the $refs in that case, your example is not compliant to the spec (see more about this here). That's what the spec-strict-refs rule is about.

You have several options here. First, you can go along with the spec and use $refs in other places, e.g.:

openapi: 3.0.0
info:
  version: v1
  title: Example

components:
  schemas:
    FooModel:
      $ref: "./schemas.yaml#/FooModel"

Second, you can bypass the components section and refer to the schemas.yaml file directly (I'd expect this to be the best option), e.g.:

paths:
  /foo:
    get:
      responses:
        '200':
          description: The list of foo.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: 'schemas.yaml#/FooModel'

Then, you can turn off this rule or make its severity warning instead of error. And finally, you can suppress this rule for this particular case by generating the ignore file as the linter suggests:

run `redocly lint --generate-ignore-file` to add all problems to the ignore file.
lornajane commented 4 weeks ago

Thanks @tatomyr for this clear explanation. The tool is correctly identifying the $ref doesn't meet the strict standard, so I'll close this issue.