stoplightio / vscode-spectral

VS Code extension bringing the awesome Spectral JSON/YAML linter with OpenAPI/AsyncAPI support

Home Page:https://marketplace.visualstudio.com/items?itemName=stoplight.spectral

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Extension doesn’t seem to work

martinbean opened this issue · comments

I’ve tried using this extension to disable some rules in a given OpenAPI reference, but either I’ve not configured something or this extension doesn’t work.

I have a file in reference/stats-api-contract.yaml and a Spectral file at spectral.yaml. The provided OpenAPI file has some keys missing, so I tried to disable those rules. My spectral.yaml file looks like this:

extends: spectral:oas
rules:
  info-contact: off
  openapi-tags: off
  operation-tags: off

However, when I open the OpenAPI YAML file in VS Code, it still prints warnings like:

OpenAPI object should have non-empty `tags` array.spectral(openapi-tags)

So how do I go about making the extension see my Spectral file in the root of my project? I’ve tried both a period and without a period at the start of the filename, and both .yaml and .yml file extensions; the Code extension still complains about the rules I’ve tried turning off, though.

@philsturgeon Hey, thanks for getting back to me. I’d tried these filenames:

  • .spectral.yml
  • .spectral.yaml
  • spectral.yml
  • spectral.yaml

But each time I opened the OpenAPI file, it still highlighted the rules I’ve tried turning off.

Is there something else I need to do to make the extension see my rules file?

@martinbean Thanks for reporting this.

Any chance you could repro this and paste here the logs from the Spectral task output pane? (you can easily display it though Ctrl+Shift+P to display the command palette, then start typing "Spectral: Show Output Channel")

Having this same issue, so I added spectral.rulesetFile to my settings via "spectral.rulesetFile": "/path/to/.spectral.yml"

There is an error while parsing now, and it shows in the Spectral Output Channel:

yaml: Unable to read ruleset at /path/to/.spectral.yml.
seenDependencies (before): 0.

However, Spectral itself does not have any problems parsing this file and applying the rules.

@meme Could you please share the rulesetfile causing the issue (or an equivalent repro case)?

@nulltoken here's what I'm seeing in the output pane:

-----
Scan triggered file file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml.
Linting root file file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml.
[DBG] documents.keys => ["file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http","untitled:Untitled-2","untitled:Untitled-1","file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml","file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json","file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml"]
[DBG] fileResolver.resolve => /Users/waldyrious/Developer/my-api-repo/models/model-foo.yaml
[DBG] lookedUpUri => file:///Users/waldyrious/Developer/my-api-repo/models/model-foo.yaml
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-2
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-1
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml
[DBG] key ==? lookedUpUri => false
[DBG] documents.keys => ["file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http","untitled:Untitled-2","untitled:Untitled-1","file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml","file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json","file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml"]
[DBG] fileResolver.resolve => /Users/waldyrious/Developer/my-api-repo/responses/invalid-scope.yaml
[DBG] lookedUpUri => file:///Users/waldyrious/Developer/my-api-repo/responses/invalid-scope.yaml
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-2
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-1
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml
[DBG] key ==? lookedUpUri => false
[DBG] documents.keys => ["file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http","untitled:Untitled-2","untitled:Untitled-1","file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml","file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json","file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml"]
[DBG] fileResolver.resolve => /Users/waldyrious/Developer/my-api-repo/responses/unauthorized.yaml
[DBG] lookedUpUri => file:///Users/waldyrious/Developer/my-api-repo/responses/unauthorized.yaml
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-2
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-1
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml
[DBG] key ==? lookedUpUri => false
[DBG] documents.keys => ["file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http","untitled:Untitled-2","untitled:Untitled-1","file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml","file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json","file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml"]
[DBG] fileResolver.resolve => /Users/waldyrious/Developer/my-api-repo/schemas/address.yaml
[DBG] lookedUpUri => file:///Users/waldyrious/Developer/my-api-repo/schemas/address.yaml
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-2
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-1
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml
[DBG] key ==? lookedUpUri => false
[DBG] documents.keys => ["file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http","untitled:Untitled-2","untitled:Untitled-1","file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml","file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json","file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml"]
[DBG] fileResolver.resolve => /Users/waldyrious/Developer/my-api-repo/schemas/invalid-scope-error.yaml
[DBG] lookedUpUri => file:///Users/waldyrious/Developer/my-api-repo/schemas/invalid-scope-error.yaml
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-2
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-1
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml
[DBG] key ==? lookedUpUri => false
[DBG] documents.keys => ["file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http","untitled:Untitled-2","untitled:Untitled-1","file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml","file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json","file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml"]
[DBG] fileResolver.resolve => /Users/waldyrious/Developer/my-api-repo/responses/not-found.yaml
[DBG] lookedUpUri => file:///Users/waldyrious/Developer/my-api-repo/responses/not-found.yaml
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-2
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-1
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml
[DBG] key ==? lookedUpUri => false
[DBG] documents.keys => ["file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http","untitled:Untitled-2","untitled:Untitled-1","file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml","file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json","file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml"]
[DBG] fileResolver.resolve => /Users/waldyrious/Developer/my-api-repo/models/create-transaction.v0.yaml
[DBG] lookedUpUri => file:///Users/waldyrious/Developer/my-api-repo/models/create-transaction.v0.yaml
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-2
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-1
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml
[DBG] key ==? lookedUpUri => false
[DBG] documents.keys => ["file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http","untitled:Untitled-2","untitled:Untitled-1","file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml","file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json","file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml"]
[DBG] fileResolver.resolve => /Users/waldyrious/Developer/my-api-repo/models/transaction.v0.yaml
[DBG] lookedUpUri => file:///Users/waldyrious/Developer/my-api-repo/models/transaction.v0.yaml
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-2
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-1
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml
[DBG] key ==? lookedUpUri => false
[DBG] documents.keys => ["file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http","untitled:Untitled-2","untitled:Untitled-1","file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml","file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json","file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml"]
[DBG] fileResolver.resolve => /Users/waldyrious/Developer/my-api-repo/responses/not-found.yaml
[DBG] lookedUpUri => file:///Users/waldyrious/Developer/my-api-repo/responses/not-found.yaml
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-2
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-1
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml
[DBG] key ==? lookedUpUri => false
[DBG] documents.keys => ["file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http","untitled:Untitled-2","untitled:Untitled-1","file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml","file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json","file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml"]
[DBG] fileResolver.resolve => /Users/waldyrious/Developer/my-api-repo/schemas/abstract-error.yaml
[DBG] lookedUpUri => file:///Users/waldyrious/Developer/my-api-repo/schemas/abstract-error.yaml
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-2
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-1
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml
[DBG] key ==? lookedUpUri => false
[DBG] documents.keys => ["file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http","untitled:Untitled-2","untitled:Untitled-1","file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml","file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json","file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml"]
[DBG] fileResolver.resolve => /Users/waldyrious/Developer/my-api-repo/schemas/not-found-error.yaml
[DBG] lookedUpUri => file:///Users/waldyrious/Developer/my-api-repo/schemas/not-found-error.yaml
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/untracked/api-requests.http
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-2
[DBG] key ==? lookedUpUri => false
[DBG] uri => untitled:Untitled-1
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.spectral.yaml
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/.vscode/settings.json
[DBG] key ==? lookedUpUri => false
[DBG] uri => file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml
[DBG] key ==? lookedUpUri => false
[DBG] lintDocumentOrRoot. knownDeps=[]
pdps: [
  {
    "uri": "file:///Users/waldyrious/Developer/my-api-repo/my-api.yaml",
    "diagnostics": []
  }
].
deps: [].
seenDependencies (after): 0.
-----

Here's what I have in .vscode/settings.json:

{
    "spectral.enable": true,
    "spectral.rulesetFile": "reference/uphold-public-api/.spectral.yaml",
    "spectral.run": "onType",
    "spectral.validateFiles": ["**/*.yaml"]
}

And here's the ruleset file, .spectral.yaml:

extends: spectral:oas
rules:
  'description-in-schema-fields':
    given: schema.properties.*
    then:
      field: description
      function: defined
    severity: error

Built-in spectral issues are reported normally, but I can't seem to trigger the rules in my custom ruleset file. I suppose I'm doing something wrong, but I can't figure out what! 😅

@waldyrious Your given seems off. It doesn't look like a JSONPath expression (see. https://meta.stoplight.io/docs/spectral/docs/guides/4-custom-rulesets.md#given)

I knew it had to be something silly. I've added $.. to the JSONPath expression and now it works (though I had to change function: defined to function: truthy). Sorry for the noise.

@nulltoken: Could you please share the rulesetfile causing the issue (or an equivalent repro case)?

extends:
  - "some-ruleset-here"

Appears to happen with "extends" on Spectral rulesets as npm modules.

Could you please share the rulesetfile causing the issue (or an equivalent repro case)?
Appears to happen with "extends" on Spectral rulesets as npm modules.

@meme Ok. And could you please share a working repro case?

@nulltoken sure: https://github.com/meme/vscode-spectral-repro


I yarn link in the example-ruleset and then yarn link example-ruleset inside of example-package

Then, inside of the Spectral output channel:

[Error - 9:35:05 a.m.] An error occurred while validating document /path/to/vscode-specral-repro/example-package/openapi.yml: Unable to read ruleset at /path/to/vscode-specral-repro/example-package/.spectral.yml.

However, yarn lint in example-package shows (proves that Spectral CLI is working):

/path/to/vscode-specral-repro/example-package/openapi.yml
 11:20  warning  bogus-rule  Bananas rule
 14:25  warning  bogus-rule  Bananas rule
 20:22  warning  bogus-rule  Bananas rule
 23:31  warning  bogus-rule  Bananas rule

✖ 4 problems (0 errors, 4 warnings, 0 infos, 0 hints)

Any updates on this one?

Hey @meme. Certain require calls are supported only in Node.js, hence CLI may work. They are unlikely to work in the context of VSCode. In every other case we rely on unpkg.com to deliver rulesets distributed via npm.
Is your ruleset published to npm?

I have provided an exact example ruleset that reproduces this behaviour. Please see: #30 (comment) (it is not published to npm)

The reason is probably that it cannot be reached on unpkg.com. Can you elaborate on why this is the behaviour? And if there are perhaps other options for private Spectral rulesets in VSCode.

I saw your repo and that's why I asked whether your module is published and whether the example ruleset you provided is just a sample to demonstrate some other issue.

Can you elaborate on why this is the behaviour?

We try to use require.resolve to determine the source of a given ruleset.
If the check fails, we point at unpkg.com.
That's why I said that we primarily supported Node.js here.

And if there are perhaps other options for private Spectral rulesets in VSCode.

You can load it from the filesystem. We also support http(s) protocols, so you can serve your ruleset from an external serve.

Sure, if we can load it from the filesystem as you've said, then could we have a behaviour where it attempts to manually resolve the file path:

We see that example-ruleset is being used in our .spectral.yml file, which means that it is probably going to be an on-disk node_modules dependency, so resolve it on disk using a variation of the Node.js module resolution algorithm and load it in as a ruleset?

@meme
Hey, yeah, that's something we could potentially implement in Spectral as some sort of a workaround when require.resolve is not available, yet we do have unrestricted access to fs.
Unfortunately, I cannot promise on any deliverables, thus you'll need to stick to the fs or, alternatively, will need to decide to publish the module to npm.

I'm having a slightly different issue with loading rulesets that I think is related to this issue.

When I point to my ruleset as a raw github file in a .spectral.yaml file, the extension works fine:

extends:
- https://raw.githubusercontent.com/mkistler/azure-spectral-ruleset/main/spectral-vscode.yaml

But if I specify the file directly in the spectral.rulesetFile setting, it (silently) reverts to using the default ruleset.

It would be nice to have this fixed so that I don't have to sprinkle .spectral.yaml files all over the place.

Thanks for reporting @mkistler. This is being tracked in #149, and hopefully now that the team has more time allocated to maintain this extension we'll see a resolution there soon.

If anyone else has concerns about other specific bugs please make a more specific issue, as this one is a bit "doesn't work"-ish and that's hard to keep track of.