-
Notifications
You must be signed in to change notification settings - Fork 96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automate Linting with Husky and lint-staged to Prevent CI Failures #896
Changes from all commits
fa77324
14a2ae7
2e16d53
6fa1948
a28fc29
c574f04
110b9f6
2493aba
3ab8318
f0b4c6f
1624665
fa5f976
aa95c55
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# common | ||
**/dist/* | ||
|
||
# sdk | ||
packages/sdk/src/api/yorkie/v1/yorkie_grpc_web_pb.d.ts | ||
packages/sdk/src/api/yorkie/v1/yorkie_pb.d.ts | ||
packages/sdk/src/api/yorkie/v1/resources_grpc_web_pb.d.ts | ||
packages/sdk/src/api/yorkie/v1/resources_pb.d.ts | ||
packages/sdk/test/vitest.d.ts | ||
packages/sdk/lib |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
module.exports = { | ||
root: true, | ||
plugins: ['prettier', 'jsdoc', '@typescript-eslint'], | ||
extends: [ | ||
'eslint:recommended', | ||
'plugin:@typescript-eslint/eslint-recommended', | ||
'plugin:@typescript-eslint/recommended', | ||
], | ||
rules: { | ||
'prettier/prettier': 'error', | ||
'object-shorthand': ['error', 'always'], | ||
'no-unreachable': 'error', | ||
}, | ||
overrides: [ | ||
{ | ||
files: ['**/*.ts', '**/*.tsx'], | ||
parser: '@typescript-eslint/parser', | ||
plugins: ['@typescript-eslint'], | ||
extends: ['plugin:@typescript-eslint/recommended'], | ||
rules: { | ||
'@typescript-eslint/no-non-null-assertion': 'off', | ||
'@typescript-eslint/no-explicit-any': 'off', | ||
'@typescript-eslint/ban-ts-comment': 'off', | ||
'jsdoc/require-jsdoc': [ | ||
'error', | ||
{ | ||
contexts: ['MethodDefinition:not([accessibility="private"])'], | ||
require: { | ||
ClassDeclaration: true, | ||
}, | ||
checkConstructors: false, | ||
enableFixer: false, | ||
}, | ||
], | ||
'@typescript-eslint/naming-convention': [ | ||
'error', | ||
{ | ||
selector: 'variable', | ||
format: ['camelCase', 'PascalCase'], | ||
leadingUnderscore: 'allowDouble', | ||
trailingUnderscore: 'allowDouble', | ||
}, | ||
], | ||
'@typescript-eslint/ban-types': [ | ||
'error', | ||
{ | ||
types: { null: 'Use undefined instead of null' }, | ||
}, | ||
], | ||
'@typescript-eslint/array-type': ['error', { default: 'generic' }], | ||
'@typescript-eslint/no-this-alias': [ | ||
'error', | ||
{ | ||
allowDestructuring: true, | ||
allowedNames: ['node'], | ||
}, | ||
], | ||
}, | ||
}, | ||
], | ||
}; | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
npx lint-staged |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,5 +7,6 @@ module.exports = { | |
endOfLine: 'auto', | ||
}, | ||
], | ||
'@next/next/no-html-link-for-pages': 'off', | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
const { ESLint } = require('eslint'); | ||
const { execSync } = require('child_process'); | ||
const path = require('path'); | ||
|
||
const removeIgnoredFiles = async (files) => { | ||
const eslintIgnorePath = path.resolve('.eslintignore'); // Pointing to the root .eslintignore | ||
const eslint = new ESLint({ ignorePath: eslintIgnorePath }); | ||
|
||
const isIgnored = await Promise.all( | ||
files.map(async (file) => { | ||
const ignored = await eslint.isPathIgnored(file); | ||
return ignored; | ||
}), | ||
); | ||
|
||
const filteredFiles = files.filter((_, i) => !isIgnored[i]); | ||
return filteredFiles; | ||
}; | ||
|
||
module.exports = { | ||
'**/*.ts': async (files) => { | ||
const filesToLint = await removeIgnoredFiles(files); | ||
|
||
if (filesToLint.length > 0) { | ||
const fileArgs = filesToLint.join(' '); | ||
const command = `pnpm exec eslint ${fileArgs} --fix --max-warnings=0 --ext .ts`; | ||
try { | ||
execSync(command, { stdio: 'inherit' }); | ||
process.exit(0); | ||
} catch (error) { | ||
console.error('Linting failed. Commit will be aborted.'); | ||
process.exit(1); | ||
} | ||
} else { | ||
console.log('No eligible files to lint. Skipping lint-staged command.'); | ||
process.exit(0); | ||
} | ||
}, | ||
}; | ||
Comment on lines
+20
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Robust linting configuration for TypeScript files. The module export configuration for linting TypeScript files is well-implemented. The use of Suggestion: Consider handling the process exit more gracefully by allowing other middleware in |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review of ESLint Configuration: Generally Solid with Suggestions for Improvement
The ESLint configuration is well-structured and covers a broad range of rules that are essential for maintaining code quality and consistency, especially in a TypeScript project. Here are some observations and suggestions:
@typescript-eslint/no-non-null-assertion
,@typescript-eslint/no-explicit-any
, and@typescript-eslint/ban-ts-comment
). While this may offer flexibility, it could compromise type safety. Consider enabling these rules if the project aims for strict type safety.jsdoc/require-jsdoc
) is commendable as it enforces documentation, which is crucial for maintainability and clarity.prettier
rules as errors is a good practice to ensure consistent code formatting.Overall, the setup is robust, but revisiting the disabled TypeScript rules could further enhance the project's code quality.