From c1966dde3a5e20dcccb836c123a7ff05ddb95a4b Mon Sep 17 00:00:00 2001 From: Martin Hradil Date: Fri, 22 Jul 2016 12:43:21 +0000 Subject: [PATCH 1/7] Linter::ESLint --- lib/linter/eslint.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 lib/linter/eslint.rb diff --git a/lib/linter/eslint.rb b/lib/linter/eslint.rb new file mode 100644 index 00000000..1b2a5159 --- /dev/null +++ b/lib/linter/eslint.rb @@ -0,0 +1,23 @@ +module Linter + class ESLint < Base + private + + def config_files + [".eslintrc.js", ".eslintrc.json"] + end + + def linter_executable + 'eslint .' + end + + def options + {:format => 'json'} + end + + def filtered_files(files) + files.select do |file| + file.end_with? '.js' + end + end + end +end From 53e39bfa4ee6fdf7731c7b7e49854089696cd80a Mon Sep 17 00:00:00 2001 From: Martin Hradil Date: Fri, 22 Jul 2016 13:01:06 +0000 Subject: [PATCH 2/7] Linter::SCSS --- lib/linter/scss.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 lib/linter/scss.rb diff --git a/lib/linter/scss.rb b/lib/linter/scss.rb new file mode 100644 index 00000000..d3a2258a --- /dev/null +++ b/lib/linter/scss.rb @@ -0,0 +1,21 @@ +module Linter + class SCSS < Base + private + + def config_files + [".scss-lint.yml"] + end + + def linter_executable + 'scss-lint' + end + + def options + {:format => 'JSON'} + end + + def filtered_files(files) + files.select { |file| file.end_with?(".scss") } + end + end +end From 37e690f983469530d80274a2771a469fbaf661d3 Mon Sep 17 00:00:00 2001 From: Martin Hradil Date: Fri, 22 Jul 2016 12:36:35 +0000 Subject: [PATCH 3/7] Enable the new linters (eslint, scss) --- .../commit_monitor_handlers/commit_range/rubocop_checker.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/workers/commit_monitor_handlers/commit_range/rubocop_checker.rb b/app/workers/commit_monitor_handlers/commit_range/rubocop_checker.rb index 032e76ef..ff9aa5ca 100644 --- a/app/workers/commit_monitor_handlers/commit_range/rubocop_checker.rb +++ b/app/workers/commit_monitor_handlers/commit_range/rubocop_checker.rb @@ -24,7 +24,10 @@ def process_branch unmerged_results = [] unmerged_results << Linter::Rubocop.new(branch).run unmerged_results << Linter::Haml.new(branch).run + unmerged_results << Linter::ESLint.new(branch).run + unmerged_results << Linter::SCSS.new(branch).run unmerged_results.compact! + if unmerged_results.empty? @results = {"files" => []} else From f16e12509338e2fa95d47997eaaeb23a1fb1a86a Mon Sep 17 00:00:00 2001 From: Martin Hradil Date: Fri, 22 Jul 2016 13:18:19 +0000 Subject: [PATCH 4/7] Add scss_lint gem, eslint as a npm package --- Gemfile | 9 +++++---- package.json | 6 ++++++ 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 package.json diff --git a/Gemfile b/Gemfile index b0c31f9a..d35d3bed 100644 --- a/Gemfile +++ b/Gemfile @@ -40,10 +40,11 @@ gem 'travis', '~>1.7.6' gem 'awesome_spawn', '>= 1.4.1' gem 'default_value_for' -gem 'haml_lint', '= 0.16.1', :require => false -gem 'more_core_extensions', '~> 2.0.0', :require => 'more_core_extensions/all' -gem 'rubocop', '= 0.37.2', :require => false -gem 'rugged', :require => false +gem 'haml_lint', '= 0.16.1', :require => false +gem 'more_core_extensions', '~> 2.0.0', :require => 'more_core_extensions/all' +gem 'rubocop', '= 0.37.2', :require => false +gem 'rugged', :require => false +gem 'scss_lint', '~> 0.49.0', :require => false gem 'octokit', '~> 3.8.0' gem 'minigit', '~> 0.0.4' diff --git a/package.json b/package.json new file mode 100644 index 00000000..9fc0c713 --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "eslint": "^3.13.1", + "eslint-cli": "^1.1.0" + } +} From b231b129775dcc94fa2e655bdeecdfd604fabadc Mon Sep 17 00:00:00 2001 From: Martin Hradil Date: Fri, 22 Jul 2016 13:19:04 +0000 Subject: [PATCH 5/7] gitignore node_modules --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 67a51760..98c45f77 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,5 @@ /repos /Gemfile.lock + +/node_modules From 742517f37f5deba171e600748718a0070e2f7723 Mon Sep 17 00:00:00 2001 From: Martin Hradil Date: Fri, 22 Jul 2016 12:37:56 +0000 Subject: [PATCH 6/7] Linter::Base - separate output parsing into parse_output and convert_parsed ..so that these can be overriden in linters that have special parsing/running needs the default `parse_output` is the original JSON.parse + exceptions and could be overriden for linters that don't output JSON the default `convert_parsed` is an identity function, but is needed by eslint & scss to convert between the different JSON formats --- lib/linter/base.rb | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/linter/base.rb b/lib/linter/base.rb index 4c1eff7f..b0f358b5 100644 --- a/lib/linter/base.rb +++ b/lib/linter/base.rb @@ -27,13 +27,7 @@ def run end end - begin - offenses = JSON.parse(result.output.chomp) - rescue JSON::ParserError => error - logger.error("#{log_header} #{error.message}") - logger.error("#{log_header} Failed to parse JSON result #{result.output.inspect}") - return failed_linter_offenses("error parsing JSON result") - end + offenses = parse_output(result.output) logger.info("#{log_header} Completed run with offenses #{offenses.inspect}") offenses end @@ -69,6 +63,21 @@ def files_to_lint @files_to_lint ||= filtered_files(diff_service.new_files) end + def parse_output(str) + begin + convert_parsed(JSON.parse(str.chomp)) + rescue JSON::ParserError => error + logger.error("#{log_header} #{error.message}") + logger.error("#{log_header} Failed to parse JSON result #{result.output.inspect}") + return failed_linter_offenses("error parsing JSON result") + end + end + + # overriden in linters with different JSON format + def convert_parsed(hash_or_array) + hash_or_array + end + def run_linter(dir) logger.info("#{log_header} Executing linter...") require 'awesome_spawn' From 156d75696f87554809da6d49aad24493230a7712 Mon Sep 17 00:00:00 2001 From: Martin Hradil Date: Wed, 11 Jan 2017 19:32:29 +0000 Subject: [PATCH 7/7] Linter::ESLint & Linter::SCSS - add convert_parsed converting from each format to the one used by rubocop eslint output: ``` [ { filePath: "foo/bar", messages: [ { ruleId: "baz", severity: 1, message: "quux", line: 4, column: 5, }, ], }, ] ``` scss output: ``` { "foo/bar": [ { line: 4, column: 5, severity: "warning", reason: "quux", linter: "baz", }, ], } ``` converted output: ``` { files: [ { path: "foo/bar", offenses: [ { severity: "warning", message: "quux", location: { line: 4, column: 5, }, cop_name: "baz", }, ], }, ], summary: { target_file_count: 1, offense_count: 1, }, } ``` --- lib/linter/eslint.rb | 22 ++++++++++++++++++++++ lib/linter/scss.rb | 22 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/lib/linter/eslint.rb b/lib/linter/eslint.rb index 1b2a5159..5f6ee183 100644 --- a/lib/linter/eslint.rb +++ b/lib/linter/eslint.rb @@ -19,5 +19,27 @@ def filtered_files(files) file.end_with? '.js' end end + + def convert_parsed(array) + files = array.map { |f| convert_file(f) } + + {:files => files, + :summary => {:offense_count => files.reduce(0) { |memo, f| memo + f.offenses.count }, + :target_file_count => files.count}} + end + + def convert_file(file) + {:path => file[:filePath], + :offenses => file[:messages].map { |m| convert_offense(m) }} + end + + SEVERITY = ['off', 'warning', 'error'] + def convert_offense(offense) + {:severity => SEVERITY[offense[:severity]], + :message => offense[:message], + :location => {:line => offense[:line], + :column => offense[:column]}, + :cop_name => offense[:ruleId]} + end end end diff --git a/lib/linter/scss.rb b/lib/linter/scss.rb index d3a2258a..5afcda52 100644 --- a/lib/linter/scss.rb +++ b/lib/linter/scss.rb @@ -17,5 +17,27 @@ def options def filtered_files(files) files.select { |file| file.end_with?(".scss") } end + + def convert_parsed(hash) + files = hash.map { |path, offenses| convert_file(path, offenses) } + + {:files => files, + :summary => {:offense_count => files.reduce(0) { |memo, f| memo + f.offenses.count }, + :target_file_count => files.count}} + end + + def convert_file(path, offenses) + {:path => path, + :offenses => offenses.map { |o| convert_offense(o) }} + end + + def convert_offense(offense) + {:severity => offense[:severity], + :message => offense[:reason], + :location => {:line => offense[:line], + :column => offense[:column]}, + :cop_name => offense[:linter]} + end + end end end