Add and validate UserConfig schema

This commit is contained in:
Michael B. Gale
2025-10-12 13:14:11 +01:00
parent 66df0bc515
commit ac922ab562
15 changed files with 12167 additions and 2741 deletions
+1314 -16
View File
File diff suppressed because it is too large Load Diff
+1309 -1308
View File
File diff suppressed because it is too large Load Diff
+1307 -9
View File
File diff suppressed because it is too large Load Diff
+1316 -1315
View File
File diff suppressed because it is too large Load Diff
+1475 -10
View File
File diff suppressed because it is too large Load Diff
+1307 -9
View File
File diff suppressed because it is too large Load Diff
+1314 -16
View File
File diff suppressed because it is too large Load Diff
+1307 -9
View File
File diff suppressed because it is too large Load Diff
+25 -24
View File
@@ -20885,19 +20885,19 @@ var require_validator = __commonJS({
var SchemaError = helpers.SchemaError;
var SchemaContext = helpers.SchemaContext;
var anonymousBase = "/";
var Validator2 = function Validator3() {
this.customFormats = Object.create(Validator3.prototype.customFormats);
var Validator3 = function Validator4() {
this.customFormats = Object.create(Validator4.prototype.customFormats);
this.schemas = {};
this.unresolvedRefs = [];
this.types = Object.create(types);
this.attributes = Object.create(attribute.validators);
};
Validator2.prototype.customFormats = {};
Validator2.prototype.schemas = null;
Validator2.prototype.types = null;
Validator2.prototype.attributes = null;
Validator2.prototype.unresolvedRefs = null;
Validator2.prototype.addSchema = function addSchema(schema2, base) {
Validator3.prototype.customFormats = {};
Validator3.prototype.schemas = null;
Validator3.prototype.types = null;
Validator3.prototype.attributes = null;
Validator3.prototype.unresolvedRefs = null;
Validator3.prototype.addSchema = function addSchema(schema2, base) {
var self2 = this;
if (!schema2) {
return null;
@@ -20915,25 +20915,25 @@ var require_validator = __commonJS({
});
return this.schemas[ourUri];
};
Validator2.prototype.addSubSchemaArray = function addSubSchemaArray(baseuri, schemas) {
Validator3.prototype.addSubSchemaArray = function addSubSchemaArray(baseuri, schemas) {
if (!Array.isArray(schemas)) return;
for (var i = 0; i < schemas.length; i++) {
this.addSubSchema(baseuri, schemas[i]);
}
};
Validator2.prototype.addSubSchemaObject = function addSubSchemaArray(baseuri, schemas) {
Validator3.prototype.addSubSchemaObject = function addSubSchemaArray(baseuri, schemas) {
if (!schemas || typeof schemas != "object") return;
for (var p in schemas) {
this.addSubSchema(baseuri, schemas[p]);
}
};
Validator2.prototype.setSchemas = function setSchemas(schemas) {
Validator3.prototype.setSchemas = function setSchemas(schemas) {
this.schemas = schemas;
};
Validator2.prototype.getSchema = function getSchema(urn) {
Validator3.prototype.getSchema = function getSchema(urn) {
return this.schemas[urn];
};
Validator2.prototype.validate = function validate(instance, schema2, options, ctx) {
Validator3.prototype.validate = function validate(instance, schema2, options, ctx) {
if (typeof schema2 !== "boolean" && typeof schema2 !== "object" || schema2 === null) {
throw new SchemaError("Expected `schema` to be an object or boolean");
}
@@ -20971,7 +20971,7 @@ var require_validator = __commonJS({
if (typeof ref == "string") return ref;
return false;
}
Validator2.prototype.validateSchema = function validateSchema(instance, schema2, options, ctx) {
Validator3.prototype.validateSchema = function validateSchema(instance, schema2, options, ctx) {
var result = new ValidatorResult(instance, schema2, options, ctx);
if (typeof schema2 === "boolean") {
if (schema2 === true) {
@@ -21021,17 +21021,17 @@ var require_validator = __commonJS({
}
return result;
};
Validator2.prototype.schemaTraverser = function schemaTraverser(schemaobj, s) {
Validator3.prototype.schemaTraverser = function schemaTraverser(schemaobj, s) {
schemaobj.schema = helpers.deepMerge(schemaobj.schema, this.superResolve(s, schemaobj.ctx));
};
Validator2.prototype.superResolve = function superResolve(schema2, ctx) {
Validator3.prototype.superResolve = function superResolve(schema2, ctx) {
var ref = shouldResolve(schema2);
if (ref) {
return this.resolve(schema2, ref, ctx).subschema;
}
return schema2;
};
Validator2.prototype.resolve = function resolve6(schema2, switchSchema, ctx) {
Validator3.prototype.resolve = function resolve6(schema2, switchSchema, ctx) {
switchSchema = ctx.resolve(switchSchema);
if (ctx.schemas[switchSchema]) {
return { subschema: ctx.schemas[switchSchema], switchSchema };
@@ -21048,7 +21048,7 @@ var require_validator = __commonJS({
}
return { subschema, switchSchema };
};
Validator2.prototype.testType = function validateType(instance, schema2, options, ctx, type2) {
Validator3.prototype.testType = function validateType(instance, schema2, options, ctx, type2) {
if (type2 === void 0) {
return;
} else if (type2 === null) {
@@ -21063,7 +21063,7 @@ var require_validator = __commonJS({
}
return true;
};
var types = Validator2.prototype.types = {};
var types = Validator3.prototype.types = {};
types.string = function testString(instance) {
return typeof instance == "string";
};
@@ -21091,7 +21091,7 @@ var require_validator = __commonJS({
types.object = function testObject(instance) {
return instance && typeof instance === "object" && !Array.isArray(instance) && !(instance instanceof Date);
};
module2.exports = Validator2;
module2.exports = Validator3;
}
});
@@ -21099,7 +21099,7 @@ var require_validator = __commonJS({
var require_lib2 = __commonJS({
"node_modules/jsonschema/lib/index.js"(exports2, module2) {
"use strict";
var Validator2 = module2.exports.Validator = require_validator();
var Validator3 = module2.exports.Validator = require_validator();
module2.exports.ValidatorResult = require_helpers().ValidatorResult;
module2.exports.ValidatorResultError = require_helpers().ValidatorResultError;
module2.exports.ValidationError = require_helpers().ValidationError;
@@ -21107,7 +21107,7 @@ var require_lib2 = __commonJS({
module2.exports.SchemaScanResult = require_scan().SchemaScanResult;
module2.exports.scan = require_scan().scan;
module2.exports.validate = function(instance, schema2, options) {
var v = new Validator2();
var v = new Validator3();
return v.validate(instance, schema2, options);
};
}
@@ -84865,7 +84865,7 @@ var path14 = __toESM(require("path"));
var url = __toESM(require("url"));
var import_zlib = __toESM(require("zlib"));
var core11 = __toESM(require_core());
var jsonschema = __toESM(require_lib2());
var jsonschema2 = __toESM(require_lib2());
// src/actions-util.ts
var fs4 = __toESM(require("fs"));
@@ -89049,6 +89049,7 @@ var path9 = __toESM(require("path"));
var core6 = __toESM(require_core());
// src/config/db-config.ts
var jsonschema = __toESM(require_lib2());
var semver2 = __toESM(require_semver2());
var PACK_IDENTIFIER_PATTERN = (function() {
const alphaNumeric = "[a-z0-9]";
@@ -92651,7 +92652,7 @@ function validateSarifFileSchema(sarif, sarifFilePath, logger) {
}
logger.info(`Validating ${sarifFilePath}`);
const schema2 = require_sarif_schema_2_1_0();
const result = new jsonschema.Validator().validate(sarif, schema2);
const result = new jsonschema2.Validator().validate(sarif, schema2);
const warningAttributes = ["uri-reference", "uri"];
const errors = (result.errors ?? []).filter(
(err) => !(err.name === "format" && typeof err.argument === "string" && warningAttributes.includes(err.argument))
+1298
View File
File diff suppressed because it is too large Load Diff
+25 -24
View File
@@ -80374,19 +80374,19 @@ var require_validator2 = __commonJS({
var SchemaError = helpers.SchemaError;
var SchemaContext = helpers.SchemaContext;
var anonymousBase = "/";
var Validator2 = function Validator3() {
this.customFormats = Object.create(Validator3.prototype.customFormats);
var Validator3 = function Validator4() {
this.customFormats = Object.create(Validator4.prototype.customFormats);
this.schemas = {};
this.unresolvedRefs = [];
this.types = Object.create(types);
this.attributes = Object.create(attribute.validators);
};
Validator2.prototype.customFormats = {};
Validator2.prototype.schemas = null;
Validator2.prototype.types = null;
Validator2.prototype.attributes = null;
Validator2.prototype.unresolvedRefs = null;
Validator2.prototype.addSchema = function addSchema(schema2, base) {
Validator3.prototype.customFormats = {};
Validator3.prototype.schemas = null;
Validator3.prototype.types = null;
Validator3.prototype.attributes = null;
Validator3.prototype.unresolvedRefs = null;
Validator3.prototype.addSchema = function addSchema(schema2, base) {
var self2 = this;
if (!schema2) {
return null;
@@ -80404,25 +80404,25 @@ var require_validator2 = __commonJS({
});
return this.schemas[ourUri];
};
Validator2.prototype.addSubSchemaArray = function addSubSchemaArray(baseuri, schemas) {
Validator3.prototype.addSubSchemaArray = function addSubSchemaArray(baseuri, schemas) {
if (!Array.isArray(schemas)) return;
for (var i = 0; i < schemas.length; i++) {
this.addSubSchema(baseuri, schemas[i]);
}
};
Validator2.prototype.addSubSchemaObject = function addSubSchemaArray(baseuri, schemas) {
Validator3.prototype.addSubSchemaObject = function addSubSchemaArray(baseuri, schemas) {
if (!schemas || typeof schemas != "object") return;
for (var p in schemas) {
this.addSubSchema(baseuri, schemas[p]);
}
};
Validator2.prototype.setSchemas = function setSchemas(schemas) {
Validator3.prototype.setSchemas = function setSchemas(schemas) {
this.schemas = schemas;
};
Validator2.prototype.getSchema = function getSchema(urn) {
Validator3.prototype.getSchema = function getSchema(urn) {
return this.schemas[urn];
};
Validator2.prototype.validate = function validate(instance, schema2, options, ctx) {
Validator3.prototype.validate = function validate(instance, schema2, options, ctx) {
if (typeof schema2 !== "boolean" && typeof schema2 !== "object" || schema2 === null) {
throw new SchemaError("Expected `schema` to be an object or boolean");
}
@@ -80460,7 +80460,7 @@ var require_validator2 = __commonJS({
if (typeof ref == "string") return ref;
return false;
}
Validator2.prototype.validateSchema = function validateSchema(instance, schema2, options, ctx) {
Validator3.prototype.validateSchema = function validateSchema(instance, schema2, options, ctx) {
var result = new ValidatorResult(instance, schema2, options, ctx);
if (typeof schema2 === "boolean") {
if (schema2 === true) {
@@ -80510,17 +80510,17 @@ var require_validator2 = __commonJS({
}
return result;
};
Validator2.prototype.schemaTraverser = function schemaTraverser(schemaobj, s) {
Validator3.prototype.schemaTraverser = function schemaTraverser(schemaobj, s) {
schemaobj.schema = helpers.deepMerge(schemaobj.schema, this.superResolve(s, schemaobj.ctx));
};
Validator2.prototype.superResolve = function superResolve(schema2, ctx) {
Validator3.prototype.superResolve = function superResolve(schema2, ctx) {
var ref = shouldResolve(schema2);
if (ref) {
return this.resolve(schema2, ref, ctx).subschema;
}
return schema2;
};
Validator2.prototype.resolve = function resolve6(schema2, switchSchema, ctx) {
Validator3.prototype.resolve = function resolve6(schema2, switchSchema, ctx) {
switchSchema = ctx.resolve(switchSchema);
if (ctx.schemas[switchSchema]) {
return { subschema: ctx.schemas[switchSchema], switchSchema };
@@ -80537,7 +80537,7 @@ var require_validator2 = __commonJS({
}
return { subschema, switchSchema };
};
Validator2.prototype.testType = function validateType(instance, schema2, options, ctx, type2) {
Validator3.prototype.testType = function validateType(instance, schema2, options, ctx, type2) {
if (type2 === void 0) {
return;
} else if (type2 === null) {
@@ -80552,7 +80552,7 @@ var require_validator2 = __commonJS({
}
return true;
};
var types = Validator2.prototype.types = {};
var types = Validator3.prototype.types = {};
types.string = function testString(instance) {
return typeof instance == "string";
};
@@ -80580,7 +80580,7 @@ var require_validator2 = __commonJS({
types.object = function testObject(instance) {
return instance && typeof instance === "object" && !Array.isArray(instance) && !(instance instanceof Date);
};
module2.exports = Validator2;
module2.exports = Validator3;
}
});
@@ -80588,7 +80588,7 @@ var require_validator2 = __commonJS({
var require_lib2 = __commonJS({
"node_modules/jsonschema/lib/index.js"(exports2, module2) {
"use strict";
var Validator2 = module2.exports.Validator = require_validator2();
var Validator3 = module2.exports.Validator = require_validator2();
module2.exports.ValidatorResult = require_helpers3().ValidatorResult;
module2.exports.ValidatorResultError = require_helpers3().ValidatorResultError;
module2.exports.ValidationError = require_helpers3().ValidationError;
@@ -80596,7 +80596,7 @@ var require_lib2 = __commonJS({
module2.exports.SchemaScanResult = require_scan2().SchemaScanResult;
module2.exports.scan = require_scan2().scan;
module2.exports.validate = function(instance, schema2, options) {
var v = new Validator2();
var v = new Validator3();
return v.validate(instance, schema2, options);
};
}
@@ -89725,6 +89725,7 @@ var path10 = __toESM(require("path"));
var core8 = __toESM(require_core());
// src/config/db-config.ts
var jsonschema = __toESM(require_lib2());
var semver4 = __toESM(require_semver2());
var PACK_IDENTIFIER_PATTERN = (function() {
const alphaNumeric = "[a-z0-9]";
@@ -90009,7 +90010,7 @@ var path15 = __toESM(require("path"));
var url = __toESM(require("url"));
var import_zlib = __toESM(require("zlib"));
var core12 = __toESM(require_core());
var jsonschema = __toESM(require_lib2());
var jsonschema2 = __toESM(require_lib2());
// src/codeql.ts
var fs12 = __toESM(require("fs"));
@@ -93305,7 +93306,7 @@ function validateSarifFileSchema(sarif, sarifFilePath, logger) {
}
logger.info(`Validating ${sarifFilePath}`);
const schema2 = require_sarif_schema_2_1_0();
const result = new jsonschema.Validator().validate(sarif, schema2);
const result = new jsonschema2.Validator().validate(sarif, schema2);
const warningAttributes = ["uri-reference", "uri"];
const errors = (result.errors ?? []).filter(
(err) => !(err.name === "format" && typeof err.argument === "string" && warningAttributes.includes(err.argument))
+1
View File
@@ -400,6 +400,7 @@ test("parseUserConfig - successfully parses valid YAML", (t) => {
- "some/path"
queries:
- uses: foo
some-unknown-option: true
`,
);
t.truthy(result);
+18 -1
View File
@@ -1,6 +1,7 @@
import * as path from "path";
import * as yaml from "js-yaml";
import * as jsonschema from "jsonschema";
import * as semver from "semver";
import * as errorMessages from "../error-messages";
@@ -489,7 +490,23 @@ export function parseUserConfig(
contents: string,
): UserConfig {
try {
return yaml.load(contents) as UserConfig;
const schema =
// eslint-disable-next-line @typescript-eslint/no-require-imports
require("../../src/db-config-schema.json") as jsonschema.Schema;
const doc = yaml.load(contents);
const result = new jsonschema.Validator().validate(doc, schema);
if (result.errors.length > 0) {
throw new ConfigurationError(
errorMessages.getInvalidConfigFileMessage(
pathInput,
`The configuration file contained ${result.errors.length} error(s)`,
),
);
}
return doc as UserConfig;
} catch (error) {
if (error instanceof yaml.YAMLException) {
throw new ConfigurationError(
+144
View File
@@ -0,0 +1,144 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "CodeQL Database Configuration",
"description": "Format of the config file supplied by the user for CodeQL analysis",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name of the configuration"
},
"disable-default-queries": {
"type": "boolean",
"description": "Whether to disable default queries"
},
"queries": {
"type": "array",
"description": "List of additional queries to run",
"items": {
"$ref": "#/definitions/QuerySpec"
}
},
"paths-ignore": {
"type": "array",
"description": "Paths to ignore during analysis",
"items": {
"type": "string"
}
},
"paths": {
"type": "array",
"description": "Paths to include in analysis",
"items": {
"type": "string"
}
},
"packs": {
"description": "Query packs to include. Can be a simple array for single-language analysis or an object with language-specific arrays for multi-language analysis",
"oneOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
}
]
},
"query-filters": {
"type": "array",
"description": "Set of query filters to include and exclude extra queries based on CodeQL query suite include and exclude properties",
"items": {
"$ref": "#/definitions/QueryFilter"
}
}
},
"additionalProperties": true,
"definitions": {
"QuerySpec": {
"type": "object",
"description": "Detailed query specification object",
"properties": {
"name": {
"type": "string",
"description": "Optional name for the query"
},
"uses": {
"type": "string",
"description": "The query or query suite to use"
}
},
"required": ["uses"],
"additionalProperties": false
},
"QueryFilter": {
"description": "Query filter that can either include or exclude queries",
"oneOf": [
{
"$ref": "#/definitions/ExcludeQueryFilter"
},
{
"$ref": "#/definitions/IncludeQueryFilter"
}
]
},
"ExcludeQueryFilter": {
"type": "object",
"description": "Filter to exclude queries",
"properties": {
"exclude": {
"type": "object",
"description": "Queries to exclude",
"additionalProperties": {
"oneOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "string"
}
]
}
}
},
"required": ["exclude"],
"additionalProperties": false
},
"IncludeQueryFilter": {
"type": "object",
"description": "Filter to include queries",
"properties": {
"include": {
"type": "object",
"description": "Queries to include",
"additionalProperties": {
"oneOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "string"
}
]
}
}
},
"required": ["include"],
"additionalProperties": false
}
}
}
+7
View File
@@ -21,6 +21,13 @@ export function getConfigFileParseErrorMessage(
return `Cannot parse "${configFile}": ${message}`;
}
export function getInvalidConfigFileMessage(
configFile: string,
detail: string,
): string {
return `The configuration file "${configFile}" is invalid: ${detail}`;
}
export function getConfigFileRepoFormatInvalidMessage(
configFile: string,
): string {