diff --git a/.eslintignore b/.eslintignore index 2482278de75cc..94357790433f7 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,5 +1,9 @@ +/optimize +/src/fixtures/vislib/mock_data +/src/ui/public/angular-bootstrap +/test/fixtures/scenarios +/src/core_plugins/console/public/webpackShims +/src/core_plugins/console/public/tests/webpackShims /src/core_plugins/timelion/bower_components /src/core_plugins/timelion/vendor_components -test/fixtures/scenarios -optimize -test/fixtures/scenarios +/src/ui/public/utils/decode_geo_hash.js diff --git a/.eslintrc b/.eslintrc index 7a623df06a6ca..1904222b3cfa9 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,2 +1,8 @@ --- extends: '@elastic/kibana' +rules: + no-unused-vars: off + no-var: off + prefer-const: off + no-extra-semi: off + quotes: off diff --git a/Gruntfile.js b/Gruntfile.js index 6c025cd1b94a0..bd843b0eff635 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -38,18 +38,6 @@ module.exports = function (grunt) { ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= package.author.company %>;' + ' Licensed <%= package.license %> */\n' }, - - lintThese: [ - 'Gruntfile.js', - '<%= root %>/tasks/**/*.js', - '<%= root %>/test/**/*.js', - '<%= src %>/**/*.js', - '!<%= src %>/ui/public/angular-bootstrap/**/*.js', - '!<%= src %>/core_plugins/timelion/bower_components/**/*.js', - '!<%= src %>/core_plugins/timelion/vendor_components/**/*.js', - '!<%= src %>/fixtures/**/*.js', - '!<%= root %>/test/fixtures/scenarios/**/*.js' - ] }; grunt.config.merge(config); diff --git a/package.json b/package.json index 01ac395810b7d..bcfb871d0edf2 100644 --- a/package.json +++ b/package.json @@ -165,17 +165,17 @@ "wreck": "6.2.0" }, "devDependencies": { - "@elastic/eslint-config-kibana": "0.0.3", + "@elastic/eslint-config-kibana": "0.2.1", "angular-mocks": "1.4.7", "auto-release-sinon": "1.0.3", - "babel-eslint": "4.1.8", + "babel-eslint": "6.1.2", "chai": "3.5.0", "cheerio": "0.22.0", "chokidar": "1.6.0", "chromedriver": "2.24.1", "elasticdump": "2.1.1", - "eslint": "1.10.3", - "eslint-plugin-mocha": "1.1.0", + "eslint": "3.11.1", + "eslint-plugin-mocha": "4.7.0", "event-stream": "3.3.2", "expect.js": "0.3.1", "faker": "1.1.0", @@ -189,7 +189,6 @@ "grunt-karma": "2.0.0", "grunt-run": "0.6.0", "grunt-simple-mocha": "0.4.0", - "gruntify-eslint": "1.0.1", "gulp-sourcemaps": "1.7.3", "handlebars": "4.0.5", "husky": "0.8.1", diff --git a/src/cli/cluster/__tests__/_mock_cluster_fork.js b/src/cli/cluster/__tests__/_mock_cluster_fork.js index 2671ca08bdb9a..0915d172a4cd6 100644 --- a/src/cli/cluster/__tests__/_mock_cluster_fork.js +++ b/src/cli/cluster/__tests__/_mock_cluster_fork.js @@ -24,7 +24,7 @@ export default class MockClusterFork extends EventEmitter { dead = true; this.emit('exit'); cluster.emit('exit', this, this.exitCode || 0); - }()); + })(); }), }, isDead: sinon.spy(() => dead), @@ -39,6 +39,6 @@ export default class MockClusterFork extends EventEmitter { await wait(); dead = false; this.emit('online'); - }()); + })(); } } diff --git a/src/cli/cluster/cluster_manager.js b/src/cli/cluster/cluster_manager.js index 80b183cd663a6..1282d17442b02 100644 --- a/src/cli/cluster/cluster_manager.js +++ b/src/cli/cluster/cluster_manager.js @@ -86,19 +86,16 @@ module.exports = class ClusterManager { const chokidar = require('chokidar'); const fromRoot = require('../../utils/from_root'); - const watchPaths = uniq( - [ - fromRoot('src/core_plugins'), - fromRoot('src/server'), - fromRoot('src/ui'), - fromRoot('src/utils'), - fromRoot('config'), - ...extraPaths - ] - .map(path => resolve(path)) - ); - - this.watcher = chokidar.watch(watchPaths, { + const watchPaths = [ + fromRoot('src/core_plugins'), + fromRoot('src/server'), + fromRoot('src/ui'), + fromRoot('src/utils'), + fromRoot('config'), + ...extraPaths + ].map(path => resolve(path)); + + this.watcher = chokidar.watch(uniq(watchPaths), { cwd: fromRoot('.'), ignored: /[\\\/](\..*|node_modules|bower_components|public|__tests__)[\\\/]/ }); diff --git a/src/core_plugins/console/.eslintrc b/src/core_plugins/console/.eslintrc index c5fcfc4ff6fda..f539f6cd5878f 100644 --- a/src/core_plugins/console/.eslintrc +++ b/src/core_plugins/console/.eslintrc @@ -1,34 +1,36 @@ --- root: true -extends: '@elastic/kibana' +extends: '../../../.eslintrc' rules: - block-scoped-var: [0] - camelcase: [0] - curly: [0] - dot-location: [0] - dot-notation: [0] - eqeqeq: [0] - guard-for-in: [0] - indent: [0] - max-len: [0] - new-cap: [0] - no-caller: [0] - no-empty: [0] - no-extend-native: [0] - no-loop-func: [0] - no-multi-str: [0] - no-nested-ternary: [0] - no-proto: [0] - no-sequences: [0] - no-undef: [0] - no-use-before-define: [0] - one-var: [0] - quotes: [0] - space-before-blocks: [0] - space-in-parens: [0] - space-infix-ops: [0] - semi: [0] - strict: [0] - wrap-iife: [0] + block-scoped-var: off + camelcase: off + curly: off + dot-location: off + dot-notation: off + eqeqeq: off + guard-for-in: off + indent: off + max-len: off + new-cap: off + no-caller: off + no-empty: off + no-extend-native: off + no-loop-func: off + no-multi-str: off + no-nested-ternary: off + no-proto: off + no-sequences: off + no-undef: off + no-use-before-define: off + one-var: off + quotes: off + space-before-blocks: off + space-in-parens: off + space-infix-ops: off + semi: off + strict: off + wrap-iife: off + no-var: off + prefer-const: off diff --git a/src/core_plugins/timelion/.eslintrc b/src/core_plugins/timelion/.eslintrc deleted file mode 100644 index 78ad50cf6a489..0000000000000 --- a/src/core_plugins/timelion/.eslintrc +++ /dev/null @@ -1,68 +0,0 @@ ---- -parser: babel-eslint - -env: - es6: true - amd: true - node: true - browser: true - jasmine: true - -rules: - block-scoped-var: 2 - camelcase: [ 2, { properties: never } ] - comma-dangle: 0 - comma-style: [ 2, last ] - consistent-return: 0 - curly: [ 2, multi-line ] - dot-location: [ 2, property ] - dot-notation: [ 2, { allowKeywords: true } ] - eqeqeq: [ 2, allow-null ] - guard-for-in: 2 - indent: [ 2, 2, { SwitchCase: 1 } ] - key-spacing: [ 0, { align: value } ] - max-len: [ 2, 140, 2, { ignoreComments: true, ignoreUrls: true } ] - new-cap: [ 2, { capIsNewExceptions: [ Private ] } ] - no-bitwise: 0 - no-caller: 2 - no-cond-assign: 0 - no-debugger: 2 - no-empty: 2 - no-eval: 2 - no-extend-native: 2 - no-extra-parens: 0 - no-irregular-whitespace: 2 - no-iterator: 2 - no-loop-func: 2 - no-multi-spaces: 0 - no-multi-str: 2 - no-nested-ternary: 2 - no-new: 0 - no-path-concat: 0 - no-proto: 2 - no-return-assign: 0 - no-script-url: 2 - no-sequences: 2 - no-shadow: 0 - no-trailing-spaces: 2 - no-undef: 2 - no-underscore-dangle: 0 - no-unused-expressions: 0 - no-unused-vars: 0 - no-use-before-define: [ 2, nofunc ] - no-with: 2 - one-var: [ 2, never ] - quotes: [ 2, single ] - semi-spacing: [ 2, { before: false, after: true } ] - semi: [ 2, always ] - space-after-keywords: [ 2, always ] - space-before-blocks: [ 2, always ] - space-before-function-paren: [ 2, { anonymous: always, named: never } ] - space-in-parens: [ 2, never ] - space-infix-ops: [ 2, { int32Hint: false } ] - space-return-throw-case: [ 2 ] - space-unary-ops: [ 2 ] - strict: [ 2, never ] - valid-typeof: 2 - wrap-iife: [ 2, outside ] - yoda: 0 diff --git a/src/fixtures/mock_ui_state.js b/src/fixtures/mock_ui_state.js index 50d913ae337e8..5f5b90e38eb3d 100644 --- a/src/fixtures/mock_ui_state.js +++ b/src/fixtures/mock_ui_state.js @@ -10,4 +10,4 @@ export default { }, on: _.noop, off: _.noop -} +}; diff --git a/src/ui/ui_bundle_collection.js b/src/ui/ui_bundle_collection.js index 76cd173678d97..463f217a9c46e 100644 --- a/src/ui/ui_bundle_collection.js +++ b/src/ui/ui_bundle_collection.js @@ -1,8 +1,3 @@ -const rimraf = promisify(require('rimraf')); -const mkdirp = promisify(require('mkdirp')); -const unlink = promisify(require('fs').unlink); -const readdir = promisify(require('fs').readdir); - import UiBundle from './ui_bundle'; import appEntryTemplate from './app_entry_template'; import { readFileSync as readSync } from 'fs'; @@ -10,6 +5,11 @@ import { pull, transform, pluck } from 'lodash'; import { promisify } from 'bluebird'; import { makeRe } from 'minimatch'; +const rimraf = promisify(require('rimraf')); +const mkdirp = promisify(require('mkdirp')); +const unlink = promisify(require('fs').unlink); +const readdir = promisify(require('fs').readdir); + class UiBundleCollection { constructor(bundlerEnv, filter) { this.each = []; diff --git a/tasks/config/eslint.js b/tasks/config/eslint.js index dbc1cea416969..ba5fb91a02080 100644 --- a/tasks/config/eslint.js +++ b/tasks/config/eslint.js @@ -1,30 +1,33 @@ -var resolve = require('path').resolve; +import { resolve } from 'path'; +export default grunt => ({ + options: { + paths: [ + 'Gruntfile.js', + 'bin', + 'config', + 'src', + 'tasks', + 'test', + 'utilities', + ], + }, -module.exports = function (grunt) { - return { - // just lint the source dir - source: { - options: { - cache: resolve(grunt.config.get('root'), '.eslint.fixSource.cache') - }, + source: { + options: { + cache: resolve(grunt.config.get('root'), '.eslint.fixSource.cache') + } + }, - files: { - src: '<%= lintThese %>' - } - }, + fixSource: { + options: { + cache: resolve(grunt.config.get('root'), '.eslint.fixSource.cache'), + fix: true + } + }, - // lint the source and fix any fixable errors - fixSource: { - options: { - cache: resolve(grunt.config.get('root'), '.eslint.fixSource.cache'), - fix: true - }, - - files: { - src: '<%= lintThese %>' - } - }, - - staged: {} - }; -}; + staged: { + options: { + paths: null // overridden by lintStagedFiles task + } + } +}); diff --git a/tasks/eslint.js b/tasks/eslint.js new file mode 100644 index 0000000000000..4ee55056c2c6d --- /dev/null +++ b/tasks/eslint.js @@ -0,0 +1,44 @@ +import { CLIEngine } from 'eslint'; + +const OPTION_DEFAULTS = { + paths: null, + cache: null, + fix: false +}; + +export default grunt => { + grunt.registerMultiTask('eslint', function () { + const options = this.options(OPTION_DEFAULTS); + + if (!options.paths) { + grunt.fatal(new Error('No eslint.options.paths specified')); + return; + } + + const cli = new CLIEngine({ + cache: options.cache, + fix: options.fix, + cwd: grunt.config.get('root'), + }); + + // report includes an entire list of files checked and the + // fixes, errors, and warning for each. + const report = cli.executeOnFiles(options.paths); + + // output fixes to disk + if (options.fix) { + CLIEngine.outputFixes(report); + } + + // log the formatted linting report + const formatter = cli.getFormatter(); + + const errTypes = []; + if (report.errorCount > 0) errTypes.push('errors'); + if (report.warningCount > 0) errTypes.push('warning'); + if (!errTypes.length) return; + + grunt.log.write(formatter(report.results)); + grunt.fatal(`eslint ${errTypes.join(' & ')}`); + }); +}; diff --git a/tasks/lint_staged_files.js b/tasks/lint_staged_files.js index e7c2f95752d13..d8117b62c2772 100644 --- a/tasks/lint_staged_files.js +++ b/tasks/lint_staged_files.js @@ -1,5 +1,7 @@ import { resolve } from 'path'; import { isStaged, getFilename } from './utils/files_to_commit'; +import { CLIEngine } from 'eslint'; +import minimatch from 'minimatch'; const root = resolve(__dirname, '..'); @@ -7,18 +9,32 @@ export default function (grunt) { grunt.registerTask('lintStagedFiles', function () { grunt.task.requires('collectFilesToCommit'); - // match these patterns - var patterns = grunt.config.get('eslint.source.files.src'); - if (!patterns) grunt.fail.warn('eslint file pattern is not defined'); + // convert eslint paths to globs + const cli = new CLIEngine(); + const eslintSourcePaths = grunt.config.get('eslint.options.paths'); + if (!eslintSourcePaths) grunt.fail.warn('eslint.options.paths is not defined'); + + const sourcePathRegexps = cli.resolveFileGlobPatterns(eslintSourcePaths) + .map(glob => minimatch.makeRe(glob)); const files = grunt.config .get('filesToCommit') .filter(isStaged) .map(getFilename) .map(file => resolve(root, file)) - .filter(file => grunt.file.isMatch(patterns, file)); + .filter(file => { + if (!sourcePathRegexps.some(re => file.match(re))) { + return false; + } + + if (cli.isPathIgnored(file)) { + return false; + } + + return true; + }); - grunt.config.set('eslint.staged.files.src', files); + grunt.config.set('eslint.staged.options.paths', files); grunt.task.run(['eslint:staged']); }); } diff --git a/test/functional/apps/visualize/_data_table.js b/test/functional/apps/visualize/_data_table.js index 1ec25f0006b2f..70f0eaa83f127 100644 --- a/test/functional/apps/visualize/_data_table.js +++ b/test/functional/apps/visualize/_data_table.js @@ -73,8 +73,9 @@ bdd.describe('visualize app', function describeIndexTests() { bdd.it('should show correct data, take screenshot', function () { var chartHeight = 0; - var expectedChartData = [ '0 2,088', '2,000 2,748', '4,000 2,707', '6,000 2,876', - '8,000 2,863', '10,000 147', '12,000 148', '14,000 129', '16,000 161', '18,000 137' + var expectedChartData = [ + '0 2,088', '2,000 2,748', '4,000 2,707', '6,000 2,876', + '8,000 2,863', '10,000 147', '12,000 148', '14,000 129', '16,000 161', '18,000 137' ]; return PageObjects.common.try(function () {