chris48s / v8r

✔️ A command-line JSON, YAML and TOML validator that's on your wavelength
https://chris48s.github.io/v8r/
MIT License
29 stars 5 forks source link

schema with key or id "https://json-schema.org/draft/2019-09/schema" already exists #234

Open bdovaz opened 2 years ago

bdovaz commented 2 years ago

Trying to lint a docker-compose.yml file:

 Processing docker-compose.yml
ℹ Cache miss: calling https://json.schemastore.org/schema-catalog.json
ℹ Searching for schema in my-catalog.json ...
ℹ Found schema in my-catalog.json ...
ℹ Cache miss: calling https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json
ℹ Validating docker-compose.yml against schema from https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json ...
ℹ Cache miss: calling http://json-schema.org/draft/2019-09/schema
✖ schema with key or id "https://json-schema.org/draft/2019-09/schema" already exists

I get exit code 1 because of this.

chris48s commented 2 years ago

As noted in https://github.com/chris48s/v8r#faq v8r is not a validator in itself. Its a convenience layer between schemastore and ajv.

This is an error which is thrown by Ajv when trying to load the schema.

Although I do try to do what I can within this tool to maximise compatibility, there are some non-zero number of schemas on schemastore which don't work due to either an issue with the schema, bugs in ajv, or differing approaches to ambiguities in the schema drafts. I think in this case, there are some issues with the schema at https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json but some validation libraries may be a little more lenient than AJV in parsing it. The schemas linked from the schemastore catalog do tend to vary quite widely in quality and some are more useful than others. Having a quick look at it, it looks to me like https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json may actually be implementing an earlier draft than draft/2019-09 but I've not really dug into it.

bdovaz commented 2 years ago

But then what do you want to tell me that has no solution? If I can't use a schema as famous and used as docker-compose, I can't use this validator...

chris48s commented 2 years ago

Not as such.

In its current form, the schema at https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json is in itself invalid according to at least some subset of json schema parsers. This is not unique to v8r. For example, if you use ajv-cli instead it will also tell you this schema is invalid:

$ curl "https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json" --output compose-spec.json

...

$ npx ajv-cli@latest compile -s compose-spec.json 
schema compose-spec.json is invalid

That is not to say this situation is unfixable. For example, with the following modifications that schema would be usable:

diff --git a/schema/compose-spec.json b/schema/compose-spec.json
index d744d3d..4da419f 100644
--- a/schema/compose-spec.json
+++ b/schema/compose-spec.json
@@ -1,6 +1,6 @@
 {
-  "$schema": "http://json-schema.org/draft/2019-09/schema#",
-  "id": "compose_spec.json",
+  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$id": "compose_spec.json",
   "type": "object",
   "title": "Compose Specification",
   "description": "The Compose file is a YAML file defining a multi-containers based application.",
@@ -17,7 +17,7 @@
     },

     "services": {
-      "id": "#/properties/services",
+      "$id": "#/properties/services",
       "type": "object",
       "patternProperties": {
         "^[a-zA-Z0-9._-]+$": {
@@ -28,7 +28,7 @@
     },

     "networks": {
-      "id": "#/properties/networks",
+      "$id": "#/properties/networks",
       "type": "object",
       "patternProperties": {
         "^[a-zA-Z0-9._-]+$": {
@@ -38,7 +38,7 @@
     },

     "volumes": {
-      "id": "#/properties/volumes",
+      "$id": "#/properties/volumes",
       "type": "object",
       "patternProperties": {
         "^[a-zA-Z0-9._-]+$": {
@@ -49,7 +49,7 @@
     },

     "secrets": {
-      "id": "#/properties/secrets",
+      "$id": "#/properties/secrets",
       "type": "object",
       "patternProperties": {
         "^[a-zA-Z0-9._-]+$": {
@@ -60,7 +60,7 @@
     },

     "configs": {
-      "id": "#/properties/configs",
+      "$id": "#/properties/configs",
       "type": "object",
       "patternProperties": {
         "^[a-zA-Z0-9._-]+$": {
@@ -77,7 +77,7 @@
   "definitions": {

     "service": {
-      "id": "#/definitions/service",
+      "$id": "#/definitions/service",
       "type": "object",

       "properties": {
@@ -431,7 +431,7 @@
     },

     "healthcheck": {
-      "id": "#/definitions/healthcheck",
+      "$id": "#/definitions/healthcheck",
       "type": "object",
       "properties": {
         "disable": {"type": "boolean"},
@@ -450,7 +450,7 @@
       "patternProperties": {"^x-": {}}
     },
     "deployment": {
-      "id": "#/definitions/deployment",
+      "$id": "#/definitions/deployment",
       "type": ["object", "null"],
       "properties": {
         "mode": {"type": "string"},
@@ -552,7 +552,7 @@
     },

     "generic_resources": {
-      "id": "#/definitions/generic_resources",
+      "$id": "#/definitions/generic_resources",
       "type": "array",
       "items": {
         "type": "object",
@@ -573,7 +573,7 @@
     },

     "devices": {
-      "id": "#/definitions/devices",
+      "$id": "#/definitions/devices",
       "type": "array",
       "items": {
         "type": "object",
@@ -590,7 +590,7 @@
     },

     "network": {
-      "id": "#/definitions/network",
+      "$id": "#/definitions/network",
       "type": ["object", "null"],
       "properties": {
         "name": {"type": "string"},
@@ -653,7 +653,7 @@
     },

     "volume": {
-      "id": "#/definitions/volume",
+      "$id": "#/definitions/volume",
       "type": ["object", "null"],
       "properties": {
         "name": {"type": "string"},
@@ -682,7 +682,7 @@
     },

     "secret": {
-      "id": "#/definitions/secret",
+      "$id": "#/definitions/secret",
       "type": "object",
       "properties": {
         "name": {"type": "string"},
@@ -709,7 +709,7 @@
     },

     "config": {
-      "id": "#/definitions/config",
+      "$id": "#/definitions/config",
       "type": "object",
       "properties": {
         "name": {"type": "string"},
@@ -798,7 +798,7 @@

     "constraints": {
       "service": {
-        "id": "#/definitions/constraints/service",
+        "$id": "#/definitions/constraints/service",
         "anyOf": [
           {"required": ["build"]},
           {"required": ["image"]}

although I don't know if that is exactly the original author's intent or not. It is one possible solution. What I'm getting at is: I'm sure this is fixable by submitting a PR to https://github.com/compose-spec/compose-spec fixing the schema upstream, but it probably requires some input from the authors.

If your requirement is strictly "I need to be able to validate a file against the schema at https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json with zero modifications to the schema", you are right. You can't use this tool, or ajv-cli, or probably other validation tools. You may be able to find a tool which is a bit less strict about what it will accept. Schemasafe could be worth a look for that use-case.

Abrifq commented 1 year ago

Bunch of info repeated

I managed to skip all of chris' comment, huh?

Removing comment, sorry for necrobumping.