Merge pull request #1 from matrix-org/anoa/support-rendered-data

Reinstate and fix schema validation files
This commit is contained in:
wbamberg 2021-02-05 09:43:01 -08:00 committed by Richard van der Hoff
commit a26c352d78
6 changed files with 167 additions and 27 deletions

View file

@ -5,9 +5,10 @@ gendoc: &gendoc
scripts/gendoc.py scripts/gendoc.py
genswagger: &genswagger genswagger: &genswagger
name: Generate the swagger name: Validate sources and generate swagger json
command: | command: |
source /env/bin/activate source /env/bin/activate
scripts/check-swagger-sources.py
scripts/dump-swagger.py scripts/dump-swagger.py
buildswaggerui: &buildswaggerui buildswaggerui: &buildswaggerui
@ -27,10 +28,7 @@ checkexamples: &checkexamples
name: Check Event Examples name: Check Event Examples
command: | command: |
source /env/bin/activate source /env/bin/activate
cd event-schemas scripts/check-event-schema-examples.py
./check_examples.py
cd ../api
./check_examples.py
genmatrixassets: &genmatrixassets genmatrixassets: &genmatrixassets
name: Generate/Verify matrix.org assets name: Generate/Verify matrix.org assets
@ -41,9 +39,9 @@ genmatrixassets: &genmatrixassets
validateapi: &validateapi validateapi: &validateapi
name: Validate OpenAPI specifications name: Validate OpenAPI specifications
command: | command: |
cd api cd scripts
npm install npm install
node validator.js -s "client-server" node validator.js -s "../data/api/client-server"
buildspeculator: &buildspeculator buildspeculator: &buildspeculator
name: Build Speculator name: Build Speculator

View file

@ -128,7 +128,14 @@ def check_example_dir(exampledir, schemadir):
if __name__ == '__main__': if __name__ == '__main__':
# Get the directory that this script is residing in
script_directory = os.path.dirname(os.path.realpath(__file__))
# Resolve the directories to check, relative to the script path
examples_directory = os.path.join(script_directory, "../event-schemas/examples")
schema_directory = os.path.join(script_directory, "../event-schemas/schema")
try: try:
check_example_dir("examples", "schema") check_example_dir(examples_directory, schema_directory)
except: except:
sys.exit(1) sys.exit(1)

View file

@ -108,13 +108,36 @@ def check_swagger_file(filepath):
def resolve_references(path, schema): def resolve_references(path, schema):
"""Recurse through a given schema until we find a $ref key. Upon doing so,
check that the referenced file exists, then load it up and check all of the
references in that file. Continue on until we've hit all dead ends.
$ref values are deleted from schemas as they are validated, to prevent
duplicate work.
"""
if isinstance(schema, dict): if isinstance(schema, dict):
# do $ref first # do $ref first
if '$ref' in schema: if '$ref' in schema:
value = schema['$ref'] # Pull the referenced filepath from the schema
path = os.path.abspath(os.path.join(os.path.dirname(path), value)) referenced_file = schema['$ref']
ref = load_file("file://" + path)
result = resolve_references(path, ref) # Referenced filepaths are relative, so take the current path's
# directory and append the relative, referenced path to it.
inner_path = os.path.join(os.path.dirname(path), referenced_file)
# Then convert the path (which may contiain '../') into a
# normalised, absolute path
inner_path = os.path.abspath(inner_path)
# Load the referenced file
ref = load_file("file://" + inner_path)
# Check that the references in *this* file are valid
result = resolve_references(inner_path, ref)
# They were valid, and so were the sub-references. Delete
# the reference here to ensure we don't pass over it again
# when checking other files
del schema['$ref'] del schema['$ref']
else: else:
result = {} result = {}
@ -143,15 +166,22 @@ def load_file(path):
if __name__ == '__main__': if __name__ == '__main__':
paths = sys.argv[1:] # Get the directory that this script is residing in
if not paths: script_directory = os.path.dirname(os.path.realpath(__file__))
paths = []
for (root, dirs, files) in os.walk(os.curdir): # Resolve the directory containing the swagger sources,
for filename in files: # relative to the script path
if filename.endswith(".yaml"): source_files_directory = os.path.realpath(os.path.join(script_directory, "../data"))
paths.append(os.path.join(root, filename))
for path in paths: # Walk the source path directory, looking for YAML files to check
try: for (root, dirs, files) in os.walk(source_files_directory):
check_swagger_file(path) for filename in files:
except Exception as e: if not filename.endswith(".yaml"):
raise ValueError("Error checking file %r" % (path,), e) continue
path = os.path.join(root, filename)
try:
check_swagger_file(path)
except Exception as e:
raise ValueError("Error checking file %s" % (path,), e)

15
scripts/package.json Normal file
View file

@ -0,0 +1,15 @@
{
"name": "swagger-cli-validator",
"version": "0.0.1",
"description": "",
"main": "validator.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"nopt": "^3.0.2",
"swagger-parser": "^3.2.1"
}
}

View file

@ -11,12 +11,16 @@ virtualenv -p python3 env
python --version python --version
pip --version pip --version
# Install python dependencies
pip install -r scripts/requirements.txt pip install -r scripts/requirements.txt
# Install node dependencies
npm install --prefix=scripts
# do sanity checks on the examples and swagger # do sanity checks on the examples and swagger
(cd event-schemas/ && ./check_examples.py) scripts/check-event-schema-examples.py
(cd api && ./check_examples.py) scripts/check-swagger-sources.py
(cd api && npm install && node validator.js -s "client-server") node scripts/validator.js --schema "data/api/client-server"
: ${GOPATH:=${WORKSPACE}/.gopath} : ${GOPATH:=${WORKSPACE}/.gopath}
mkdir -p "${GOPATH}" mkdir -p "${GOPATH}"

86
scripts/validator.js Normal file
View file

@ -0,0 +1,86 @@
"use strict";
var fs = require("fs");
var nopt = require("nopt");
var parser = require("swagger-parser");
var path = require("path");
var opts = nopt({
"help": Boolean,
"schema": path
}, {
"h": "--help",
"s": "--schema"
});
if (opts.help) {
console.log(
"Use swagger-parser to validate against Swagger 2.0\n"+
"Usage:\n"+
" node validator.js -s <schema_file_or_folder>"
);
process.exit(0);
}
if (!opts.schema) {
console.error("No [s]chema specified.");
process.exit(1);
}
var errFn = function(err, api) {
if (!err) {
return;
}
console.error(err);
process.exit(1);
};
/**
* @brief Produce a handler for parser.validate().
* Recommended usage: `parser.validate(filename, makeHandler(filename));`
* or `parser.validate(schema, makeHandler());`.
* @param scope - usually a filename, this will be used to denote
* an (in)valid schema in console output; "Schema" if undefined
* @returns {function} the handler that can be passed to parser.validate
*/
function makeHandler(scope) {
if (!scope)
scope = "Schema";
return function(err, api, metadata) {
if (err) {
console.error("%s is not valid.", scope || "Schema");
errFn(err, api, metadata); // Won't return
}
Object.keys(api.paths).forEach(function (endpoint) {
var operationsMap = api.paths[endpoint];
Object.keys(operationsMap).forEach(function (verb) {
if (!operationsMap[verb]["operationId"]) {
console.error("%s is not valid", scope);
errFn("operationId is missing in " + endpoint + ", verb " + verb, api);
}
})
});
console.log("%s is valid.", scope);
}
}
var isDir = fs.lstatSync(opts.schema).isDirectory();
if (isDir) {
console.log("Checking directory %s for .yaml files...", opts.schema);
fs.readdir(opts.schema, function(err, files) {
if (err) {
errFn(err); // Won't return
}
files.forEach(function(f) {
var suffix = ".yaml";
if (f.indexOf(suffix, f.length - suffix.length) > 0) {
parser.validate(path.join(opts.schema, f), makeHandler(f));
}
});
});
}
else{
parser.validate(opts.schema, makeHandler(opts.schema));
}