Merge pull request #1642 from github/koesie10/validate-mocks
Add linter for scenario files
This commit is contained in:
5
.github/workflows/main.yml
vendored
5
.github/workflows/main.yml
vendored
@@ -103,6 +103,11 @@ jobs:
|
||||
run: |
|
||||
npm run lint
|
||||
|
||||
- name: Lint scenarios
|
||||
working-directory: extensions/ql-vscode
|
||||
run: |
|
||||
npm run lint:scenarios
|
||||
|
||||
- name: Run unit tests (Linux)
|
||||
working-directory: extensions/ql-vscode
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
|
||||
1026
extensions/ql-vscode/package-lock.json
generated
1026
extensions/ql-vscode/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1234,7 +1234,8 @@
|
||||
"lint": "eslint src test --ext .ts,.tsx --max-warnings=0",
|
||||
"format-staged": "lint-staged",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"build-storybook": "build-storybook"
|
||||
"build-storybook": "build-storybook",
|
||||
"lint:scenarios": "ts-node scripts/lint-scenarios.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@octokit/plugin-retry": "^3.0.9",
|
||||
@@ -1329,6 +1330,7 @@
|
||||
"@types/xml2js": "~0.4.4",
|
||||
"@typescript-eslint/eslint-plugin": "^4.26.0",
|
||||
"@typescript-eslint/parser": "^4.26.0",
|
||||
"ajv": "^8.11.0",
|
||||
"ansi-colors": "^4.1.1",
|
||||
"applicationinsights": "^2.3.5",
|
||||
"babel-loader": "^8.2.5",
|
||||
@@ -1362,6 +1364,7 @@
|
||||
"sinon-chai": "~3.5.0",
|
||||
"through2": "^4.0.2",
|
||||
"ts-jest": "^29.0.1",
|
||||
"ts-json-schema-generator": "^1.1.2",
|
||||
"ts-loader": "^8.1.0",
|
||||
"ts-node": "^10.7.0",
|
||||
"ts-protoc-gen": "^0.9.0",
|
||||
|
||||
79
extensions/ql-vscode/scripts/lint-scenarios.ts
Normal file
79
extensions/ql-vscode/scripts/lint-scenarios.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
|
||||
import Ajv from 'ajv';
|
||||
import * as tsj from 'ts-json-schema-generator';
|
||||
|
||||
const extensionDirectory = path.resolve(__dirname, '..');
|
||||
const rootDirectory = path.resolve(extensionDirectory, '../..');
|
||||
const scenariosDirectory = path.resolve(extensionDirectory, 'src/mocks/scenarios');
|
||||
|
||||
const debug = process.env.RUNNER_DEBUG || process.argv.includes('--debug');
|
||||
|
||||
async function lintScenarios() {
|
||||
const schema = tsj.createGenerator({
|
||||
path: path.resolve(extensionDirectory, 'src/mocks/gh-api-request.ts'),
|
||||
tsconfig: path.resolve(extensionDirectory, 'tsconfig.json'),
|
||||
type: 'GitHubApiRequest',
|
||||
skipTypeCheck: true,
|
||||
topRef: true,
|
||||
additionalProperties: true,
|
||||
}).createSchema('GitHubApiRequest');
|
||||
|
||||
const ajv = new Ajv();
|
||||
|
||||
if (!ajv.validateSchema(schema)) {
|
||||
throw new Error('Invalid schema: ' + ajv.errorsText());
|
||||
}
|
||||
|
||||
const validate = await ajv.compile(schema);
|
||||
|
||||
let invalidFiles = 0;
|
||||
|
||||
if (!(await fs.pathExists(scenariosDirectory))) {
|
||||
console.error('Scenarios directory does not exist: ' + scenariosDirectory);
|
||||
// Do not exit with a non-zero status code, as this is not a fatal error.
|
||||
return;
|
||||
}
|
||||
|
||||
for await (const file of getFiles(scenariosDirectory)) {
|
||||
if (!file.endsWith('.json')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const contents = await fs.readFile(file, 'utf8');
|
||||
const data = JSON.parse(contents);
|
||||
|
||||
if (!validate(data)) {
|
||||
validate.errors?.forEach(error => {
|
||||
// https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message
|
||||
console.log(`::error file=${path.relative(rootDirectory, file)}::${error.instancePath}: ${error.message}`);
|
||||
});
|
||||
invalidFiles++;
|
||||
} else if (debug) {
|
||||
console.log(`File '${path.relative(rootDirectory, file)}' is valid`);
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidFiles > 0) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/45130990
|
||||
async function* getFiles(dir: string): AsyncGenerator<string> {
|
||||
const dirents = await fs.readdir(dir, { withFileTypes: true });
|
||||
for (const dirent of dirents) {
|
||||
const res = path.resolve(dir, dirent.name);
|
||||
if (dirent.isDirectory()) {
|
||||
yield* getFiles(res);
|
||||
} else {
|
||||
yield res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lintScenarios().catch(e => {
|
||||
console.error(e);
|
||||
process.exit(2);
|
||||
});
|
||||
Reference in New Issue
Block a user