Skip to content

Commit 5861954

Browse files
committed
Add JSON schema for package index
This schema defines the data structure of the Arduino package index at three compliance levels: - permissive: the minimum accepted format. This allows for a gradual deprecation following specification changes. - specification: the format as defined in the official specification - strict: best practices Helper functions for reading package indexes and validating them against the schema are added, at this point for use in the tests, but also for the schema-based rules to come.
1 parent a11044a commit 5861954

9 files changed

+3595
-0
lines changed

Diff for: etc/schemas/arduino-package-index-definitions-schema.json

+1,324
Large diffs are not rendered by default.
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "https://raw.githubusercontent.com/arduino/arduino-lint/main/etc/schemas/arduino-package-index-permissive-schema.json",
4+
"title": "Arduino Package Index JSON permissive schema",
5+
"description": "Package indexes define Arduino hardware packages. See: https://arduino.github.io/arduino-cli/latest/package_index_json-specification/. This schema defines the minimum accepted data format.",
6+
"allOf": [
7+
{
8+
"$ref": "arduino-package-index-definitions-schema.json#/definitions/root/permissive/object"
9+
}
10+
]
11+
}

Diff for: etc/schemas/arduino-package-index-schema.json

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "https://raw.githubusercontent.com/arduino/arduino-lint/main/etc/schemas/arduino-package-index-schema.json",
4+
"title": "Arduino Package Index JSON schema",
5+
"description": "Package indexes define Arduino hardware packages. See: https://arduino.github.io/arduino-cli/latest/package_index_json-specification/. This schema defines the data format per the specification.",
6+
"allOf": [
7+
{
8+
"$ref": "arduino-package-index-definitions-schema.json#/definitions/root/specification/object"
9+
}
10+
]
11+
}

Diff for: etc/schemas/arduino-package-index-strict-schema.json

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "https://raw.githubusercontent.com/arduino/arduino-lint/main/etc/schemas/arduino-package-index-strict-schema.json",
4+
"title": "Arduino Package Index JSON strict schema",
5+
"description": "Package indexes define Arduino hardware packages. See: https://arduino.github.io/arduino-cli/latest/package_index_json-specification/. This schema defines the best practices for the data format, above and beyond the specification.",
6+
"allOf": [
7+
{
8+
"$ref": "arduino-package-index-definitions-schema.json#/definitions/root/strict/object"
9+
}
10+
]
11+
}

Diff for: internal/project/packageindex/packageindex.go

+43
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,55 @@ See: https://arduino.github.io/arduino-cli/latest/package_index_json-specificati
2020
package packageindex
2121

2222
import (
23+
"encoding/json"
2324
"fmt"
2425
"regexp"
2526

27+
"github.com/arduino/arduino-lint/internal/rule/schema"
28+
"github.com/arduino/arduino-lint/internal/rule/schema/compliancelevel"
29+
"github.com/arduino/arduino-lint/internal/rule/schema/schemadata"
2630
"github.com/arduino/go-paths-helper"
2731
)
2832

33+
// Properties parses the package index from the given path and returns the data.
34+
func Properties(packageIndexPath *paths.Path) (map[string]interface{}, error) {
35+
rawIndex, err := packageIndexPath.ReadFile()
36+
if err != nil {
37+
panic(err)
38+
}
39+
var indexData map[string]interface{}
40+
err = json.Unmarshal(rawIndex, &indexData)
41+
if err != nil {
42+
return nil, err
43+
}
44+
45+
return indexData, nil
46+
}
47+
48+
var schemaObject = make(map[compliancelevel.Type]schema.Schema)
49+
50+
// Validate validates boards.txt data against the JSON schema and returns a map of the result for each compliance level.
51+
func Validate(packageIndex map[string]interface{}) map[compliancelevel.Type]schema.ValidationResult {
52+
referencedSchemaFilenames := []string{
53+
"general-definitions-schema.json",
54+
"arduino-package-index-definitions-schema.json",
55+
}
56+
57+
var validationResults = make(map[compliancelevel.Type]schema.ValidationResult)
58+
59+
if schemaObject[compliancelevel.Permissive].Compiled == nil { // Only compile the schemas once.
60+
schemaObject[compliancelevel.Permissive] = schema.Compile("arduino-package-index-permissive-schema.json", referencedSchemaFilenames, schemadata.Asset)
61+
schemaObject[compliancelevel.Specification] = schema.Compile("arduino-package-index-schema.json", referencedSchemaFilenames, schemadata.Asset)
62+
schemaObject[compliancelevel.Strict] = schema.Compile("arduino-package-index-strict-schema.json", referencedSchemaFilenames, schemadata.Asset)
63+
}
64+
65+
validationResults[compliancelevel.Permissive] = schema.Validate(packageIndex, schemaObject[compliancelevel.Permissive])
66+
validationResults[compliancelevel.Specification] = schema.Validate(packageIndex, schemaObject[compliancelevel.Specification])
67+
validationResults[compliancelevel.Strict] = schema.Validate(packageIndex, schemaObject[compliancelevel.Strict])
68+
69+
return validationResults
70+
}
71+
2972
var empty struct{}
3073

3174
// Reference: https://arduino.github.io/arduino-cli/latest/package_index_json-specification/#naming-of-the-json-index-file

Diff for: internal/project/packageindex/packageindex_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"github.com/arduino/go-paths-helper"
2323
"github.com/stretchr/testify/assert"
24+
"github.com/stretchr/testify/require"
2425
)
2526

2627
var testDataPath *paths.Path
@@ -33,6 +34,13 @@ func init() {
3334
testDataPath = paths.New(workingDirectory, "testdata")
3435
}
3536

37+
func TestProperties(t *testing.T) {
38+
packageIndex, err := Properties(testDataPath.Join("package_valid_index.json"))
39+
require.Nil(t, err)
40+
41+
assert.NotNil(t, packageIndex)
42+
}
43+
3644
func TestHasValidExtension(t *testing.T) {
3745
assert.True(t, HasValidExtension(paths.New("/foo", "bar.json")))
3846
assert.False(t, HasValidExtension(paths.New("/foo", "bar.baz")))

0 commit comments

Comments
 (0)