IBM/openapi-validator

Unable to customize spectral config: Error: Cannot find module 'ajv'

Closed this issue ยท 5 comments

Disclaimer: I'm new to openapi-validator so it's very likely that I'm missing something obvious.

What I'm trying to do
Customize default rules and disable rule oas3-api-servers. Essentially I'm trying to follow instructions in README.md:

To completely disable a rule, use the severity of off. For example, to disable the operation-tags rule, specify the following in your Spectral ruleset file:

extends: ibm:oas
rules:
  operation-tags: off

What I have done
I added a file .spectral.yaml with the following content:

extends: ibm:oas
rules:
  oas3-api-servers: off

and then I'm running the Docker container of openapi-validator:

docker run --volume "<my-local-path>":/data jamescooke/openapi-validator -v -s -c /data/lint-openapi-settings.json /data/my-openapi-spec-file.json

Running the above, results in the following output:

Error: Cannot find module 'ajv'
Require stack:
- /usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/rulesets/evaluators.js
- /usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/spectral.js
- /usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/index.js
- /usr/local/lib/node_modules/ibm-openapi-validator/src/spectral/utils/spectral-validator.js
- /usr/local/lib/node_modules/ibm-openapi-validator/src/cli-validator/utils/validator.js
- /usr/local/lib/node_modules/ibm-openapi-validator/src/cli-validator/runValidator.js
- /usr/local/lib/node_modules/ibm-openapi-validator/src/cli-validator/index.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:893:15)
    at Function.resolve (internal/modules/cjs/helpers.js:94:19)
    at require (/usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/rulesets/evaluators.js:41:25)
    at Object.eval (eval at exports.evaluateExport (/usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/rulesets/evaluators.js:89:80), <anonymous>:3:13)
    at Object.exports.evaluateExport (/usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/rulesets/evaluators.js:89:94)
    at Object.exports.compileExportedFunction (/usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/rulesets/evaluators.js:109:32)
    at /usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/spectral.js:169:37
    at Array.reduce (<anonymous>)
    at Spectral.setRuleset (/usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/spectral.js:160:61)
    at Spectral.loadRuleset (/usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/spectral.js:155:14) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/rulesets/evaluators.js',
    '/usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/spectral.js',
    '/usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/index.js',
    '/usr/local/lib/node_modules/ibm-openapi-validator/src/spectral/utils/spectral-validator.js',
    '/usr/local/lib/node_modules/ibm-openapi-validator/src/cli-validator/utils/validator.js',
    '/usr/local/lib/node_modules/ibm-openapi-validator/src/cli-validator/runValidator.js',
    '/usr/local/lib/node_modules/ibm-openapi-validator/src/cli-validator/index.js'
  ]
}

If I remove/rename .spectral.yaml the command above works fine and shows me expected warnings/errors in my OpenAPI spec file (including oas3-api-servers that I would like to remove).

(FYI: lint-openapi-settings.json is the file generated by lint-openapi init with a few customizations on casing rules - these work fine).

Any suggestions on what I'm doing wrong?

Maybe related question: The docs describe that I should customize Spectral config in .spectral.yaml. When I generate .validaterc using lint-openapi init, then the generated file contains an (empty) spectral section:

{
  ...
  "spectral": {
    "rules": {}
  }
}

What's the purpose of this section?

Thank you for the detailed outline of the problem!

I've reproduced the issue on my side, and this seems to be a problem in the validator when a custom spectral config file extends our ruleset.

I'm going to work on this today, and I will update you later today (including an answer to your follow-up question about lint-openapi init).

I have considered a couple of solutions, one of which is outlined in #277. We will move forward once I get some feedback on which solution we want to use.

๐ŸŽ‰ This issue has been resolved in version 0.40.2 ๐ŸŽ‰

The release is available on:

Your semantic-release bot ๐Ÿ“ฆ๐Ÿš€

@barrett-schonefeld thanks a lot for the super-fast fix! I validated it with the 0.40.2 Docker image and it looks great.

Do you mind sharing some details about the purpose of the "spectral" rules entry in the generated .validaterc file?

And I have one more question (happy to open a dedicated issue if this is indeed an issue and not just me doing something wrong): I would like to have the .spectral.yaml file in a specific directory, so I call openapi-validator with the -r parameter as follows:

docker run --volume "<local-path>":/data jamescooke/openapi-validator:0.40.2 -v -s -c /data/settings/.validaterc -r /data/settings/.spectral.yaml /data/my-openapi-spec-file.json

If I use the above, I get the following error (notice the /data/data path in the error message):

Error: Could not parse /data/data/settings/.spectral.yaml: Could not read /data/data/settings/.spectral.yaml: ENOENT: no such file or directory, open '/data/data/settings/.spectral.yaml'
    at Object.readParsable (/usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/fs/reader.js:86:15)
    at async processRuleset (/usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/rulesets/reader.js:49:25)
    at async Object.readRuleset (/usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/rulesets/reader.js:29:33)
    at async Spectral.loadRuleset (/usr/local/lib/node_modules/ibm-openapi-validator/node_modules/@stoplight/spectral/dist/spectral.js:155:25)
    at async Object.setup (/usr/local/lib/node_modules/ibm-openapi-validator/src/spectral/utils/spectral-validator.js:85:3)
    at async processInput (/usr/local/lib/node_modules/ibm-openapi-validator/src/cli-validator/runValidator.js:176:5)

So I tried to remove /data from the -r parameter path:

docker run --volume "<local-path>":/data jamescooke/openapi-validator:0.40.2 -v -s -c /data/settings/.validaterc -r /settings/.spectral.yaml /data/my-openapi-spec-file.json

This time the command succeeds, but it seems to ignore the settings in my .spectral.yaml file.

Do you have any thoughts on this?

The "spectral" rules entry in the generated .validaterc file is a relic of our early integration of Spectral into the validator. At that time, we had plans to incorporate configuration for Spectral into .validaterc, but as we considered support for custom rules, we realized that using the standard .spectral.yaml was the better approach.