Chore: Move betterer eslint rules to separate file and allow opting in (#96240)

* Move betterer eslint rules to separate file and allow opt-in for local dev

* Add betterer eslint to codeowners
This commit is contained in:
Tom Ratcliffe 2024-11-15 14:01:39 +00:00 committed by GitHub
parent 97103a5256
commit 7ae0d551fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 60 additions and 51 deletions

View File

@ -0,0 +1,45 @@
// @ts-check
/**
* @type {Array<import('eslint').Linter.Config>}
*/
module.exports = [
{
files: ['**/*.{js,jsx,ts,tsx}'],
rules: {
'@typescript-eslint/no-explicit-any': 'error',
'@grafana/no-aria-label-selectors': 'error',
'no-restricted-imports': [
'error',
{
patterns: [
{
group: ['@grafana/ui*', '*/Layout/*'],
importNames: ['Layout', 'HorizontalGroup', 'VerticalGroup'],
message: 'Use Stack component instead.',
},
],
},
],
},
},
{
files: ['**/*.{ts,tsx}'],
ignores: ['**/*.{test,spec}.{ts,tsx}', '**/__mocks__/**', '**/public/test/**'],
rules: {
'@typescript-eslint/consistent-type-assertions': ['error', { assertionStyle: 'never' }],
},
},
{
files: ['public/app/**/*.{ts,tsx}'],
rules: {
'no-barrel-files/no-barrel-files': 'error',
},
},
{
files: ['public/**/*.tsx', 'packages/grafana-ui/**/*.tsx'],
ignores: ['public/app/plugins/**', '**/*.story.tsx', '**/*.{test,spec}.{ts,tsx}', '**/__mocks__/', 'public/test'],
rules: {
'@grafana/no-untranslated-strings': 'error',
},
},
];

View File

@ -1,7 +1,9 @@
import { BettererFileTest } from '@betterer/betterer'; import { BettererFileTest } from '@betterer/betterer';
import { ESLint, Linter } from 'eslint'; import { ESLint } from 'eslint';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
import config from './.betterer.eslint.config';
// Why are we ignoring these? // Why are we ignoring these?
// They're all deprecated/being removed so doesn't make sense to fix types // They're all deprecated/being removed so doesn't make sense to fix types
const eslintPathsToIgnore = [ const eslintPathsToIgnore = [
@ -81,56 +83,6 @@ function countEslintErrors() {
const { baseDirectory } = resolver; const { baseDirectory } = resolver;
const baseRules: Partial<Linter.RulesRecord> = {
'@typescript-eslint/no-explicit-any': 'error',
'@grafana/no-aria-label-selectors': 'error',
'no-restricted-imports': [
'error',
{
patterns: [
{
group: ['@grafana/ui*', '*/Layout/*'],
importNames: ['Layout', 'HorizontalGroup', 'VerticalGroup'],
message: 'Use Stack component instead.',
},
],
},
],
};
const config: Linter.Config[] = [
{
files: ['**/*.{js,jsx,ts,tsx}'],
rules: baseRules,
},
{
files: ['**/*.{ts,tsx}'],
ignores: ['**/*.{test,spec}.{ts,tsx}', '**/__mocks__/**', '**/public/test/**'],
rules: {
'@typescript-eslint/consistent-type-assertions': ['error', { assertionStyle: 'never' }],
},
},
{
files: ['public/app/**/*.{ts,tsx}'],
rules: {
'no-barrel-files/no-barrel-files': 'error',
},
},
{
files: ['public/**/*.tsx', 'packages/grafana-ui/**/*.tsx'],
ignores: [
'public/app/plugins/**',
'**/*.story.tsx',
'**/*.{test,spec}.{ts,tsx}',
'**/__mocks__/',
'public/test',
],
rules: {
'@grafana/no-untranslated-strings': 'error',
},
},
];
const runner = new ESLint({ const runner = new ESLint({
overrideConfig: config, overrideConfig: config,
cwd: baseDirectory, cwd: baseDirectory,

1
.github/CODEOWNERS vendored
View File

@ -385,6 +385,7 @@
/tsconfig.json @grafana/frontend-ops /tsconfig.json @grafana/frontend-ops
/.editorconfig @grafana/frontend-ops /.editorconfig @grafana/frontend-ops
/eslint.config.js @grafana/frontend-ops /eslint.config.js @grafana/frontend-ops
/.betterer.eslint.config.js @grafana/frontend-ops
/.gitattributes @grafana/frontend-ops /.gitattributes @grafana/frontend-ops
/.gitignore @grafana/frontend-ops /.gitignore @grafana/frontend-ops
/.nvmrc @grafana/frontend-ops /.nvmrc @grafana/frontend-ops

View File

@ -2034,3 +2034,6 @@ fail_tests_on_console = true
# Whether or not to enable the MSW mock API, which intercepts requests and returns mock data # Whether or not to enable the MSW mock API, which intercepts requests and returns mock data
# Should only be used for local development or demo purposes # Should only be used for local development or demo purposes
mock_api = false mock_api = false
# Whether to enable betterer eslint rules for local development
# Useful if you want to always see betterer rules that we're trying to fix so they're more prevalent
betterer_eslint_rules = false

View File

@ -14,6 +14,12 @@ const unicornPlugin = require('eslint-plugin-unicorn');
const grafanaConfig = require('@grafana/eslint-config/flat'); const grafanaConfig = require('@grafana/eslint-config/flat');
const grafanaPlugin = require('@grafana/eslint-plugin'); const grafanaPlugin = require('@grafana/eslint-plugin');
const bettererConfig = require('./.betterer.eslint.config');
const getEnvConfig = require('./scripts/webpack/env-util');
const envConfig = getEnvConfig();
const enableBettererRules = envConfig.frontend_dev_betterer_eslint_rules;
/** /**
* @type {Array<import('eslint').Linter.Config>} * @type {Array<import('eslint').Linter.Config>}
*/ */
@ -43,6 +49,8 @@ module.exports = [
'scripts/grafana-server/tmp', 'scripts/grafana-server/tmp',
], ],
}, },
// Conditionally run the betterer rules if enabled in dev's config
...(enableBettererRules ? bettererConfig : []),
grafanaConfig, grafanaConfig,
{ {
name: 'react/jsx-runtime', name: 'react/jsx-runtime',