Skip to content

Commit 1302eb5

Browse files
authored
Initial prototype of an ESLint-based validator of the Elasticsearch specification (#4400)
* Initial prototype of an ESLint-based validator of the Elasticsearch specification * Add linter to make validate target * Stop using mjs file extension * Add testing framework * Typo * Fix ESM setup in spec repo * Formatting cleanup * Clarifications in README about writing rules * Add invalid-node-types rule * Appease the linter * Add license headers * Appease the linter again! * Install validator dependencies in makefile * Ignore new ESLint-related files in validate-pr script * Attempt to short-circuit reporting tool when it gets an invalid file * Debugging the validate-pr script to find an issue * Skip markdown files in validate-pr script
1 parent dbbdd21 commit 1302eb5

15 files changed

+2564
-6
lines changed

.github/validate-pr/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,12 @@ async function run() {
9090
if (file.startsWith('specification/_spec_utils')) continue
9191
if (file.startsWith('specification/_doc_ids')) continue
9292
if (file.startsWith('specification/_json_spec')) continue
93-
if (file === 'specification/tsconfig.json') continue
93+
if (file.startsWith('specification/node_modules')) continue
94+
if (file.endsWith('tsconfig.json')) continue
95+
if (file.endsWith('eslint.config.js')) continue
96+
if (file.endsWith('package.json')) continue
97+
if (file.endsWith('package-lock.json')) continue
98+
if (file.endsWith('.md')) continue
9499
if (getApi(file).endsWith('_types')) {
95100
const apis = specification.endpoints
96101
.filter(endpoint => endpoint.name.split('.').filter(s => !privateNames.includes(s))[0] === getApi(file).split('.')[0])

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ SHELL := /bin/bash
22

33
validate: ## Validate a given endpoint request or response
44
@node compiler/run-validations.js --api $(api) --type $(type) --branch $(branch)
5+
@npm run lint --prefix specification
56

67
validate-no-cache: ## Validate a given endpoint request or response without local cache
78
@node compiler/run-validations.js --api $(api) --type $(type) --branch $(branch) --no-cache
@@ -39,6 +40,8 @@ setup: ## Install dependencies for contrib target
3940
@make clean-dep
4041
@npm install --prefix compiler
4142
@npm install --prefix typescript-generator
43+
@npm install --prefix validator
44+
@npm install --prefix specification
4245
@npm install @redocly/cli
4346

4447
clean-dep: ## Clean npm dependencies

docs/specification-structure.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Specification structure
22

33
The [`/specification`](../specification) folders follows a set of rules to
4-
keep the defintion easy to access and contribute, while maintaing
4+
keep the definition easy to access and contribute, while maintaining
55
the generated schema consistent and useful for language generators.
66

77
## Rules
@@ -14,7 +14,7 @@ root of the [`/specification`](../specification) folder as well
1414
as inside the namespaces when necessary.
1515

1616
You should decide if a type should go inside the top-level `_types`
17-
folder or inside a namespace (eg: `indices/_types`) on a case by case basis.
17+
folder or inside a namespace (e.g.: `indices/_types`) on a case by case basis.
1818
A good rule of thumb is that if a type is widely used in the specification,
1919
it should go in the top level `_types`, while if it's used only within
2020
a namespace or a few times in other namespaces, it could go inside the
@@ -29,8 +29,8 @@ end with `Request` or `Response`.
2929

3030
### Request and Response definitions
3131

32-
Request and Reponse definitions should be placed by structly following
33-
the rest-api-spec structure.
32+
Request and Response definitions should be placed by strictly following
33+
the `rest-api-spec` structure.
3434
For example, the request and response definition for `indices.put_mapping`
3535
should go in [`/specification/indices/put_mapping`](../specification/indices/put_mapping).
3636
There are no requirements on the file name, but the type should be
@@ -45,4 +45,4 @@ For example: [`/specification/_global/search`](../specification/_global/search).
4545
### Specification helpers
4646

4747
The specification has a set of custom types used to define complex structures
48-
or behaviors. Those types must be placed in [`/specification/_spec_utils`](../specification/_spec_utils).
48+
or behaviors. Those types must be placed in [`/specification/_spec_utils`](../specification/_spec_utils).

specification/eslint.config.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
import parser from '@typescript-eslint/parser'
20+
import validator from 'eslint-plugin-es-spec'
21+
import { defineConfig } from 'eslint/config'
22+
23+
export default defineConfig({
24+
files: ['**/*.ts'],
25+
languageOptions: {
26+
parser,
27+
parserOptions: {
28+
projectService: true,
29+
tsconfigRootDir: import.meta.dirname
30+
}
31+
},
32+
plugins: { 'es-spec-validator': validator },
33+
rules: {
34+
'es-spec-validator/single-key-dictionary-key-is-string': 'error',
35+
'es-spec-validator/invalid-node-types': 'warn'
36+
}
37+
})

0 commit comments

Comments
 (0)