From f99fdee32f4823803f110ada188fa4d5adb955fd Mon Sep 17 00:00:00 2001 From: Andrey Melikhov Date: Thu, 10 Aug 2023 12:46:33 +0300 Subject: [PATCH] feat: enable pre-pr lint (#15) --- .eslintrc | 7 ++ .github/workflows/ci.yaml | 26 ++++ .github/workflows/release.yml | 1 + .prettierrc.js | 1 + a11y.js | 2 +- base.js | 219 ++++++++++++++++++---------------- constants.js | 2 +- package-lock.json | 20 +++- package.json | 4 +- react.js | 82 ++++++------- server.js | 6 +- 11 files changed, 212 insertions(+), 158 deletions(-) create mode 100644 .eslintrc create mode 100644 .github/workflows/ci.yaml create mode 100644 .prettierrc.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..9ae959a --- /dev/null +++ b/.eslintrc @@ -0,0 +1,7 @@ +{ + "extends": ["./index.js", "./prettier.js"], + "root": true, + "env": { + "node": true + } +} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..3f93c58 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,26 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + verify_files: + name: Verify Files + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Setup Node + uses: actions/setup-node@v2 + with: + node-version: '18.x' + cache: 'npm' + - name: Install Packages + run: npm ci + - name: Lint Files + run: npm run lint diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7d137e4..f7830c1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,3 +12,4 @@ jobs: with: github-token: ${{ secrets.GRAVITY_UI_BOT_GITHUB_TOKEN }} npm-token: ${{ secrets.GRAVITY_UI_BOT_NPM_TOKEN }} + node-version: 18 diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..5da9c2e --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1 @@ +module.exports = require('@gravity-ui/prettier-config'); diff --git a/a11y.js b/a11y.js index 816a9ae..4fcc64b 100644 --- a/a11y.js +++ b/a11y.js @@ -2,7 +2,7 @@ module.exports = { extends: ['plugin:jsx-a11y/recommended'], parserOptions: { ecmaFeatures: { - jsx: true + jsx: true, }, }, }; diff --git a/base.js b/base.js index c66bc02..6edc6a6 100644 --- a/base.js +++ b/base.js @@ -20,11 +20,11 @@ module.exports = { // Best Practices 'array-callback-return': ERROR, 'block-scoped-var': WARNING, - 'complexity': WARNING, + complexity: WARNING, 'consistent-return': WARNING, - 'curly': ERROR, + curly: ERROR, 'dot-location': [ERROR, 'property'], - 'eqeqeq': [WARNING, 'always'], + eqeqeq: [WARNING, 'always'], 'guard-for-in': ERROR, 'no-caller': ERROR, 'no-console': WARNING, @@ -59,7 +59,7 @@ module.exports = { 'no-useless-concat': ERROR, 'no-void': ERROR, 'no-with': ERROR, - 'radix': WARNING, + radix: WARNING, 'wrap-iife': [ERROR, 'inside'], // Variables @@ -76,7 +76,7 @@ module.exports = { 'no-path-concat': WARNING, // Stylistic Issues - 'camelcase': [ERROR, {properties: 'never'}], + camelcase: [ERROR, {properties: 'never'}], 'comma-style': [ERROR, 'last'], 'max-depth': [WARNING, {maximum: 5}], 'new-cap': ERROR, @@ -89,9 +89,12 @@ module.exports = { 'no-new-object': WARNING, 'no-restricted-syntax': [ERROR, 'WithStatement'], 'no-unneeded-ternary': ERROR, - 'sort-imports': [ERROR, { - ignoreDeclarationSort: true - }], + 'sort-imports': [ + ERROR, + { + ignoreDeclarationSort: true, + }, + ], // ECMAStrict 6 'no-duplicate-imports': ERROR, @@ -108,112 +111,122 @@ module.exports = { 'import/order': [ ERROR, { - 'alphabetize': { - order: 'asc' + alphabetize: { + order: 'asc', }, 'newlines-between': 'always', - 'groups': [ - 'builtin', - 'external', - 'internal', - 'parent', - 'sibling', - 'index' - ], - 'warnOnUnassignedImports': true - } - ] + groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], + warnOnUnassignedImports: true, + }, + ], }, - overrides: [{ - files: ['*.ts', '*.tsx'], - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint'], - rules: { - // TypeScript compiler handles these on its own - 'strict': OFF, - 'no-undef': OFF, - 'no-dupe-class-members': OFF, + overrides: [ + { + files: ['*.ts', '*.tsx'], + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint'], + rules: { + // TypeScript compiler handles these on its own + strict: OFF, + 'no-undef': OFF, + 'no-dupe-class-members': OFF, - 'valid-jsdoc': [WARNING, { - // type annotations are redundant when in TS files - requireReturnType: false, - requireParamType: false, - // same as for JS - requireParamDescription: false, - requireReturnDescription: false, - }], + 'valid-jsdoc': [ + WARNING, + { + // type annotations are redundant when in TS files + requireReturnType: false, + requireParamType: false, + // same as for JS + requireParamDescription: false, + requireReturnDescription: false, + }, + ], - // TypeScript-specific extension rules - 'no-array-constructor': OFF, - 'no-duplicate-imports': OFF, - 'no-loop-func': OFF, - 'no-redeclare': OFF, - 'no-shadow': OFF, - 'no-unused-expressions': OFF, - 'no-unused-vars': OFF, - 'no-use-before-define': OFF, - 'no-useless-constructor': OFF, - '@typescript-eslint/no-array-constructor': WARNING, - '@typescript-eslint/no-duplicate-imports': ERROR, - '@typescript-eslint/no-loop-func': ERROR, - '@typescript-eslint/no-redeclare': ERROR, - '@typescript-eslint/no-shadow': WARNING, - '@typescript-eslint/no-unused-expressions': ERROR, - '@typescript-eslint/no-unused-vars': [ERROR, { - argsIgnorePattern: '^_', - varsIgnorePattern: '^_', - }], - '@typescript-eslint/no-use-before-define': [WARNING, {functions: false}], - '@typescript-eslint/no-useless-constructor': ERROR, + // TypeScript-specific extension rules + 'no-array-constructor': OFF, + 'no-duplicate-imports': OFF, + 'no-loop-func': OFF, + 'no-redeclare': OFF, + 'no-shadow': OFF, + 'no-unused-expressions': OFF, + 'no-unused-vars': OFF, + 'no-use-before-define': OFF, + 'no-useless-constructor': OFF, + '@typescript-eslint/no-array-constructor': WARNING, + '@typescript-eslint/no-duplicate-imports': ERROR, + '@typescript-eslint/no-loop-func': ERROR, + '@typescript-eslint/no-redeclare': ERROR, + '@typescript-eslint/no-shadow': WARNING, + '@typescript-eslint/no-unused-expressions': ERROR, + '@typescript-eslint/no-unused-vars': [ + ERROR, + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + }, + ], + '@typescript-eslint/no-use-before-define': [WARNING, {functions: false}], + '@typescript-eslint/no-useless-constructor': ERROR, - '@typescript-eslint/naming-convention': [ - ERROR, - { - selector: 'typeLike', - format: ['PascalCase'], - leadingUnderscore: 'forbid', - }, - ], - '@typescript-eslint/member-delimiter-style': ERROR, - '@typescript-eslint/member-ordering': [ERROR, { - 'default': [ - 'public-static-field', - 'protected-static-field', - 'private-static-field', + '@typescript-eslint/naming-convention': [ + ERROR, + { + selector: 'typeLike', + format: ['PascalCase'], + leadingUnderscore: 'forbid', + }, + ], + '@typescript-eslint/member-delimiter-style': ERROR, + '@typescript-eslint/member-ordering': [ + ERROR, + { + default: [ + 'public-static-field', + 'protected-static-field', + 'private-static-field', - 'public-static-method', - 'protected-static-method', - 'private-static-method', + 'public-static-method', + 'protected-static-method', + 'private-static-method', - 'public-instance-field', - 'protected-instance-field', - 'private-instance-field', + 'public-instance-field', + 'protected-instance-field', + 'private-instance-field', - 'constructor', + 'constructor', - 'public-instance-method', - 'protected-instance-method', - 'private-instance-method', + 'public-instance-method', + 'protected-instance-method', + 'private-instance-method', + ], + }, ], - }], - '@typescript-eslint/explicit-member-accessibility': [ERROR, {'accessibility': 'no-public'}], - '@typescript-eslint/consistent-type-assertions': ERROR, - '@typescript-eslint/no-explicit-any': WARNING, - '@typescript-eslint/no-inferrable-types': ERROR, - '@typescript-eslint/no-namespace': ERROR, - '@typescript-eslint/no-non-null-assertion': WARNING, - '@typescript-eslint/no-parameter-properties': ERROR, - '@typescript-eslint/triple-slash-reference': ERROR, - '@typescript-eslint/prefer-namespace-keyword': ERROR, - '@typescript-eslint/type-annotation-spacing': [ERROR, { - before: true, - after: true, - overrides: { - colon: { - before: false, + '@typescript-eslint/explicit-member-accessibility': [ + ERROR, + {accessibility: 'no-public'}, + ], + '@typescript-eslint/consistent-type-assertions': ERROR, + '@typescript-eslint/no-explicit-any': WARNING, + '@typescript-eslint/no-inferrable-types': ERROR, + '@typescript-eslint/no-namespace': ERROR, + '@typescript-eslint/no-non-null-assertion': WARNING, + '@typescript-eslint/no-parameter-properties': ERROR, + '@typescript-eslint/triple-slash-reference': ERROR, + '@typescript-eslint/prefer-namespace-keyword': ERROR, + '@typescript-eslint/type-annotation-spacing': [ + ERROR, + { + before: true, + after: true, + overrides: { + colon: { + before: false, + }, + }, }, - }, - }], + ], + }, }, - }], + ], }; diff --git a/constants.js b/constants.js index e141540..1a4cfb3 100644 --- a/constants.js +++ b/constants.js @@ -1,5 +1,5 @@ module.exports = { OFF: 0, WARNING: 1, - ERROR: 2 + ERROR: 2, }; diff --git a/package-lock.json b/package-lock.json index cf240cd..333bf23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "devDependencies": { "@commitlint/cli": "17.0.3", "@commitlint/config-conventional": "17.0.3", + "@gravity-ui/prettier-config": "^1.0.1", "eslint": "8.8.0", "husky": "8.0.1" }, @@ -1083,6 +1084,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@gravity-ui/prettier-config": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@gravity-ui/prettier-config/-/prettier-config-1.0.1.tgz", + "integrity": "sha512-VpTM+OiUMgXjwc7HBo0ekxBFghzELsnE/RFBYwbkbIqm0NrL4SiEPzne1IyEY/WsfI8om1hpn81t+qjGbicMSw==", + "dev": true, + "peerDependencies": { + "prettier": "^2.2.1" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.9.5", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", @@ -4705,15 +4715,15 @@ } }, "node_modules/prettier": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.1.tgz", - "integrity": "sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "peer": true, "bin": { - "prettier": "bin/prettier.cjs" + "prettier": "bin-prettier.js" }, "engines": { - "node": ">=14" + "node": ">=10.13.0" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" diff --git a/package.json b/package.json index a6189ef..ba5b71a 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,8 @@ "homepage": "https://github.com/gravity-ui/eslint-config#readme", "scripts": { "prepare": "husky install", - "test": "echo \"Error: no test specified\" && exit 0" + "test": "echo \"Error: no test specified\" && exit 0", + "lint": "eslint ." }, "dependencies": { "@babel/core": "7.16.0", @@ -46,6 +47,7 @@ "devDependencies": { "@commitlint/cli": "17.0.3", "@commitlint/config-conventional": "17.0.3", + "@gravity-ui/prettier-config": "^1.0.1", "eslint": "8.8.0", "husky": "8.0.1" }, diff --git a/react.js b/react.js index cf22204..da18551 100644 --- a/react.js +++ b/react.js @@ -8,7 +8,7 @@ module.exports = { plugins: ['react', 'react-hooks', 'import'], parserOptions: { ecmaFeatures: { - jsx: true + jsx: true, }, babelOptions: { presets: ['@babel/preset-react'], @@ -22,73 +22,67 @@ module.exports = { 'import/order': [ ERROR, { - 'alphabetize': { - order: 'asc' + alphabetize: { + order: 'asc', }, 'newlines-between': 'always', - 'groups': [ - 'builtin', - 'external', - 'internal', - 'parent', - 'sibling', - 'index' - ], - 'pathGroups': [ + groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], + pathGroups: [ { pattern: 'react', group: 'external', - position: 'before' + position: 'before', }, { pattern: assetFiles, patternOptions: { dot: true, nocomment: true, - matchBase: true + matchBase: true, }, group: 'type', - position: 'after' + position: 'after', }, { pattern: styleFiles, patternOptions: { dot: true, nocomment: true, - matchBase: true + matchBase: true, }, group: 'type', - position: 'after' - } - ], - 'pathGroupsExcludedImportTypes': [ - assetFiles, - styleFiles, - 'react' + position: 'after', + }, ], - 'warnOnUnassignedImports': true - } - ] + pathGroupsExcludedImportTypes: [assetFiles, styleFiles, 'react'], + warnOnUnassignedImports: true, + }, + ], }, settings: { react: { - version: 'detect' - } + version: 'detect', + }, }, - overrides: [{ - files: ['*.ts', '*.tsx'], - rules: { - 'react/prop-types': OFF, - 'react/sort-comp': [WARNING, { - 'order': [ - 'static-variables', - 'static-methods', - 'instance-variables', - 'lifecycle', - 'render', - 'everything-else' - ] - }] - } - }] + overrides: [ + { + files: ['*.ts', '*.tsx'], + rules: { + 'react/prop-types': OFF, + 'react/sort-comp': [ + WARNING, + { + order: [ + 'static-variables', + 'static-methods', + 'instance-variables', + 'lifecycle', + 'render', + 'everything-else', + ], + }, + ], + }, + }, + ], }; diff --git a/server.js b/server.js index 9bb786f..7f09abc 100644 --- a/server.js +++ b/server.js @@ -3,7 +3,7 @@ const {WARNING, ERROR} = require('./constants'); module.exports = { plugins: ['security'], env: { - node: true + node: true, }, rules: { 'global-require': WARNING, @@ -17,6 +17,6 @@ module.exports = { 'security/detect-non-literal-require': ERROR, 'security/detect-possible-timing-attacks': ERROR, 'security/detect-pseudoRandomBytes': ERROR, - 'security/detect-unsafe-regex': ERROR - } + 'security/detect-unsafe-regex': ERROR, + }, };