mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Linting: Speed up betterer by sharing eslint instances by groups (#60019)
This commit is contained in:
parent
a6e8f651ac
commit
a7a2c0f373
104
.betterer.ts
104
.betterer.ts
@ -2,6 +2,9 @@ import { regexp } from '@betterer/regexp';
|
||||
import { BettererFileTest } from '@betterer/betterer';
|
||||
import { ESLint, Linter } from 'eslint';
|
||||
import { existsSync } from 'fs';
|
||||
import { exec } from 'child_process';
|
||||
import path from 'path';
|
||||
import glob from 'glob';
|
||||
|
||||
export default {
|
||||
'no enzyme tests': () => regexp(/from 'enzyme'/g).include('**/*.test.*'),
|
||||
@ -22,54 +25,79 @@ function countUndocumentedStories() {
|
||||
});
|
||||
}
|
||||
|
||||
async function findEslintConfigFiles(): Promise<string[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
glob('**/.eslintrc', (err, files) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
resolve(files);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function countEslintErrors() {
|
||||
return new BettererFileTest(async (filePaths, fileTestResult, resolver) => {
|
||||
const { baseDirectory } = resolver;
|
||||
const cli = new ESLint({ cwd: baseDirectory });
|
||||
|
||||
await Promise.all(
|
||||
filePaths.map(async (filePath) => {
|
||||
const linterOptions = (await cli.calculateConfigForFile(filePath)) as Linter.Config;
|
||||
const eslintConfigFiles = await findEslintConfigFiles();
|
||||
const eslintConfigMainPaths = eslintConfigFiles.map((file) => path.resolve(path.dirname(file)));
|
||||
|
||||
const rules: Partial<Linter.RulesRecord> = {
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
};
|
||||
const baseRules: Partial<Linter.RulesRecord> = {
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
};
|
||||
|
||||
const isTestFile =
|
||||
filePath.endsWith('.test.tsx') ||
|
||||
filePath.endsWith('.test.ts') ||
|
||||
filePath.includes('__mocks__') ||
|
||||
filePath.includes('public/test/');
|
||||
const nonTestFilesRules: Partial<Linter.RulesRecord> = {
|
||||
...baseRules,
|
||||
'@typescript-eslint/consistent-type-assertions': ['error', { assertionStyle: 'never' }],
|
||||
};
|
||||
|
||||
if (!isTestFile) {
|
||||
rules['@typescript-eslint/consistent-type-assertions'] = [
|
||||
'error',
|
||||
{
|
||||
assertionStyle: 'never',
|
||||
},
|
||||
];
|
||||
}
|
||||
// group files by eslint config file
|
||||
// this will create two file groups for each eslint config file
|
||||
// one for test files and one for non-test files
|
||||
const fileGroups: Record<string, string[]> = {};
|
||||
|
||||
const runner = new ESLint({
|
||||
baseConfig: {
|
||||
...linterOptions,
|
||||
rules,
|
||||
},
|
||||
useEslintrc: false,
|
||||
cwd: baseDirectory,
|
||||
});
|
||||
for (const filePath of filePaths) {
|
||||
let configPath = eslintConfigMainPaths.find((configPath) => filePath.startsWith(configPath)) ?? '';
|
||||
const isTestFile =
|
||||
filePath.endsWith('.test.tsx') ||
|
||||
filePath.endsWith('.test.ts') ||
|
||||
filePath.includes('__mocks__') ||
|
||||
filePath.includes('public/test/');
|
||||
|
||||
const lintResults = await runner.lintFiles([filePath]);
|
||||
lintResults
|
||||
.filter((lintResult) => lintResult.source)
|
||||
.forEach((lintResult) => {
|
||||
const { messages } = lintResult;
|
||||
const file = fileTestResult.addFile(filePath, '');
|
||||
messages.forEach((message, index) => {
|
||||
file.addIssue(0, 0, message.message, `${index}`);
|
||||
});
|
||||
if (isTestFile) {
|
||||
configPath += '-test';
|
||||
}
|
||||
if (!fileGroups[configPath]) {
|
||||
fileGroups[configPath] = [];
|
||||
}
|
||||
fileGroups[configPath].push(filePath);
|
||||
}
|
||||
|
||||
for (const configPath of Object.keys(fileGroups)) {
|
||||
const rules = configPath.endsWith('-test') ? baseRules : nonTestFilesRules;
|
||||
// this is by far the slowest part of this code. It takes eslint about 2 seconds just to find the config
|
||||
const linterOptions = (await cli.calculateConfigForFile(fileGroups[configPath][0])) as Linter.Config;
|
||||
const runner = new ESLint({
|
||||
baseConfig: {
|
||||
...linterOptions,
|
||||
rules: rules,
|
||||
},
|
||||
useEslintrc: false,
|
||||
cwd: baseDirectory,
|
||||
});
|
||||
const lintResults = await runner.lintFiles(fileGroups[configPath]);
|
||||
lintResults
|
||||
.filter((lintResult) => lintResult.source)
|
||||
.forEach((lintResult) => {
|
||||
const { messages } = lintResult;
|
||||
const filePath = lintResult.filePath;
|
||||
const file = fileTestResult.addFile(filePath, '');
|
||||
messages.forEach((message, index) => {
|
||||
file.addIssue(0, 0, message.message, `${index}`);
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -120,6 +120,7 @@
|
||||
"@types/enzyme-adapter-react-16": "1.0.6",
|
||||
"@types/eslint": "8.4.9",
|
||||
"@types/file-saver": "2.0.5",
|
||||
"@types/glob": "^8.0.0",
|
||||
"@types/google.analytics": "^0.0.42",
|
||||
"@types/gtag.js": "^0.0.12",
|
||||
"@types/history": "4.7.11",
|
||||
|
11
yarn.lock
11
yarn.lock
@ -10781,6 +10781,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/glob@npm:^8.0.0":
|
||||
version: 8.0.0
|
||||
resolution: "@types/glob@npm:8.0.0"
|
||||
dependencies:
|
||||
"@types/minimatch": "*"
|
||||
"@types/node": "*"
|
||||
checksum: 1817b05f5a8aed851d102a65b5e926d5c777bef927ea62b36d635860eef5364f2046bb5a692d135b6f2b28f34e4a9d44ade9396122c0845bcc7636d35f624747
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/google.analytics@npm:^0.0.42":
|
||||
version: 0.0.42
|
||||
resolution: "@types/google.analytics@npm:0.0.42"
|
||||
@ -21518,6 +21528,7 @@ __metadata:
|
||||
"@types/enzyme-adapter-react-16": 1.0.6
|
||||
"@types/eslint": 8.4.9
|
||||
"@types/file-saver": 2.0.5
|
||||
"@types/glob": ^8.0.0
|
||||
"@types/google.analytics": ^0.0.42
|
||||
"@types/gtag.js": ^0.0.12
|
||||
"@types/history": 4.7.11
|
||||
|
Loading…
Reference in New Issue
Block a user