Skip to content

Commit 3cd597b

Browse files
authored
QUA-840: fix issue reporting (#4)
1 parent 37ac79b commit 3cd597b

File tree

1 file changed

+42
-43
lines changed

1 file changed

+42
-43
lines changed

Diff for: lib/cc/engine/golangci.rb

+42-43
Original file line numberDiff line numberDiff line change
@@ -2,54 +2,73 @@
22
require 'pathname'
33
require 'json'
44
require 'digest/sha1'
5+
require 'open3'
56

67
module CC
78
module Engine
89
class Golangci
910
ALLOWED_EXTENSIONS = %w[.go]
11+
ISSUE_IDENTIFIER_REGEXP = /^([^\s]+): (.*)/.freeze
1012

1113
def initialize(engine_config)
1214
@engine_config = engine_config || {}
1315
@files_to_analyze = []
1416
@dirs_to_analyze = []
1517
end
1618

17-
attr_reader :engine_config, :dirs_to_analyze, :files_to_analyze
19+
attr_reader :engine_config
1820

1921
def run
20-
build_paths_to_analyze
22+
issues = analyze_paths.compact
2123

22-
run_for_paths(dirs_to_analyze)
23-
run_for_paths(files_to_analyze)
24+
puts output_issues(issues)
2425
end
2526

26-
def run_for_paths(paths)
27-
data = IO.popen(command_env, command(paths)).read
28-
begin
29-
data = JSON.parse(data)
30-
rescue JSON::ParserError
31-
warn "Error parsing golangci-lint's output:"
32-
warn data
33-
exit!
27+
def analyze_paths
28+
# run the linter for each include_paths path
29+
# we do this because the linter is very strict and loud about the paths to analyze we provide as arguments
30+
# this method is noticeably slower than running the linter just once
31+
32+
include_paths.flat_map do |path|
33+
real_path = Pathname.new(path).realpath
34+
35+
if real_path.directory?
36+
path += "..."
37+
else
38+
next unless ALLOWED_EXTENSIONS.include?(real_path.extname)
39+
end
40+
41+
issues = run_command(path)["Issues"]
42+
next unless issues.is_a?(Array) && issues.length > 0
43+
44+
issues.map { |issue| process_issue(issue) }
3445
end
46+
end
47+
48+
def run_command(path)
49+
data = IO.popen(command_env, command(path)).read
50+
return {} if data.nil? || data.empty?
3551

36-
issues = data["Issues"]
37-
return unless issues.is_a?(Array) && issues.length > 0
38-
39-
puts data['Issues'].map { |issue| "#{convert_issue(issue)}\0" }.join
52+
JSON.parse(data)
53+
rescue JSON::ParserError
54+
warn "Error parsing golangci-lint's output:"
55+
warn "#{data}"
56+
exit!
4057
end
4158

42-
def command(paths)
43-
["/usr/local/bin/golangci-lint", "run", "--out-format", "json", *paths]
59+
def command(path)
60+
["/usr/local/bin/golangci-lint", "run", "--out-format", "json", path]
4461
end
4562

4663
def command_env
4764
{ "CGO_ENABLED" => "0" }
4865
end
4966

50-
ISSUE_IDENTIFIER_REGEXP = /^([^\s]+): (.*)/.freeze
67+
def output_issues(issues)
68+
issues.uniq { |issue| issue[:fingerprint] }.map { |issue| issue.to_json + "\0" }.join
69+
end
5170

52-
def convert_issue(issue)
71+
def process_issue(issue)
5372
text = issue['Text']
5473
# Data coming from linters is not standardised, so it may be quite
5574
# complicated to extract a check_name and description from it. Here we
@@ -69,7 +88,7 @@ def convert_issue(issue)
6988
categories: categories_for_linter(linter_name),
7089
fingerprint: fingerprint_issue(issue),
7190
location: locate_issue(issue)
72-
}.to_json
91+
}
7392
end
7493

7594
def categories_for_linter(linter)
@@ -104,28 +123,8 @@ def fingerprint_issue(issue)
104123

105124
private
106125

107-
def build_paths_to_analyze
108-
# golangci-lint surfaces errors when analyzing directories and files in the same run,
109-
# so we need to split the analysis into two different runs: one for directories and one for files
110-
111-
include_paths = engine_config["include_paths"] || ["./"]
112-
113-
include_paths.each do |path|
114-
begin
115-
pathname = Pathname.new(path).realpath
116-
117-
if pathname.directory?
118-
# golangci-lint allows adding ... to a directory path to analyze it recursively
119-
# we want to do this for all directories
120-
121-
@dirs_to_analyze << (pathname + "...").to_s
122-
else
123-
@files_to_analyze << pathname.to_s if ALLOWED_EXTENSIONS.include?(pathname.extname)
124-
end
125-
rescue Errno::ENOENT
126-
nil
127-
end
128-
end.compact
126+
def include_paths
127+
@include_paths ||= engine_config["include_paths"]
129128
end
130129
end
131130
end

0 commit comments

Comments
 (0)