diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml index 7ccf632..466d143 100644 --- a/.github/workflows/validate.yaml +++ b/.github/workflows/validate.yaml @@ -15,7 +15,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v3 with: python-version: 3.11 @@ -23,4 +23,22 @@ jobs: run: pip install -r utility/requirements.txt - name: Validate repository lists - run: ./utility/validate.py $(find **/*.json -not -name 'other.json') + run: ./utility/validate.py --verbose $(find . -name '*.json' -not -name 'other.json' -not -name 'schema*.json') + + validate_other_lists: + name: Validate other lists + runs-on: ubuntu-latest + steps: + - name: Check out the repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: 3.11 + + - name: Install dependencies + run: pip install -r utility/requirements.txt + + - name: Validate repository lists + run: ./utility/validate.py --verbose --other $(find . -name 'other.json') diff --git a/alan_turing_institute/other.json b/alan_turing_institute/other.json index 680a4e4..1282af0 100644 --- a/alan_turing_institute/other.json +++ b/alan_turing_institute/other.json @@ -2,7 +2,7 @@ { "package_name": "RStudio", "url": "https://posit.co/download/rstudio-desktop/", - "version": "*", + "version": "> 0", "approval_date": "2023-09-29", "revoke_date": null } diff --git a/schema.json b/schema.json new file mode 100644 index 0000000..5439703 --- /dev/null +++ b/schema.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "type": "object", + "properties": { + "package_name": {"type": "string"}, + "version": { + "type": "string", + "_comment": "PEP404 version string prefixed with a comparison operator, Excluding trailing '.*'.\nhttps://peps.python.org/pep-0440/#version-specifiers\nhttps://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions", + "pattern": "^(~=|==|!=|<=|>=|<|>|===)\\s*([1-9][0-9]*!)?(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))*((a|b|rc)(0|[1-9][0-9]*))?(\\.post(0|[1-9][0-9]*))?(\\.dev(0|[1-9][0-9]*))?$" + }, + "approval_date": { + "type": "string", + "format": "date" + }, + "revoke_date": { + "oneOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ] + } + }, + "required": ["package_name", "version", "approval_date", "revoke_date"], + "additionalProperties": false + } +} diff --git a/schema_other.json b/schema_other.json new file mode 100644 index 0000000..6a7e5ad --- /dev/null +++ b/schema_other.json @@ -0,0 +1,38 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "type": "object", + "properties": { + "package_name": {"type": "string"}, + "url": { + "type": "string", + "format": "uri" + }, + "version": { + "type": "string", + "_comment": "PEP404 version string prefixed with a comparison operator, Excluding trailing '.*'.\nhttps://peps.python.org/pep-0440/#version-specifiers\nhttps://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions", + "pattern": "^(~=|==|!=|<=|>=|<|>|===)\\s*([1-9][0-9]*!)?(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))*((a|b|rc)(0|[1-9][0-9]*))?(\\.post(0|[1-9][0-9]*))?(\\.dev(0|[1-9][0-9]*))?$" + }, + "approval_date": { + "type": "string", + "format": "date" + }, + "revoke_date": { + "oneOf": [ + { + "type": "string", + "format": "date" + }, + { + "type": "null" + } + ] + } + }, + "required": ["package_name", "url", "version", "approval_date", "revoke_date"], + "additionalProperties": false + } +} diff --git a/utility/requirements.in b/utility/requirements.in index d89304b..049fc28 100644 --- a/utility/requirements.in +++ b/utility/requirements.in @@ -1 +1 @@ -jsonschema +jsonschema[format] diff --git a/utility/requirements.txt b/utility/requirements.txt index e7bc41d..6174807 100644 --- a/utility/requirements.txt +++ b/utility/requirements.txt @@ -4,19 +4,43 @@ # # pip-compile requirements.in # +arrow==1.2.3 + # via isoduration attrs==23.1.0 # via # jsonschema # referencing -jsonschema==4.19.1 +fqdn==1.5.1 + # via jsonschema +idna==3.4 + # via jsonschema +isoduration==20.11.0 + # via jsonschema +jsonpointer==2.4 + # via jsonschema +jsonschema[format]==4.19.1 # via -r requirements.in jsonschema-specifications==2023.7.1 # via jsonschema +python-dateutil==2.8.2 + # via arrow referencing==0.30.2 # via # jsonschema # jsonschema-specifications +rfc3339-validator==0.1.4 + # via jsonschema +rfc3987==1.3.8 + # via jsonschema rpds-py==0.10.3 # via # jsonschema # referencing +six==1.16.0 + # via + # python-dateutil + # rfc3339-validator +uri-template==1.3.0 + # via jsonschema +webcolors==1.13 + # via jsonschema diff --git a/utility/validate.py b/utility/validate.py index 2147aa6..3cf731c 100755 --- a/utility/validate.py +++ b/utility/validate.py @@ -2,47 +2,11 @@ import argparse import json -import pathlib +from pathlib import Path import jsonschema -schema = { - "type": "array", - "minItems": 1, - "uniqueItems": True, - "items": { - "type": "object", - "properties": { - "package_name": {"type": "string"}, - "version": { - "type": "string", - # PEP404 version string prefixed with a comparison operator - # Excluding trailing '.*' - # https://peps.python.org/pep-0440/#version-specifiers - # https://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions - "pattern": r'^(~=|==|!=|<=|>=|<|>|===)\s*([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$' - }, - "approval_date": { - "type": "string", - "format": "date" - }, - "revoke_date": { - "oneOf": [ - { - "type": "string", - "format": "date" - }, - { - "type": "null" - } - ] - } - } - } -} - - class ValidationError(Exception): pass @@ -54,13 +18,34 @@ def main() -> None: ) parser.add_argument( "filename", - type=pathlib.Path, + type=Path, nargs="+", ) + parser.add_argument( + "-o", + "--other", + action="store_true" + ) + parser.add_argument( + "-v", + "--verbose", + action="store_true" + ) clargs = parser.parse_args() + if clargs.other: + schema_filename = "schema_other.json" + else: + schema_filename = "schema.json" + + schema_path = Path(__file__).parent.parent.absolute() / schema_filename + with open(schema_path, "r") as file: + schema = json.load(file) + for path in clargs.filename: + if clargs.verbose: + print(f"Validating {path}") with open(path, "r") as file: try: jsonschema.validate(