Skip to content

Commit

Permalink
Automate Linting with Husky and lint-staged to Prevent CI Failures (
Browse files Browse the repository at this point in the history
#893)

This commit addresses the issue where linting was not being automatically
executed before commits, despite Husky being installed. The previous
setup had Husky installed at v8, but proper pre-commit hooks were not
in place to ensure that linting occurred consistently. Since Husky v5,
the configuration and usage have changed. For more details, refer to
the documentation of Husky.

Key changes include:

- Adding the missing pre-commit configuration in the .husky folder,
  and ensure Husky works as expected to automate linting at the
  pre-commit stage.
- Integrating lint-staged to only lint the files that are staged for
  commit, improving efficiency.

With these updates, developers will no longer need to manually run
lint checks, as the process will be automated and enforced during the
commit phase.
  • Loading branch information
gwbaik9717 authored Sep 5, 2024
1 parent 2b2ee0b commit 4bd2a90
Show file tree
Hide file tree
Showing 23 changed files with 655 additions and 304 deletions.
8 changes: 8 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# 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/dist
packages/sdk/lib
61 changes: 61 additions & 0 deletions .eslintrc.js
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'],
},
],
},
},
],
};
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
if: steps.cache.outputs.cache-hit != 'true'
run: pnpm install

- run: pnpm sdk lint
- run: pnpm lint
- run: pnpm sdk build
- run: pnpm build:examples
- run: docker compose -f docker/docker-compose-ci.yml up --build -d
Expand Down
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx lint-staged
3 changes: 2 additions & 1 deletion examples/nextjs-scheduler/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
module.exports = {
extends: ['next', 'plugin:prettier/recommended'],
extends: ['next', 'plugin:prettier/recommended', '../../.eslintrc.js'],
rules: {
'prettier/prettier': [
'error',
{
endOfLine: 'auto',
},
],
'@next/next/no-html-link-for-pages': 'off',
},
};
4 changes: 1 addition & 3 deletions examples/nextjs-scheduler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
"@types/react-dom": "18.2.0",
"eslint-config-next": "^14.2.5",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.0.0",
"prettier": "^3.3.3",
"typescript": "5.3.3"
"prettier": "^3.3.3"
}
}
1 change: 0 additions & 1 deletion examples/react-tldraw/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"@vitejs/plugin-react": "^4.2.1",
"typescript": "^5.3.3",
"vite": "^5.0.12",
"vite-tsconfig-paths": "^4.3.1"
}
Expand Down
1 change: 0 additions & 1 deletion examples/react-todomvc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"@vitejs/plugin-react": "^4.2.1",
"typescript": "^5.3.3",
"vite": "^5.0.12",
"vite-tsconfig-paths": "^4.3.1"
}
Expand Down
1 change: 0 additions & 1 deletion examples/vanilla-codemirror6/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"preview": "vite preview"
},
"devDependencies": {
"typescript": "^5.3.3",
"vite": "^5.0.12"
},
"dependencies": {
Expand Down
1 change: 0 additions & 1 deletion examples/vanilla-quill/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
"devDependencies": {
"@types/color-hash": "^1.0.2",
"@types/quill": "^1.3.10",
"typescript": "^5.3.3",
"vite": "^5.0.12"
},
"dependencies": {
Expand Down
39 changes: 39 additions & 0 deletions lint-staged.config.js
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.log('Linting failed. Commit will be aborted.');
process.exit(1);
}
} else {
console.log('No eligible files to lint. Skipping lint-staged command.');
process.exit(0);
}
},
};
14 changes: 12 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"vanilla-codemirror6": "pnpm --filter=vanilla-codemirror6",
"vanilla-quill": "pnpm --filter=vanilla-quill",
"vuejs-kanban": "pnpm --filter=vuejs-kanban",
"build:examples": "pnpm --filter './examples/*' run build"
"build:examples": "pnpm --filter './examples/*' run build",
"lint": "eslint . --fix --max-warnings=0 --ext .ts",
"prepare": "husky"
},
"keywords": [],
"author": {
Expand All @@ -25,6 +27,14 @@
},
"license": "Apache-2.0",
"devDependencies": {
"only-allow": "^1.2.1"
"eslint": "^8.19.0",
"husky": "^9.1.5",
"lint-staged": "^15.2.9",
"only-allow": "^1.2.1",
"eslint-plugin-jsdoc": "^39.3.3",
"eslint-plugin-prettier": "^5.0.0",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"typescript": "5.3.3"
}
}
3 changes: 1 addition & 2 deletions packages/devtools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
"@types/node": "20.9.0",
"@types/react": "18.2.0",
"@types/react-dom": "18.2.0",
"prettier": "3.0.3",
"typescript": "5.3.3"
"prettier": "3.0.3"
},
"manifest": {
"permissions": [
Expand Down
7 changes: 0 additions & 7 deletions packages/sdk/.eslintignore

This file was deleted.

50 changes: 2 additions & 48 deletions packages/sdk/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,55 +1,9 @@
// eslint-disable-next-line no-undef
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'prettier', 'eslint-plugin-tsdoc', 'jsdoc'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
],
extends: ['../../.eslintrc.js'],
plugins: ['eslint-plugin-tsdoc'],
rules: {
'prettier/prettier': 'error',
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'variable',
format: ['camelCase', 'PascalCase'],
leadingUnderscore: 'allowDouble',
trailingUnderscore: 'allowDouble',
},
],
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/ban-types': [
'error',
{
types: { null: 'Use undefined instead of null' },
},
],
'@typescript-eslint/array-type': ['error', { default: 'generic' }],
'tsdoc/syntax': 'error',
'object-shorthand': ['error', 'always'],
'no-unreachable': 'error',
'jsdoc/require-jsdoc': [
'error',
{
contexts: ['MethodDefinition:not([accessibility="private"])'],
require: {
ClassDeclaration: true,
},
checkConstructors: false,
enableFixer: false,
},
],
'@typescript-eslint/no-this-alias': [
'error',
{
allowDestructuring: true,
allowedNames: ['node'],
},
],
},
overrides: [
{
Expand Down
14 changes: 2 additions & 12 deletions packages/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"test:bench": "vitest bench",
"test:ci": "vitest run --coverage",
"test:yorkie.dev": "TEST_RPC_ADDR=https://api.yorkie.dev vitest run --coverage",
"lint": "eslint . --fix --max-warnings=0 --ext .ts",
"prepare": "pnpm build"
},
"engines": {
Expand All @@ -49,19 +48,12 @@
"@connectrpc/protoc-gen-connect-es": "^1.4.0",
"@types/google-protobuf": "^3.15.5",
"@types/long": "^4.0.1",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@vitest/coverage-istanbul": "^0.34.5",
"@vitest/coverage-v8": "^0.34.5",
"eslint": "^8.19.0",
"eslint-plugin-jsdoc": "^39.3.3",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-tsdoc": "^0.2.16",
"husky": "^8.0.3",
"prettier": "^2.7.1",
"ts-node": "^10.9.1",
"typedoc": "^0.25.13",
"typescript": "^5.3.3",
"typescript-transform-paths": "^3.3.1",
"vite": "^5.0.12",
"vite-plugin-commonjs": "^0.10.1",
Expand All @@ -75,9 +67,7 @@
"@connectrpc/connect-web": "^1.4.0",
"long": "^5.2.0"
},
"husky": {
"hooks": {
"pre-commit": "pnpm lint"
}
"resolutions": {
"typedoc/typescript": "5.3.3"
}
}
4 changes: 2 additions & 2 deletions packages/sdk/src/document/crdt/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1371,8 +1371,8 @@ export class CRDTTree extends CRDTElement implements GCParent {
const treePos = node.isText
? { node, offset: 0 }
: parentNode && leftChildNode
? this.toTreePos(parentNode, leftChildNode)
: null;
? this.toTreePos(parentNode, leftChildNode)
: null;

if (treePos) {
index = this.indexTree.indexOf(treePos);
Expand Down
Loading

0 comments on commit 4bd2a90

Please sign in to comment.