how_is 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +0 -2
- data/README.md +2 -0
- data/exe/how_is +5 -1
- data/how_is.gemspec +4 -1
- data/lib/how_is/analyzer.rb +35 -6
- data/lib/how_is/report/html.rb +15 -2
- data/lib/how_is/report/pdf.rb +6 -1
- data/lib/how_is/report.rb +16 -10
- data/lib/how_is/version.rb +1 -1
- data/lib/how_is.rb +9 -0
- metadata +14 -15
- data/data/how_is_spec/generate_report--generates-a-correct-JSON-report.json +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f8b7397035c52022ad95011075e202e3f4e271e
|
4
|
+
data.tar.gz: 1bc5444c77188717a43d667e36d84185576bb6f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 003439cd51e94bd6e7136cfae977bb8bcb1f7b5f3d9a1b5b3ebf7404f8d3d21ab668901c87565314d17bd1b2bd78e2481151c4ccbcc593b3418a006063c8e407
|
7
|
+
data.tar.gz: 040161c89aa03c12083fcae5c0e944776298b75c65087c0ac5e24b0c85b8dc10312d3b6f2b7c02356dfde0835e99e678e8540aa9e8aaf27806cde3982d8db607
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
[](https://waffle.io/duckinator/how_is)
|
2
|
+
[](https://travis-ci.org/duckinator/how_is)
|
3
|
+
|
2
4
|
# How is [your repo]?
|
3
5
|
|
4
6
|
`how_is` is tool for generating summaries of the health of a codebase. It uses information available from issues and pull requests to provide an overview of a repository and highlight problem areas of the codebase.
|
data/exe/how_is
CHANGED
@@ -33,12 +33,16 @@ opts = OptionParser.new do |opts|
|
|
33
33
|
options[:from_file] = file
|
34
34
|
end
|
35
35
|
|
36
|
-
opts.on("--report REPORT_FILE", "
|
36
|
+
opts.on("--report REPORT_FILE", "file containing the report") do |file|
|
37
37
|
options[:report_file] = file
|
38
38
|
end
|
39
39
|
end
|
40
40
|
opts.parse!
|
41
41
|
|
42
|
+
unless HowIs.can_export_to?(options[:report_file])
|
43
|
+
abort "Invalid file: #{options[:report_file]}. Supported formats: #{HowIs.supported_formats.join(', ')}"
|
44
|
+
end
|
45
|
+
|
42
46
|
if options[:from_file]
|
43
47
|
# Opening this file here seems a bit messy, but it works.
|
44
48
|
options[:repository] = JSON.parse(open(options[:from_file]).read)['repository']
|
data/how_is.gemspec
CHANGED
@@ -19,12 +19,15 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_runtime_dependency "github_api", "~> 0.13.1"
|
22
|
-
spec.add_runtime_dependency "configru", "~> 3.6.0"
|
23
22
|
spec.add_runtime_dependency "contracts"
|
24
23
|
spec.add_runtime_dependency "prawn"
|
25
24
|
|
26
25
|
spec.add_runtime_dependency "mini_magick"
|
27
26
|
|
27
|
+
# Travis CI only supports up to Ruby 2.2.0, but Rack 2.0+ requires Ruby 2.2.2+,
|
28
|
+
# so this pegs Rack to the latest version that works with Ruby 2.2.0.
|
29
|
+
spec.add_runtime_dependency "rack", "< 2.0"
|
30
|
+
|
28
31
|
spec.add_development_dependency "bundler", "~> 1.11"
|
29
32
|
spec.add_development_dependency "rake", "~> 10.0"
|
30
33
|
spec.add_development_dependency "rspec", "~> 3.0"
|
data/lib/how_is/analyzer.rb
CHANGED
@@ -24,19 +24,22 @@ module HowIs
|
|
24
24
|
pulls = data.pulls
|
25
25
|
|
26
26
|
analysis_class.new(
|
27
|
+
issues_url: "https://github.com/#{data.repository}/issues",
|
28
|
+
pulls_url: "https://github.com/#{data.repository}/pulls",
|
29
|
+
|
27
30
|
repository: data.repository,
|
28
31
|
|
29
32
|
number_of_issues: issues.length,
|
30
33
|
number_of_pulls: pulls.length,
|
31
34
|
|
32
|
-
issues_with_label: num_with_label(issues),
|
33
|
-
issues_with_no_label: num_with_no_label(issues),
|
35
|
+
issues_with_label: with_label_links(num_with_label(issues), data.repository),
|
36
|
+
issues_with_no_label: {link: nil, total: num_with_no_label(issues)},
|
34
37
|
|
35
38
|
average_issue_age: average_age_for(issues),
|
36
39
|
average_pull_age: average_age_for(pulls),
|
37
40
|
|
38
|
-
|
39
|
-
|
41
|
+
oldest_issue: issue_or_pull_to_hash(oldest_for(issues)),
|
42
|
+
oldest_pull: issue_or_pull_to_hash(oldest_for(pulls)),
|
40
43
|
)
|
41
44
|
end
|
42
45
|
|
@@ -51,6 +54,10 @@ module HowIs
|
|
51
54
|
[k, v]
|
52
55
|
end.to_h
|
53
56
|
|
57
|
+
%w[oldest_issue oldest_pull].each do |key|
|
58
|
+
hash[key]['date'] = DateTime.parse(hash[key]['date'])
|
59
|
+
end
|
60
|
+
|
54
61
|
Analysis.new(hash)
|
55
62
|
end
|
56
63
|
|
@@ -129,13 +136,35 @@ module HowIs
|
|
129
136
|
end
|
130
137
|
|
131
138
|
# Given an Array of issues or pulls, return the creation date of the oldest.
|
132
|
-
def
|
133
|
-
issues_or_pulls.
|
139
|
+
def oldest_for(issues_or_pulls)
|
140
|
+
issues_or_pulls.sort_by {|x| DateTime.parse(x['created_at']) }.first
|
141
|
+
end
|
142
|
+
|
143
|
+
def date_for(issue_or_pull)
|
144
|
+
DateTime.parse(issue_or_pull['created_at'])
|
134
145
|
end
|
135
146
|
|
136
147
|
private
|
148
|
+
def with_label_links(labels, repository)
|
149
|
+
labels.map do |label, num_issues|
|
150
|
+
label_link = "https://github.com/#{repository}/issues?q=" + CGI.escape("is:open is:issue label:\"#{label}\"")
|
151
|
+
|
152
|
+
[label, {link: label_link, total: num_issues}]
|
153
|
+
end.to_h
|
154
|
+
end
|
155
|
+
|
137
156
|
def time_ago_in_seconds(x)
|
138
157
|
DateTime.now.strftime("%s").to_i - DateTime.parse(x).strftime("%s").to_i
|
139
158
|
end
|
159
|
+
|
160
|
+
def issue_or_pull_to_hash(iop)
|
161
|
+
ret = {}
|
162
|
+
|
163
|
+
ret[:html_url] = iop['html_url']
|
164
|
+
ret[:number] = iop['number']
|
165
|
+
ret[:date] = date_for(iop)
|
166
|
+
|
167
|
+
ret
|
168
|
+
end
|
140
169
|
end
|
141
170
|
end
|
data/lib/how_is/report/html.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
1
3
|
module HowIs
|
2
4
|
class HtmlReport < BaseReport
|
3
5
|
def title(_text)
|
@@ -9,8 +11,12 @@ module HowIs
|
|
9
11
|
@r += "<h2>#{_text}</h2>"
|
10
12
|
end
|
11
13
|
|
14
|
+
def link(_text, url)
|
15
|
+
%Q[<a href="#{url}">#{_text}</a>]
|
16
|
+
end
|
17
|
+
|
12
18
|
def horizontal_bar_graph(data)
|
13
|
-
biggest = data.map
|
19
|
+
biggest = data.map { |x| x[1] }.max
|
14
20
|
get_percentage = ->(number_of_issues) { number_of_issues * 100 / biggest }
|
15
21
|
|
16
22
|
longest_label_length = data.map(&:first).map(&:length).max
|
@@ -19,9 +25,16 @@ module HowIs
|
|
19
25
|
@r += '<table class="horizontal-bar-graph">'
|
20
26
|
data.each do |row|
|
21
27
|
percentage = get_percentage.(row[1])
|
28
|
+
|
29
|
+
if row[2]
|
30
|
+
label_text = link(row[0], row[2])
|
31
|
+
else
|
32
|
+
label_text = row[1]
|
33
|
+
end
|
34
|
+
|
22
35
|
@r += <<-EOF
|
23
36
|
<tr>
|
24
|
-
<td style="width: #{label_width}">#{
|
37
|
+
<td style="width: #{label_width}">#{label_text}</td>
|
25
38
|
<td><span class="fill" style="width: #{percentage}%">#{row[1]}</span></td>
|
26
39
|
</tr>
|
27
40
|
EOF
|
data/lib/how_is/report/pdf.rb
CHANGED
@@ -19,13 +19,18 @@ module HowIs
|
|
19
19
|
}
|
20
20
|
end
|
21
21
|
|
22
|
+
def link(_text, url)
|
23
|
+
# TODO: Actually have links.
|
24
|
+
_text
|
25
|
+
end
|
26
|
+
|
22
27
|
def horizontal_bar_graph(data)
|
23
28
|
filename_base = "./issues-per-label"
|
24
29
|
dat_file = filename_base + '.dat'
|
25
30
|
png_file = filename_base + '.png'
|
26
31
|
|
27
32
|
File.open(dat_file, 'w') do |f|
|
28
|
-
data.each_with_index do |(label, n), i|
|
33
|
+
data.each_with_index do |(label, n, link), i|
|
29
34
|
f.puts "#{i}\t#{n}\t\"#{label}\""
|
30
35
|
end
|
31
36
|
end
|
data/lib/how_is/report.rb
CHANGED
@@ -18,16 +18,19 @@ module HowIs
|
|
18
18
|
end
|
19
19
|
|
20
20
|
private
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
def issue_or_pr_summary(type, type_label)
|
22
|
+
oldest_date_format = "%b %e, %Y"
|
23
|
+
a = analysis
|
24
24
|
|
25
|
-
|
25
|
+
number_of_type = a.send("number_of_#{type}s")
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
type_link = a.send("#{type}s_url")
|
28
|
+
oldest = a.send("oldest_#{type}")
|
29
|
+
|
30
|
+
"There are #{link("#{number_of_type} #{type_label}s open", type_link)}. " +
|
31
|
+
"The average #{type_label} age is #{a.send("average_#{type}_age")}, and the " +
|
32
|
+
"#{link("oldest", oldest['html_url'])} was opened on #{oldest['date'].strftime(oldest_date_format)}."
|
33
|
+
end
|
31
34
|
end
|
32
35
|
|
33
36
|
class Report
|
@@ -45,8 +48,11 @@ module HowIs
|
|
45
48
|
text issue_or_pr_summary "issue", "issue"
|
46
49
|
|
47
50
|
header "Issues Per Label"
|
48
|
-
issues_per_label = analysis.issues_with_label.to_a.sort_by { |(k, v)| v.to_i }.reverse
|
49
|
-
issues_per_label
|
51
|
+
issues_per_label = analysis.issues_with_label.to_a.sort_by { |(k, v)| v['total'].to_i }.reverse
|
52
|
+
issues_per_label.map! do |label, hash|
|
53
|
+
[label, hash['total'], hash['link']]
|
54
|
+
end
|
55
|
+
issues_per_label << ["(No label)", analysis.issues_with_no_label['total'], nil]
|
50
56
|
horizontal_bar_graph issues_per_label
|
51
57
|
end
|
52
58
|
|
data/lib/how_is/version.rb
CHANGED
data/lib/how_is.rb
CHANGED
@@ -21,6 +21,15 @@ module HowIs
|
|
21
21
|
|
22
22
|
Report.export(analysis, format)
|
23
23
|
end
|
24
|
+
|
25
|
+
def self.supported_formats
|
26
|
+
report_constants = HowIs.constants.grep(/.Report/) - [:BaseReport]
|
27
|
+
report_constants.map {|x| x.to_s.split('Report').first.downcase }
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.can_export_to?(file)
|
31
|
+
supported_formats.include?(file.split('.').last)
|
32
|
+
end
|
24
33
|
private
|
25
34
|
|
26
35
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: how_is
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ellen Marie Dash
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-07-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: github_api
|
@@ -25,21 +25,21 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.13.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: contracts
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: prawn
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: mini_magick
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -67,19 +67,19 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rack
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "<"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
75
|
+
version: '2.0'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "<"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
82
|
+
version: '2.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: bundler
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -140,7 +140,6 @@ files:
|
|
140
140
|
- Rakefile
|
141
141
|
- bin/console
|
142
142
|
- bin/setup
|
143
|
-
- data/how_is_spec/generate_report--generates-a-correct-JSON-report.json
|
144
143
|
- data/issues.plg
|
145
144
|
- exe/how_is
|
146
145
|
- how_is.gemspec
|
@@ -1 +0,0 @@
|
|
1
|
-
{"repository":"rubygems/rubygems","number_of_issues":30,"number_of_pulls":30,"issues_with_label":{"triage":7,"bug report":9,"feedback":4,"osx":1,"bug fix":4,"category - install":5,"feature implementation":2,"major bump":2,"windows":1,"feature request":1,"cleanup":1,"accepted":2,"category - #gem or #require":1,"ready for work":1,"question":3,"administrative":1},"issues_with_no_label":0,"average_issue_age":"approximately 3 months and 1 week","average_pull_age":"approximately 11 months and 3 days","oldest_issue_date":"2016-01-31T21:28:02+00:00","oldest_pull_date":"2013-09-16T15:04:07+00:00"}
|