Skip to content
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

Extending ESLint config not working #7510

Closed
conor-cafferkey-sociomantic opened this issue Aug 11, 2019 · 8 comments · Fixed by #7513 · 4 remaining pull requests
Closed

Extending ESLint config not working #7510

conor-cafferkey-sociomantic opened this issue Aug 11, 2019 · 8 comments · Fixed by #7513 · 4 remaining pull requests
Assignees
Milestone

Comments

@conor-cafferkey-sociomantic
Copy link

conor-cafferkey-sociomantic commented Aug 11, 2019

Describe the bug

Extending ESLint config not working.

Environment

  System:
    OS: macOS 10.14.6
    CPU: (4) x64 Intel(R) Core(TM) i7-7660U CPU @ 2.50GHz
  Binaries:
    Node: 8.15.0 - ~/.nvm/versions/node/v8.15.0/bin/node
    Yarn: 1.17.3 - /usr/local/bin/yarn
    npm: 6.4.1 - ~/.nvm/versions/node/v8.15.0/bin/npm
  Browsers:
    Chrome: 76.0.3809.100
    Firefox: 67.0
    Safari: 12.1.2
  npmPackages:
    react: ^16.9.0 => 16.9.0
    react-dom: ^16.9.0 => 16.9.0
    react-scripts: 3.1.0 => 3.1.0
  npmGlobalPackages:
    create-react-app: Not Found

Steps to reproduce

  1. yarn create react-app testapp (or npx create-react-app testapp)
  2. cd testapp
  3. yarn add eslint-config-airbnb (or npm install eslint-config-airbnb)
  4. Add the following to package.json:
"eslintConfig": { "extends": [ "react-app", "airbnb"] } 
  1. EXTEND_ESLINT=true yarn start ( or EXTEND_ESLINT=true npm start)

Expected behavior

  • eslint-config-airbnb should be used
  • app should not compile

Actual behavior

  • eslint-config-airbnb is not used
  • app compiles (it shouldn’t!)

Problem

webpack.config.js checks thateslintConfig.extends exists:


and – if it does – that it includes 'react-app':
eslintConfig.extends.includes('react-app')

It seems that the property extends never exists on eslintConfig(??)

Deleting the above two lines yields the expected behavior (eslint-config-airbnb is picked up and we see lint errors / Failed to compile message)

@HerbCaudill
Copy link

HerbCaudill commented Aug 11, 2019

I was just coming to file this same issue.

The problem is that we're checking the extends property for react-app, but by this time the config object has been expanded so that it actually contains the contents of eslint-config-react-app and the extends property is no longer present.

This can be confirmed by logging eslintConfig as soon as it's been obtained.

With this eslint config in package.json...

"eslintConfig": {
  "extends": [
    "react-app"
  ],
  "rules": {
    "@typescript-eslint/no-unused-vars": "off"
  }
}

...log eslintConfig after line 348:

try {
eslintConfig = eslintCli.getConfigForFile(paths.appIndexJs);
} catch (e) {
// A config couldn't be found.
}

 console.log(eslintConfig) // 🡐 

... then run yarn build. I get something like this:

{
  env: { browser: true, commonjs: true, es6: true, jest: true, node: true },
  globals: {},
  parser: 'C:\\git\\herbcaudill\\screentimebank\\node_modules\\@typescript-eslint\\parser\\dist\\parser.js',
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module',
    ecmaFeatures: { jsx: true },
    warnOnUnsupportedTypeScriptVersion: true
  },
  plugins: [
    'react-hooks',
    'react',// 
    'jsx-a11y',
    'flowtype',
    'import',
    '@typescript-eslint'
  ],
  rules: {
    '@typescript-eslint/no-unused-vars': [ 'off', [Object] ],
    'default-case': [ 'off', [Object] ],
    'no-dupe-class-members': [ 'off' ],
    'no-undef': [ 'off' ],
    '@typescript-eslint/no-angle-bracket-type-assertion': [ 'warn' ],

    // ... 

    'flowtype/require-valid-file-annotation': [ 'warn' ],
    'flowtype/use-flow-type': [ 'warn' ]
  },
  settings: { react: { version: 'detect' } }
}

As you can see, my override of @typescript-eslint/no-unused-vars was successful; but the config object no longer has an extends property, so this check

if (
process.env.EXTEND_ESLINT &&
eslintConfig &&
eslintConfig.extends &&
eslintConfig.extends.includes('react-app')

will fail and we'll fall back on the standard eslint-config-react-app.

@HerbCaudill
Copy link

I'm guessing that prior to version 6, ESLint included the extends property in the config output. This code, which is new in ESLint 6, explicitly omits it.

https://github.com/eslint/eslint/blob/fbec99ea3e39316791685652c66e522d698f52d8/lib/cli-engine/config-array-factory.js#L559-L578

@ianschmitz
Copy link
Contributor

ianschmitz commented Aug 12, 2019

@mrmckeb I'm seeing eslintCli.getConfigForFile(paths.appIndexJs) return undefined when i have a .eslintrc.json file.

@silverwind
Copy link

silverwind commented Aug 12, 2019

I'm not sure if the eslint API exposes a way to actually retrieve which extends a config uses. I did find a way to log out some potentially usable data inside eslint's getConfigForFile, but this functionality looks to not be exposed in the API.

console.log(configArrayFactory.getConfigArrayForFile(absolutePath).map(e => e.name));

Which logs this in my case:

ConfigArray [
  '.eslintrc » eslint-config-react-app',
  '.eslintrc » eslint-config-react-app#overrides[0]',
  '.eslintrc » eslint-config-silverwind',
  '.eslintrc',
  '.eslintrc#overrides[0]',
  '.eslintrc#overrides[1]'
]

Maybe cc: @not-an-aardvark

@mrmckeb
Copy link
Contributor

mrmckeb commented Aug 12, 2019

Hi all, I'm currently on a business trip and will be on a plane for the next few hours.

It seems that this may have been broken by the ESLint 6 upgrade, which came after this config change - unfortunately we didn't have a test for that and we obviously needed one.

Maybe @not-an-aardvark can have a look, otherwise I can probably investigate this in the evening today (it'll be London time). Of course if anyone else can have a look and raise a PR, we'll be very grateful.

@ianschmitz, one option is to remove the requirement to extend our config - but that could introduce risk.

@mrmckeb mrmckeb self-assigned this Aug 12, 2019
@mrmckeb mrmckeb added this to the 3.1.1 milestone Aug 12, 2019
@conor-cafferkey-sociomantic
Copy link
Author

How about checking for the extends in package.json? Would that work?

@n1ru4l
Copy link
Contributor

n1ru4l commented Aug 12, 2019

It would also be nice to print something to the console instead of swallowing the error if the eslintCli.getConfigForFile(paths.appIndexJs); fails for some reason (other than the file not existing).

Temporary patch-package fix:

patches/react-scripts+3.1.0.patch

diff --git a/node_modules/react-scripts/config/webpack.config.js b/node_modules/react-scripts/config/webpack.config.js
index dad50a3..12fad03 100644
--- a/node_modules/react-scripts/config/webpack.config.js
+++ b/node_modules/react-scripts/config/webpack.config.js
@@ -339,22 +339,16 @@ module.exports = function(webpackEnv) {
                 resolvePluginsRelativeTo: __dirname,
                 // @remove-on-eject-begin
                 baseConfig: (() => {
-                  const eslintCli = new eslint.CLIEngine();
-                  let eslintConfig;
-                  try {
-                    eslintConfig = eslintCli.getConfigForFile(paths.appIndexJs);
-                  } catch (e) {
-                    // A config couldn't be found.
-                  }
+                  if (process.env.EXTEND_ESLINT) {
+                    const eslintCli = new eslint.CLIEngine();
+                    let eslintConfig;
+                    try {
+                      eslintConfig = eslintCli.getConfigForFile(paths.appIndexJs);
+                    } catch (e) {
+                      console.error(e);
+                      process.exit(1);
+                    }
 
-                  // We allow overriding the config, only if it extends our config
-                  // (`extends` can be a string or array of strings).
-                  if (
-                    process.env.EXTEND_ESLINT &&
-                    eslintConfig &&
-                    eslintConfig.extends &&
-                    eslintConfig.extends.includes('react-app')
-                  ) {
                     return eslintConfig;
                   } else {
                     return {

@mrmckeb
Copy link
Contributor

mrmckeb commented Aug 14, 2019

Hi all, apologies for the botched release here - this was entirely my fault.

Unfortunately there was a change in ESLint 6 that broke this, as discussed, and I hadn't added a test for this before upgrading us to ESLint 6. Thanks to @ianschmitz and @iansu for getting a fix out while I was travelling.

gottfired added a commit to allaboutapps/aaa-create-react-app-typescript that referenced this issue Aug 14, 2019
@lock lock bot locked and limited conversation to collaborators Aug 19, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.