Browse Source
* Initial hardware metadata JSON schema. * GH Action to validate all schemas for boards/shields.xmkb
Peter Johanson
4 years ago
committed by
Pete Johanson
5 changed files with 368 additions and 0 deletions
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
name: Hardware Metadata Validation |
||||
|
||||
on: |
||||
push: |
||||
paths: |
||||
- ".github/workflows/hardware-metadata-validation.yml" |
||||
- "schema/hardware-metadata.schema.json" |
||||
- "app/boards/**/*.zmk.yml" |
||||
- "app/scripts/west_commands/metadata.py" |
||||
pull_request: |
||||
paths: |
||||
- ".github/workflows/hardware-metadata-validation.yml" |
||||
- "schema/hardware-metadata.schema.json" |
||||
- "app/boards/**/*.zmk.yml" |
||||
- "app/scripts/west_commands/metadata.py" |
||||
|
||||
jobs: |
||||
validate-metadata: |
||||
runs-on: ubuntu-latest |
||||
container: |
||||
image: zmkfirmware/zmk-dev-arm:2.5 |
||||
steps: |
||||
- uses: actions/checkout@v2 |
||||
- name: Install dependencies |
||||
run: pip install -r app/scripts/requirements.txt |
||||
- name: West init |
||||
run: west init -l app |
||||
- name: Update modules (west update) |
||||
run: west update |
||||
- name: Export Zephyr CMake package (west zephyr-export) |
||||
run: west zephyr-export |
||||
- name: Validate Hardware Metadata |
||||
run: | |
||||
cd app |
||||
west metadata check |
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
# Copyright (c) 2021 The ZMK Contributors |
||||
# SPDX-License-Identifier: MIT |
||||
|
||||
# Convert YAML to JSON for validation |
||||
remarshal>=0.14.0 |
||||
|
||||
# Perform our hardware metadata validation |
||||
jsonschema>=3.2.0 |
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
# Copyright (c) 2021 The ZMK Contributors |
||||
# SPDX-License-Identifier: MIT |
||||
'''Metadata command for ZMK.''' |
||||
|
||||
from functools import cached_property |
||||
import glob |
||||
import json |
||||
from jsonschema import validate, ValidationError |
||||
import os |
||||
import sys |
||||
import yaml |
||||
from textwrap import dedent # just for nicer code indentation |
||||
|
||||
from west.commands import WestCommand |
||||
from west import log # use this for user output |
||||
|
||||
|
||||
class Metadata(WestCommand): |
||||
def __init__(self): |
||||
super().__init__( |
||||
'metadata', # gets stored as self.name |
||||
'ZMK hardware metadata commands', # self.help |
||||
# self.description: |
||||
dedent('''Operate on the board/shield metadata.''')) |
||||
|
||||
def do_add_parser(self, parser_adder): |
||||
parser = parser_adder.add_parser(self.name, |
||||
help=self.help, |
||||
description=self.description) |
||||
|
||||
parser.add_argument('subcommand', default="check", |
||||
help='The subcommand to run. Defaults to "check".', nargs="?") |
||||
return parser # gets stored as self.parser |
||||
|
||||
@cached_property |
||||
def schema(self): |
||||
return json.load( |
||||
open("../schema/hardware-metadata.schema.json", 'r')) |
||||
|
||||
def validate_file(self, file): |
||||
print("Validating: " + file) |
||||
with open(file, 'r') as stream: |
||||
try: |
||||
validate(yaml.safe_load(stream), self.schema) |
||||
except yaml.YAMLError as exc: |
||||
print("Failed loading metadata yaml: " + file) |
||||
print(exc) |
||||
return False |
||||
except ValidationError as vexc: |
||||
print("Failed validation of: " + file) |
||||
print(vexc) |
||||
return False |
||||
return True |
||||
|
||||
def do_run(self, args, unknown_args): |
||||
status = all([self.validate_file(f) for f in glob.glob( |
||||
"boards/**/*.zmk.yml", recursive=True)]) |
||||
|
||||
sys.exit(0 if status else 1) |
@ -0,0 +1,261 @@
@@ -0,0 +1,261 @@
|
||||
{ |
||||
"$id": "https://zmkfirmware.dev/zmk.metadata.json", |
||||
"title": "HardwareMetadata", |
||||
"$schema": "https://json-schema.org/draft/2020-12/schema", |
||||
"oneOf": [ |
||||
{ |
||||
"$ref": "#/$defs/board" |
||||
}, |
||||
{ |
||||
"$ref": "#/$defs/shield" |
||||
}, |
||||
{ |
||||
"$ref": "#/$defs/interconnect" |
||||
} |
||||
], |
||||
"$defs": { |
||||
"id": { |
||||
"type": "string", |
||||
"pattern": "^[a-z0-9_]+$" |
||||
}, |
||||
"keyboard_siblings": { |
||||
"type": "array", |
||||
"items": { |
||||
"type": "string" |
||||
} |
||||
}, |
||||
"variant": { |
||||
"oneOf": [ |
||||
{ |
||||
"type": "string" |
||||
}, |
||||
{ |
||||
"type": "object", |
||||
"required": [ |
||||
"id", |
||||
"features" |
||||
], |
||||
"properties": { |
||||
"id": { |
||||
"$ref": "#/$defs/id" |
||||
}, |
||||
"features": { |
||||
"$ref": "#/$defs/features" |
||||
} |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
"features": { |
||||
"type": "array", |
||||
"items": { |
||||
"type": "string", |
||||
"enum": [ |
||||
"keys", |
||||
"display", |
||||
"encoder", |
||||
"underglow", |
||||
"pointer" |
||||
] |
||||
} |
||||
}, |
||||
"interconnects": { |
||||
"type": "array", |
||||
"minItems": 1, |
||||
"items": { |
||||
"$ref": "#/$defs/id" |
||||
} |
||||
}, |
||||
"sibling_details": { |
||||
"type": "object", |
||||
"additionalProperties": false, |
||||
"properties": { |
||||
"id": { |
||||
"$ref": "#/$defs/id" |
||||
}, |
||||
"features": { |
||||
"$ref": "#/$defs/features" |
||||
}, |
||||
"variants": { |
||||
"type": "array", |
||||
"items": { |
||||
"$ref": "#/$defs/variant" |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
"interconnect": { |
||||
"title": "Interconnect", |
||||
"type": "object", |
||||
"additionalProperties": false, |
||||
"required": [ |
||||
"file_format", |
||||
"id", |
||||
"name", |
||||
"url", |
||||
"type" |
||||
], |
||||
"properties": { |
||||
"file_format": { |
||||
"type": "string", |
||||
"const": "1" |
||||
}, |
||||
"id": { |
||||
"$ref": "#/$defs/id" |
||||
}, |
||||
"name": { |
||||
"type": "string" |
||||
}, |
||||
"version": { |
||||
"type": "string" |
||||
}, |
||||
"url": { |
||||
"type": "string", |
||||
"format": "uri" |
||||
}, |
||||
"description": { |
||||
"type": "string" |
||||
}, |
||||
"manufacturer": { |
||||
"type": "string" |
||||
}, |
||||
"type": { |
||||
"type": "string", |
||||
"const": "interconnect" |
||||
} |
||||
} |
||||
}, |
||||
"board": { |
||||
"title": "Board", |
||||
"type": "object", |
||||
"additionalProperties": false, |
||||
"required": [ |
||||
"file_format", |
||||
"id", |
||||
"name", |
||||
"url", |
||||
"arch", |
||||
"type", |
||||
"outputs" |
||||
], |
||||
"properties": { |
||||
"file_format": { |
||||
"type": "string", |
||||
"const": "1" |
||||
}, |
||||
"id": { |
||||
"$ref": "#/$defs/id" |
||||
}, |
||||
"name": { |
||||
"type": "string" |
||||
}, |
||||
"version": { |
||||
"type": "string" |
||||
}, |
||||
"url": { |
||||
"type": "string", |
||||
"format": "uri" |
||||
}, |
||||
"description": { |
||||
"type": "string" |
||||
}, |
||||
"manufacturer": { |
||||
"type": "string" |
||||
}, |
||||
"arch": { |
||||
"type": "string", |
||||
"pattern": "^[a-z0-9_]+$" |
||||
}, |
||||
"type": { |
||||
"type": "string", |
||||
"const": "board" |
||||
}, |
||||
"siblings": { |
||||
"$ref": "#/$defs/keyboard_siblings" |
||||
}, |
||||
"outputs": { |
||||
"type": "array", |
||||
"items": { |
||||
"type": "string", |
||||
"enum": [ |
||||
"usb", |
||||
"ble" |
||||
] |
||||
} |
||||
}, |
||||
"features": { |
||||
"$ref": "#/$defs/features" |
||||
}, |
||||
"variants": { |
||||
"type": "array", |
||||
"items": { |
||||
"$ref": "#/$defs/variant" |
||||
} |
||||
}, |
||||
"exposes": { |
||||
"$ref": "#/$defs/interconnects" |
||||
} |
||||
} |
||||
}, |
||||
"shield": { |
||||
"title": "Shield", |
||||
"type": "object", |
||||
"additionalProperties": false, |
||||
"required": [ |
||||
"file_format", |
||||
"id", |
||||
"name", |
||||
"url", |
||||
"type", |
||||
"requires" |
||||
], |
||||
"properties": { |
||||
"file_format": { |
||||
"type": "string", |
||||
"const": "1" |
||||
}, |
||||
"id": { |
||||
"$ref": "#/$defs/id" |
||||
}, |
||||
"name": { |
||||
"type": "string" |
||||
}, |
||||
"url": { |
||||
"type": "string", |
||||
"format": "uri" |
||||
}, |
||||
"description": { |
||||
"type": "string" |
||||
}, |
||||
"manufacturer": { |
||||
"type": "string" |
||||
}, |
||||
"version": { |
||||
"type": "string" |
||||
}, |
||||
"type": { |
||||
"type": "string", |
||||
"const": "shield" |
||||
}, |
||||
"features": { |
||||
"$ref": "#/$defs/features" |
||||
}, |
||||
"variants": { |
||||
"type": "array", |
||||
"items": { |
||||
"$ref": "#/$defs/variant" |
||||
} |
||||
}, |
||||
"siblings": { |
||||
"$ref": "#/$defs/keyboard_siblings" |
||||
}, |
||||
"requires": { |
||||
"$ref": "#/$defs/interconnects" |
||||
}, |
||||
"exposes": { |
||||
"$ref": "#/$defs/interconnects" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue