diff --git a/.github/workflows/strict-check.yml b/.github/workflows/strict-check.yml index 83e8fffac3..c532470d2a 100644 --- a/.github/workflows/strict-check.yml +++ b/.github/workflows/strict-check.yml @@ -32,19 +32,22 @@ jobs: - uses: ./.github/workflows/actions/turbo - - name: Install tsc-output-parser + - name: Collect metrics run: | ROOT=$(pwd) npm install -g @aivenio/tsc-output-parser@2.1.1 cd ./packages/core - npx tsc --strictNullChecks --strictPropertyInitialization --noEmit --pretty false | npx tsc-output-parser > $ROOT/strict_${{ matrix.branch }}.json + pnpm exec tsc --strictNullChecks --strictPropertyInitialization --noEmit --pretty false | npx tsc-output-parser > $ROOT/strict_${{ matrix.branch }}.json + pnpm lint --format json -o $ROOT/eslint_${{ matrix.branch }}.json cd $ROOT - name: Upload strict_${{ matrix.branch }}.json uses: actions/upload-artifact@v4 with: name: strict_${{ matrix.branch }} - path: 'strict_${{ matrix.branch }}.json' + path: | + 'strict_${{ matrix.branch }}.json' + 'eslint_${{ matrix.branch }}.json' comment_on_pr: permissions: diff --git a/packages/core/.eslintignore b/packages/core/.eslintignore index 68102d276f..b1c7ff9b13 100644 --- a/packages/core/.eslintignore +++ b/packages/core/.eslintignore @@ -1,3 +1,4 @@ playwright-ct.config.ts playwright.config.ts stencil.config.ts +src/components.d.ts diff --git a/packages/core/.eslintrc.json b/packages/core/.eslintrc.json index a7ac4abc24..8557349071 100644 --- a/packages/core/.eslintrc.json +++ b/packages/core/.eslintrc.json @@ -13,6 +13,7 @@ "react/jsx-no-bind": 0, "react/jsx-uses-react": 0, "react/react-in-jsx-scope": 0, - "@typescript-eslint/no-confusing-non-null-assertion": "error" + "@typescript-eslint/no-confusing-non-null-assertion": "error", + "@typescript-eslint/no-explicit-any": "warn" } } diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index 15e720471b..16c2b1e5b9 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -17,7 +17,11 @@ "baseUrl": ".", "paths": { "@utils/test": ["src/tests/utils/test"] - } + }, + // Strict check uncomment to check for strict + // "strictNullChecks": true, + // "strictPropertyInitialization": true, + // "noImplicitAny": true, }, "include": ["src"], "exclude": ["node_modules"] diff --git a/scripts/strict-check.ts b/scripts/strict-check.ts index efed3cd262..5e13a60490 100644 --- a/scripts/strict-check.ts +++ b/scripts/strict-check.ts @@ -44,86 +44,47 @@ type Item = { }; }; -const cwd = process.cwd(); - -const strictCheckFileMain = fs.readFileSync(path.join(cwd, 'strict_main.json')); -const strictCheckFilePr = fs.readFileSync(path.join(cwd, 'strict_pr.json')); - -const strictCheckMain = JSON.parse(strictCheckFileMain.toString()) as Item[]; -const strictCheck = JSON.parse(strictCheckFilePr.toString()) as Item[]; - -const totalErrorsMain = strictCheckMain.length; -const totalErrorsPR = strictCheck.length; - -function checkTotal() { - let output: string[] = []; - - if (totalErrorsPR > totalErrorsMain) { - output.push( - `😢 Total errors increased in PR branch: ${ - totalErrorsPR - totalErrorsMain - }` - ); - } else if (totalErrorsPR < totalErrorsMain) { - output.push( - `You decreased the total number of errors in PR branch by ${ - totalErrorsMain - totalErrorsPR - } 🎉` - ); - } else { - output.push(`Total errors are the same in both branches`); - } +export interface EsLint { + filePath: string; + messages: EsLintMessage[]; + suppressedMessages: any[]; + errorCount: number; + fatalErrorCount: number; + warningCount: number; + fixableErrorCount: number; + fixableWarningCount: number; + source: string; + usedDeprecatedRules: EsLintUsedDeprecatedRule[]; +} - return output.join('\n'); +export interface EsLintMessage { + ruleId: string; + severity: number; + message: string; + line: number; + column: number; + nodeType: string; + endLine: number; + endColumn: number; + messageId?: string; + suggestions?: EsLintSuggestion[]; } -function collectErrors(errors: Item[]) { - const errorMap: Map< - string, - { - errors: { - path: Path; - cursor: Cursor; - tsError: TsError; - message: Message; - }[]; - count: number; - } - > = new Map(); - - for (const error of errors) { - const { path, tsError, message } = error.value; - const filename = path.value; - - if (errorMap.has(filename)) { - const existingError = errorMap.get(filename)!; - existingError.errors.push({ - cursor: error.value.cursor, - message: message, - path: path, - tsError: tsError, - }); - existingError.count++; - } else { - errorMap.set(filename, { - errors: [ - { - cursor: error.value.cursor, - message: message, - path: path, - tsError: tsError, - }, - ], - count: 1, - }); - } - } +export interface EsLintSuggestion { + messageId: string; + fix: EsLintFix; + desc: string; +} - return errorMap; +export interface EsLintFix { + range: number[]; + text: string; } -const errorInMain = collectErrors(strictCheckMain); -const errorInPR = collectErrors(strictCheck); +export interface EsLintUsedDeprecatedRule { + ruleId: string; + replacedBy: any[]; +} function collapsibleMarkdown(detail: string, summary: string) { const output: string[] = [`
${summary}`]; @@ -133,36 +94,97 @@ function collapsibleMarkdown(detail: string, summary: string) { return output.join('\n'); } -function printNewErrors() { - let output: string[] = []; - errorInPR.forEach((value, key) => { - if (!errorInMain.has(key)) { - const lines: string[] = ['\n']; - - value.errors.forEach((error) => { - lines.push( - `- ${key}:${error.cursor.value.line}:${ - error.cursor.value.col - } \`${error.message.value.replace(/\n/g, '')}\`` - ); - }); +const cwd = process.cwd(); + +function checkTsc() { + const strictCheckFileMain = fs.readFileSync( + path.join(cwd, 'strict_main.json') + ); + const strictCheckFilePr = fs.readFileSync(path.join(cwd, 'strict_pr.json')); - lines.push(''); + const strictCheckMain = JSON.parse(strictCheckFileMain.toString()) as Item[]; + const strictCheck = JSON.parse(strictCheckFilePr.toString()) as Item[]; + const totalErrorsMain = strictCheckMain.length; + const totalErrorsPR = strictCheck.length; + + function checkTotal() { + let output: string[] = []; + + if (totalErrorsPR > totalErrorsMain) { + output.push( + `😢 Total errors increased in PR branch: ${ + totalErrorsPR - totalErrorsMain + }` + ); + } else if (totalErrorsPR < totalErrorsMain) { output.push( - collapsibleMarkdown( - lines.join('/n'), - `New errors in PR branch: ${key} - ${value.count} errors` - ) + `You decreased the total number of errors in PR branch by ${ + totalErrorsMain - totalErrorsPR + } 🎉` ); } else { - const mainErrors = errorInMain.get(key)!; - const prErrors = errorInPR.get(key)!; + output.push(`Total errors are the same in both branches`); + } + + return output.join('\n'); + } + + function collectErrors(errors: Item[]) { + const errorMap: Map< + string, + { + errors: { + path: Path; + cursor: Cursor; + tsError: TsError; + message: Message; + }[]; + count: number; + } + > = new Map(); - if (prErrors.count > mainErrors.count) { - const lines: string[] = ['\n']; + for (const error of errors) { + const { path, tsError, message } = error.value; + const filename = path.value; - prErrors.errors.forEach((error) => { + if (errorMap.has(filename)) { + const existingError = errorMap.get(filename)!; + existingError.errors.push({ + cursor: error.value.cursor, + message: message, + path: path, + tsError: tsError, + }); + existingError.count++; + } else { + errorMap.set(filename, { + errors: [ + { + cursor: error.value.cursor, + message: message, + path: path, + tsError: tsError, + }, + ], + count: 1, + }); + } + } + + return errorMap; + } + + const errorInMain = collectErrors(strictCheckMain); + const errorInPR = collectErrors(strictCheck); + + function printNewErrors() { + let output: string[] = []; + errorInPR.forEach((value, key) => { + if (!errorInMain.has(key)) { + const lines: string[] = []; + + value.errors.forEach((error) => { lines.push( `- ${key}:${error.cursor.value.line}:${ error.cursor.value.col @@ -174,22 +196,135 @@ function printNewErrors() { output.push( collapsibleMarkdown( - lines.join('\n'), - `Increased errors in PR branch: ${key} - ${ - prErrors.count - mainErrors.count - } errors` + lines.join('/n'), + `New errors in PR branch: ${key} - ${value.count} errors` ) ); + } else { + const mainErrors = errorInMain.get(key)!; + const prErrors = errorInPR.get(key)!; + + if (prErrors.count > mainErrors.count) { + const lines: string[] = ['\n']; + + prErrors.errors.forEach((error) => { + lines.push( + `- ${key}:${error.cursor.value.line}:${ + error.cursor.value.col + } \`${error.message.value.replace(/\n/g, '')}\`` + ); + }); + + lines.push(''); + + output.push( + collapsibleMarkdown( + lines.join('\n'), + `Increased errors in PR branch: ${key} - ${ + prErrors.count - mainErrors.count + } errors` + ) + ); + } } + }); + + return output.join('\n'); + } + + const output = [ + '### Report of `strictNullChecks (strictPropertyInitialization)` check', + checkTotal(), + printNewErrors(), + ]; + + return output; +} + +function checkEsLint() { + const eslintMainFile = fs.readFileSync(path.join(cwd, 'eslint_main.json')); + const eslintPrFile = fs.readFileSync(path.join(cwd, 'eslint_pr.json')); + + const eslintResultMain = JSON.parse(eslintMainFile.toString()) as EsLint[]; + const eslintResultPr = JSON.parse(eslintPrFile.toString()) as EsLint[]; + + const totalWarningsMain = eslintResultMain.reduce( + (acc, cur) => acc + cur.warningCount, + 0 + ); + + const totalWarningsPR = eslintResultPr.reduce( + (acc, cur) => acc + cur.warningCount, + 0 + ); + + function checkTotal() { + let output: string[] = []; + + if (totalWarningsPR > totalWarningsMain) { + output.push( + `😢 Total ESLint warnings increased in PR branch: ${ + totalWarningsPR - totalWarningsMain + }` + ); + } else if (totalWarningsPR < totalWarningsMain) { + output.push( + `You decreased the total number of ESLint warnings in PR branch by ${ + totalWarningsMain - totalWarningsPR + } 🎉` + ); + } else { + output.push(`Total ESLint warnings are the same in both branches`); } - }); - return output.join('\n'); + return output.join('\n'); + } + + function findNewErrorsOnEsLintPr() { + const output: string[] = []; + eslintResultPr.forEach((result) => { + const esLintMain = eslintResultMain.find( + (mainEslint) => mainEslint.filePath === result.filePath + ); + + if (!esLintMain) { + result.messages.forEach((message) => { + output.push( + `- ${result.filePath}:${message.line}:${message.column} \`${message.message}\`` + ); + }); + } else { + const newErrors = result.messages.filter((message) => { + return !esLintMain.messages.some( + (mainMessage) => + mainMessage.line === message.line && + mainMessage.column === message.column + ); + }); + + if (newErrors.length > 0) { + const lines: string[] = []; + + newErrors.forEach((error) => { + lines.push( + `- ${result.filePath}:${error.line}:${error.column} \`${error.message}\`` + ); + }); + + output.push(lines.join('\n')); + } + } + }); + + return output.join('\n'); + } + + return [ + checkTotal(), + collapsibleMarkdown(findNewErrorsOnEsLintPr(), 'ESLint warnings'), + ].join('\n'); } -const output = [ - '### Report of `strictNullChecks (strictPropertyInitialization)` check', - checkTotal(), - printNewErrors(), -]; +const output = [checkTsc(), checkEsLint()]; + core.setOutput('body', output.join('\n'));