Chore: Move betterer eslint rules to use eslint suppressions (#106267)

Co-authored-by: joshhunt <josh.hunt@grafana.com>
This commit is contained in:
Tom Ratcliffe
2025-09-04 10:47:13 +01:00
committed by GitHub
co-authored by joshhunt
parent df685757ff
commit 55b638ea98
16 changed files with 5219 additions and 4703 deletions
+12
View File
@@ -32,6 +32,17 @@ do
BETTERER_STATS+="\"grafana.ci-code.betterer.${name}\": \"${value}\","
done <<< "$(yarn betterer:stats)"
ESLINT_STATS=""
yarn lint:ts --format ./scripts/cli/eslint-stats-reporter.mjs -o eslint-stats.txt
while read -r name value
do
ESLINT_STATS+=$'\n '
# We still report these as "betterer" as the dashboards/other scripts will still look for it there
ESLINT_STATS+="\"grafana.ci-code.betterer.${name}\": \"${value}\","
done <<< "$(cat eslint-stats.txt)"
rm eslint-stats.txt
I18N_STATS=""
while read -r name value
do
@@ -49,6 +60,7 @@ done <<< "$(yarn themes:usage | awk '$4 == "@grafana/theme-token-usage" {print $
echo "Metrics: {
$THEME_TOKEN_USAGE
$BETTERER_STATS
$ESLINT_STATS
$I18N_STATS
\"grafana.ci-code.strictErrors\": \"${ERROR_COUNT}\",
\"grafana.ci-code.accessibilityErrors\": \"${ACCESSIBILITY_ERRORS}\",
+56
View File
@@ -0,0 +1,56 @@
//@ts-check
import lodash from 'lodash';
const { camelCase } = lodash;
/**
* Rule IDs that are overly verbose and that we want to combine so they report more cleanly
*
* i.e. so we can report `reactHooksRulesOfHooks` instead of `reactHookFooIsCalledConditionallyReactHooksMust...`
*/
const rulesToCombine = ['react-hooks/rules-of-hooks', 'react/no-unescaped-entities', 'no-barrel-files/no-barrel-files'];
const legacyChecksToTransform = [
{ messageRegex: /gfFormUsage/i, prefix: 'noGfFormUsage' },
{ messageRegex: /skippingA11Y/i, prefix: 'noSkippingA11YTestsInStories' },
];
/**
* Custom formatter that outputs suppressed rule violations in a format suitable for
* consuming on our CI code stats scripts
*
* Output in the format:
* @example
* betterEslint_reactHooksRulesOfHooks 123
* betterEslint_noBarrelFilesNoBarrelFiles 123
*
* @type {import('eslint').ESLint.FormatterFunction}
*/
export default function statsReporter(results) {
/** @type {Record<string, number>} */
const countByMessage = {};
for (const result of results) {
for (const message of result.suppressedMessages) {
// eslint disable directives count as suppressions
// we only want to report the case where everything is a file suppression
const everySuppressionIsFile = message.suppressions.every((suppression) => suppression.kind === 'file');
if (!everySuppressionIsFile) {
continue;
}
const key =
message.ruleId && rulesToCombine.includes(message.ruleId)
? camelCase(message.ruleId)
: camelCase(message.message);
countByMessage[key] = (countByMessage[key] || 0) + 1;
}
}
return Object.entries(countByMessage)
.map(([key, value]) => {
const prefix = legacyChecksToTransform.find((v) => v.messageRegex.test(key))?.prefix || 'betterEslint';
return `${prefix}_${key} ${value}`;
})
.join('\n');
}
+2 -1
View File
@@ -10,5 +10,6 @@
"compilerOptions": {
"module": "commonjs"
}
}
},
"include": ["./**/*.ts", "./**/*.mts", "./**/*.js", "./**/*.mjs"]
}