Skip to content

Commit e17a7ff

Browse files
committed
Switch ScssLint pre-commit hook to use JSON formatter
There is a pull request on the scss-lint project to change the default formatter to include more information and progress: sds/scss-lint#695 Unfortunately, changing the default formatter output breaks this hook. Fix this by switching the hook to use the JSON formatter.
1 parent 9c62b0c commit e17a7ff

File tree

4 files changed

+67
-16
lines changed

4 files changed

+67
-16
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
* Fix `Minitest` pre-push hook to include all test files
1212
* Add `MessageFormat` commit-msg hook to validate commit messages against
1313
a regex pattern
14+
* Switch `ScssLint` pre-commit hook to use the JSON output formatter instead
15+
of the default formatter
1416

1517
## 0.32.0.rc1
1618

config/default.yml

+2
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,9 @@ PreCommit:
482482
ScssLint:
483483
enabled: false
484484
description: 'Analyzing with scss-lint'
485+
required_library: 'json'
485486
required_executable: 'scss-lint'
487+
flags: ['--format', 'JSON']
486488
install_command: 'gem install scss-lint'
487489
include: '**/*.scss'
488490

lib/overcommit/hook/pre_commit/scss_lint.rb

+23-10
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@ module Overcommit::Hook::PreCommit
33
#
44
# @see https://github.com/brigade/scss-lint
55
class ScssLint < Base
6-
MESSAGE_TYPE_CATEGORIZER = lambda do |type|
7-
type.include?('W') ? :warning : :error
8-
end
9-
106
def run
117
result = execute(command, args: applicable_files)
128

@@ -16,13 +12,30 @@ def run
1612
return :pass if [0, 81].include?(result.status)
1713

1814
# Any status that isn't indicating lint warnings or errors indicates failure
19-
return :fail, result.stdout unless [1, 2].include?(result.status)
15+
return :fail, (result.stdout + result.stderr) unless [1, 2].include?(result.status)
16+
17+
begin
18+
collect_lint_messages(JSON.parse(result.stdout))
19+
rescue JSON::ParserError => ex
20+
return :fail, "Unable to parse JSON returned by SCSS-Lint: #{ex.message}\n" \
21+
"STDOUT: #{result.stdout}\nSTDERR: #{result.stderr}"
22+
end
23+
end
24+
25+
private
26+
27+
def collect_lint_messages(files_to_lints)
28+
files_to_lints.flat_map do |path, lints|
29+
lints.map do |lint|
30+
severity = lint['severity'] == 'warning' ? :warning : :error
31+
32+
message = lint['reason']
33+
message = "#{lint['linter']}: #{message}" if lint['linter']
34+
message = "#{path}:#{lint['line']} #{message}"
2035

21-
extract_messages(
22-
result.stdout.split("\n"),
23-
/^(?<file>(?:\w:)?[^:]+):(?<line>\d+)[^ ]* (?<type>[^ ]+)/,
24-
MESSAGE_TYPE_CATEGORIZER,
25-
)
36+
Overcommit::Hook::Message.new(severity, path, lint['line'], message)
37+
end
38+
end
2639
end
2740
end
2841
end

spec/overcommit/hook/pre_commit/scss_lint_spec.rb

+40-6
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,21 @@
3030
context 'and it reports a warning' do
3131
before do
3232
result.stub(:status).and_return(1)
33-
result.stub(:stdout).and_return([
34-
'file1.scss:1 [W] Prefer single quoted strings',
35-
].join("\n"))
33+
result.stub(:stderr).and_return('')
34+
result.stub(:stdout).and_return(<<-JSON)
35+
{
36+
"test.scss": [
37+
{
38+
"line": 1,
39+
"column": 1,
40+
"length": 2,
41+
"severity": "warning",
42+
"reason": "Empty rule",
43+
"linter": "EmptyRule"
44+
}
45+
]
46+
}
47+
JSON
3648
end
3749

3850
it { should warn }
@@ -41,17 +53,39 @@
4153
context 'and it reports an error' do
4254
before do
4355
result.stub(:status).and_return(2)
44-
result.stub(:stdout).and_return([
45-
'file1.scss:1 [E] Syntax Error: Invalid CSS',
46-
].join("\n"))
56+
result.stub(:stderr).and_return('')
57+
result.stub(:stdout).and_return(<<-JSON)
58+
{
59+
"test.scss": [
60+
{
61+
"line": 1,
62+
"column": 1,
63+
"length": 2,
64+
"severity": "error",
65+
"reason": "Syntax error",
66+
}
67+
]
68+
}
69+
JSON
4770
end
4871

4972
it { should fail_hook }
5073
end
5174

75+
context 'and it returns invalid JSON' do
76+
before do
77+
result.stub(:status).and_return(1)
78+
result.stub(:stderr).and_return('')
79+
result.stub(:stdout).and_return('This is not JSON')
80+
end
81+
82+
it { should fail_hook /Unable to parse JSON returned by SCSS-Lint/ }
83+
end
84+
5285
context 'and it returns status code indicating all files were filtered' do
5386
before do
5487
result.stub(:status).and_return(81)
88+
result.stub(:stderr).and_return('')
5589
result.stub(:stdout).and_return('')
5690
end
5791

0 commit comments

Comments
 (0)