Vladimir Kirichenko
Vladimir Kirichenko

Reputation: 1

How to prevent git push when there are eslint errors?Husky, lint-staged, eslint

Hi StackOverflow community,

I'm having trouble preventing a git push when there are eslint errors in my code. I'm using eslint with husky and lint-staged to catch linting errors before they are committed to the repository. However, when there are errors and I try to push my changes, they still get pushed.

So currently we have linting configured using lint-staged package which doesn't work and added additional linting call. Could we fix linting in lint-staged instead so developers can notice lint errors on staged files?

Here's my .lintstagedrc file:

{
  "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}": [
    "prettier --write"
  ],
  "src/**/*.{js,jsx,ts,tsx,json}": [
    "npm run lint"
  ]
}

package.json:

`"dependencies": {
    "@auth0/auth0-react": "^1.9.0",
    "@dezeroku/serverless-certificate-creator": "^1.6.0",
    "@emoji-mart/data": "^1.0.2",
    "@floating-ui/react-dom-interactions": "^0.9.2",
    "@sentry/react": "^7.30.0",
    "camelcase-keys": "^7.0.2",
    "classnames": "^2.3.1",
    "dayjs": "^1.11.2",
    "emoji-mart": "^5.2.1",
    "http-proxy-middleware": "^2.0.6",
    "linkify-react": "^3.0.4",
    "linkifyjs": "^3.0.5",
    "msw": "^0.40.0",
    "prop-types": "^15.8.1",
    "react": "^17.0.2",
    "react-datepicker": "^4.8.0",
    "react-dom": "^17.0.2",
    "react-hook-form": "7.43.1",
    "react-query": "^3.34.19",
    "react-router-dom": "6.6.1",
    "react-scripts": "^5.0.1",
    "react-sortablejs": "6.1.4",
    "react-table": "^7.8.0",
    "react-timeago": "^6.2.1",
    "react-toastify": "9.1.2",
    "react-transition-group": "4.4.5",
    "react-truncate": "2.4.0",
    "react-truncate-markup": "5.1.2",
    "recharts": "2.1.14",
    "serverless-finch": "^4.0.0",
    "snakecase-keys": "^5.1.2",
    "sortablejs": "1.15.0",
    "use-react-router-breadcrumbs": "^3.1.0",
    "uuid": "9.0.0",
    "web-vitals": "^2.1.4"
  },
  "devDependencies": {
    "@storybook/addon-actions": "6.5.10",
    "@storybook/addon-essentials": "6.5.10",
    "@storybook/addon-interactions": "6.5.10",
    "@storybook/addon-links": "6.5.10",
    "@storybook/builder-webpack5": "6.5.10",
    "@storybook/manager-webpack5": "6.5.10",
    "@storybook/node-logger": "6.5.10",
    "@storybook/preset-create-react-app": "^4.1.2",
    "@storybook/react": "6.5.10",
    "@storybook/testing-library": "^0.0.13",
    "@testing-library/jest-dom": "^5.16.2",
    "@testing-library/react": "^12.1.4",
    "@testing-library/user-event": "^13.5.0",
    "@trivago/prettier-plugin-sort-imports": "^4.1.1",
    "airbnb-prop-types": "^2.16.0",
    "babel-plugin-named-exports-order": "^0.0.2",
    "chromatic": "^6.7.4",
    "cypress": "^10.1.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-prettier": "^4.0.0",
    "husky": "^7.0.4",
    "lint-staged": "^12.3.8",
    "mockdate": "^3.0.5",
    "prettier": "^2.6.2",
    "webpack": "^5.76.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "eject": "react-scripts eject",
    "test": "TZ=UTC react-scripts test",
    "test:prepush": "npm run test -- --watchAll=false",
    "test:ci": "CI=true npm run test -- --coverage",
    "lint": "eslint src --max-warnings=0",
    "lint-staged": "lint-staged",
    "format": "prettier --write \"./**/*.{js,jsx}\"",
    "eslint": "eslint . --ext .js,.jsx",
    "prepare": "husky install",
    "storybook": "start-storybook -p 6006 -s public",
    "build-storybook": "build-storybook -s public",
    "chromatic": "npx chromatic --project-token=bf77f85e9cc4"
  },

husky/.pre-push

 #!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm run lint-staged && npm run test:prepush

.eslintrc

 {
  "extends": ["react-app", "react-app/jest"],
  "ignorePatterns": ["**/*.spec.jsx", "**/vendor/*.js"],
  "rules": {
    "no-duplicate-imports": "error",
    "react/prop-types": 1
  }
}

Upvotes: 0

Views: 2570

Answers (1)

sw-tracker
sw-tracker

Reputation: 86

Solution

We have setup husky + lint-staged to run all linters on commit: prettier, eslint, stylelint, spotless, etc.

Here is an example:

// lint-staged.config.js
module.exports = {
  '*.{js,html,json,md,xml,yaml,yml}': 'node node_modules/prettier/bin-prettier.js --write',
  '*.ts': ['./eslint-helper.sh', 'node node_modules/prettier/bin-prettier.js --write'],
  '*.{css,scss}': [
    'node frontend/node_modules/stylelint/bin/stylelint.js --ignore-path frontend/.stylelintignore --cache --cache-location frontend/.stylelintcache --fix',
    'node node_modules/prettier/bin-prettier.js --write',
  ],
  '*.{java,kt}': (filePaths) => {
    const filenames = filePaths.map((filePath) => filePath.split('/').pop());
    return `mvn spotless:apply -DspotlessFiles=.*${filenames.join(',.*')}`;
  },
};
  • eslint-helper.sh: we did this due to having a monorepo, maybe you can avoid it
#!/usr/bin/env sh
cd frontend
node node_modules/eslint/bin/eslint.js --config .eslintrc.json --fix "$@"

Extra Info

In regards to your current configuration. The code below is incorrect because you have the same file extension defined in multiple entries, .i.e. js,jsx,ts,tsx,json. They must be unique because each of those commands are being executed in parallel. This means that you will end up with race conditions, lint-staged will execute the commands in parallel and the last one to finish will overwrite what another command did, i.e. prettier could overwrite lint or the other way around.

// incorrect config
{
  "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}": [
    "prettier --write"
  ],
  "src/**/*.{js,jsx,ts,tsx,json}": [
    "npm run lint"
  ]
}

Upvotes: 0

Related Questions