Redocly/redocly-cli

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

danielbecroft opened this issue · 4 comments

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).

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

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.

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.

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.