stoplightio / spectral

A flexible JSON/YAML linter for creating automated style guides, with baked in support for OpenAPI (v3.1, v3.0, and v2.0), Arazzo v1.0, as well as AsyncAPI v2.x.
https://stoplight.io/spectral
Apache License 2.0
2.47k stars 233 forks source link

Apply overrides to external files referenced from the root document #2195

Open dpashkevich opened 2 years ago

dpashkevich commented 2 years ago

User story. As a developer on a large API project, I can do apply rule overrides not just to the root document, but to external files as well, so that I can maintain the file structure that makes sense for my team.

Is your feature request related to a problem? This is a feature request to effectively fix the caveat that was discovered in #2096 and currently documented at https://meta.stoplight.io/docs/spectral/e5b9616d6d50c-custom-rulesets#caveats:

Please bear in mind that overrides are only applied to the root documents. If your documents have any external dependencies, i.e. $refs, the overrides won't apply.

Example: Given the following 2 YAML documents

# my-document.yaml
openapi: "3.1.0"
paths: {}
components:
  schemas:
    User:
      $ref: "./User.yaml"
# User.yaml
title: ""
type: object
properties:
  id:
    type: string
required:
  - id

and the ruleset below

{
  "rules": {
    "empty-title-property": {
      "message": "Title must not be empty",
      "given": "$..title",
      "then": {
        "function": "truthy"
      }
    }
  },
  "overrides": [
    {
      "files": ["User.yaml"],
      "rules": {
        "empty-title-property": "off"
      }
    }
  ]
}

running spectral lint my-document.yaml will result in:

/project/User.yaml
1:8 warning empty-title-property Title must not be empty title
✖ 1 problem (0 errors, 1 warning, 0 infos, 0 hints)

while executing spectral lint User.yaml will output

No results with a severity of 'error' or higher found!

This is a very odd an unexpected behavior. It's common to have things such as schema definitions in external files on large API spec projects, but looks like today there's no way to properly apply linter rule overrides to these files.

The only workaround is to keep your shared components in one large my-document.yaml file. This will work:

    {
      "files": ["openapi.yaml#components/schemas/User"],
      "rules": {
        "empty-title-property": "off"
      }
    }
  ]

But as I said, it's undesirable when describing a large API (e.g. a public API). Our team was refactoring a API spec project and were surprised to find out that we can no longer apply overrides to the same shared components we used to have, once we extracted them to external files.

Describe the solution you'd like

Given the setup described above (my-document.yaml with a root document, User.yaml with a User model, and the corresponding "overrides" block in .spectral.json), running spectral lint my-document.yaml should result in no errors:

No results with a severity of 'error' or higher found!

When Spectral resolves $refs, it should keep track of the original pointers and check if there are overrides defined for these locations.

ahemanna commented 2 years ago

I would vote for this feature too. We have a defined common types that will be used across different APIs and we would rather reference the common types using $ref than define them in each API. And we have certain definitions we would want to skip linting and not being able to override them is a huge inconvenience.

kscheirer commented 1 year ago

How can I vote for this more? :D

mhays118 commented 1 year ago

I'd also like to vote for this. This is necessary for managing large APIs.

tmeckel commented 1 year ago

Much needed because when you reference the schema component definition from https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.0/schema.yaml#/definitions/Schema like this:

- type: object
  properties:
    identifier:
      type: string
      description: |
        Specifies the name of the parameter, whose value will be used as the identifier for a deployment.
    schema:
      $ref: 'https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.0/schema.yaml#/definitions/Schema'

You'll end up with errors like this:

https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/schemas/v3.0/schema.yaml
  42:23  error  oas3-schema                             Property "patternProperties" is not expected to be here.  definitions.Reference.patternProperties
 208:18  error  must-define-a-format-for-number-types   Numeric properties must have valid format specified       definitions.Schema.properties.multipleOf
 212:15  error  must-define-a-format-for-number-types   Numeric properties must have valid format specified       definitions.Schema.properties.maximum
 217:15  error  must-define-a-format-for-number-types   Numeric properties must have valid format specified       definitions.Schema.properties.minimum
 222:17  error  must-define-a-format-for-integer-types  Numeric properties must have valid format specified       definitions.Schema.properties.maxLength
 225:17  error  must-define-a-format-for-integer-types  Numeric properties must have valid format specified       definitions.Schema.properties.minLength
 232:16  error  must-define-a-format-for-integer-types  Numeric properties must have valid format specified       definitions.Schema.properties.maxItems
 235:16  error  must-define-a-format-for-integer-types  Numeric properties must have valid format specified       definitions.Schema.properties.minItems
 242:21  error  must-define-a-format-for-integer-types  Numeric properties must have valid format specified       definitions.Schema.properties.maxProperties
 245:21  error  must-define-a-format-for-integer-types  Numeric properties must have valid format specified       definitions.Schema.properties.minProperties
 331:23  error  oas3-schema                             Property "patternProperties" is not expected to be here.  definitions.Schema.patternProperties
 363:23  error  oas3-schema                             Property "patternProperties" is not expected to be here.  definitions.XML.patternProperties
 629:23  error  oas3-schema                             Property "patternProperties" is not expected to be here.  definitions.ExternalDocumentation.patternProperties

And currently there's no way to tell spectral to ignore the external/imported schema. Or even, as described in the solution of the original poster, a way to customize the rules for a specific external schema.

https://github.com/stoplightio/spectral/issues/2143#issuecomment-1113546044

https://github.com/stoplightio/spectral/blob/develop/docs/guides/4d-overrides.md#external-dependencies-refs

Renders spectral relatively useless for me right now.

dpashkevich commented 1 year ago

Any updates on this? This limitation is still an issue for us. The inability to define overrides on external schemas forces us to entirely turn off some rules that we would otherwise want to be on for the general case, thus limiting the value we're getting out of Spectral.

tintin92350 commented 11 months ago

May be spectral can merge all external ref into the current linting file ? Then it lint the whole but the most tricked part is for extensions. I like to use VS Code extension to directly lint my specification and it would be great to have the feature in the extension too.

Moribund7 commented 1 month ago

Is there any update regarding this feature?