how_is 11.0.0 → 12.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -44,6 +44,9 @@ module HowIs
44
44
 
45
45
  oldest_issue: issue_or_pull_to_hash(oldest_for(issues)),
46
46
  oldest_pull: issue_or_pull_to_hash(oldest_for(pulls)),
47
+
48
+ newest_issue: issue_or_pull_to_hash(newest_for(issues)),
49
+ newest_pull: issue_or_pull_to_hash(newest_for(pulls)),
47
50
  )
48
51
  end
49
52
 
@@ -147,12 +150,24 @@ module HowIs
147
150
  "approximately #{value}"
148
151
  end
149
152
 
150
- # Given an Array of issues or pulls, return the creation date of the oldest.
153
+ def sort_iops_by_created_at(issues_or_pulls)
154
+ issues_or_pulls.sort_by {|x| DateTime.parse(x['created_at']) }
155
+ end
156
+
157
+ # Given an Array of issues or pulls, return the oldest.
151
158
  # Returns nil if no issues or pulls are provided.
152
159
  def oldest_for(issues_or_pulls)
153
160
  return nil if issues_or_pulls.empty?
154
161
 
155
- issues_or_pulls.sort_by {|x| DateTime.parse(x['created_at']) }.first
162
+ sort_iops_by_created_at(issues_or_pulls).first
163
+ end
164
+
165
+ # Given an Array of issues or pulls, return the newest.
166
+ # Returns nil if no issues or pulls are provided.
167
+ def newest_for(issues_or_pulls)
168
+ return nil if issues_or_pulls.empty?
169
+
170
+ sort_iops_by_created_at(issues_or_pulls).last
156
171
  end
157
172
 
158
173
  # Given an issue or PR, returns the date it was created.
@@ -0,0 +1,129 @@
1
+ require 'json'
2
+
3
+ module HowIs
4
+ ##
5
+ # Subclasses of BaseReport represent complete reports.
6
+ class BaseReport < Struct.new(:analysis)
7
+ def generate_report_text!
8
+ # title, text, header, horizontal_bar_graph, etc,
9
+ # append to @r, which is returned at the end of the function.
10
+
11
+ title "How is #{analysis.repository}?"
12
+
13
+ # DateTime#new_offset(0) sets the timezone to UTC. I think it does this
14
+ # without changing anything besides the timezone, but who knows, 'cause
15
+ # new_offset is entirely undocumented! (Even though it's used in the
16
+ # DateTime documentation!)
17
+ #
18
+ # TODO: Stop pretending everyone who runs how_is is in UTC.
19
+ text "Monthly report, ending on #{DateTime.now.new_offset(0).strftime('%B %e, %Y')}."
20
+
21
+ text github_pulse_summary
22
+
23
+ header "Pull Requests"
24
+ issue_or_pr_summary "pull", "pull request"
25
+
26
+ header "Issues"
27
+ issue_or_pr_summary "issue", "issue"
28
+
29
+ header "Issues Per Label"
30
+ issues_per_label = analysis.issues_with_label.to_a.sort_by { |(k, v)| v['total'].to_i }.reverse
31
+ issues_per_label.map! do |label, hash|
32
+ [label, hash['total'], hash['link']]
33
+ end
34
+ issues_per_label << ["(No label)", analysis.issues_with_no_label['total'], nil]
35
+ horizontal_bar_graph issues_per_label
36
+
37
+ # See comment at beginning of function.
38
+ @r
39
+ end
40
+
41
+
42
+
43
+ def format
44
+ raise NotImplementedError
45
+ end
46
+
47
+ def title(_text)
48
+ raise NotImplementedError
49
+ end
50
+
51
+ def header(_text)
52
+ raise NotImplementedError
53
+ end
54
+
55
+ def text(_text)
56
+ raise NotImplementedError
57
+ end
58
+
59
+ def link(_text, url)
60
+ raise NotImplementedError
61
+ end
62
+
63
+ def unordered_list(arr)
64
+ raise NotImplementedError
65
+ end
66
+
67
+ def horizontal_bar_graph(data)
68
+ raise NotImplementedError
69
+ end
70
+
71
+ def monthly_summary
72
+ raise NotImplementedError
73
+ end
74
+
75
+ def export
76
+ raise NotImplementedError
77
+ end
78
+
79
+ def export_file(file)
80
+ raise NotImplementedError
81
+ end
82
+
83
+ def to_h
84
+ analysis.to_h
85
+ end
86
+ alias :to_hash :to_h
87
+
88
+ def to_json
89
+ JSON.pretty_generate(to_h)
90
+ end
91
+
92
+ private
93
+ def github_pulse_summary
94
+ @pulse ||= HowIs::Pulse.new(analysis.repository)
95
+ @pulse.send("#{format}_summary")
96
+ end
97
+
98
+ def pluralize(text, number)
99
+ number == 1 ? text : "#{text}s"
100
+ end
101
+
102
+ def are_is(number)
103
+ number == 1 ? "is" : "are"
104
+ end
105
+
106
+ def issue_or_pr_summary(type, type_label)
107
+ date_format = "%b %e, %Y"
108
+ a = analysis
109
+
110
+ number_of_type = a.send("number_of_#{type}s")
111
+
112
+ type_link = a.send("#{type}s_url")
113
+ oldest = a.send("oldest_#{type}")
114
+ newest = a.send("newest_#{type}")
115
+
116
+ if number_of_type == 0
117
+ text "There are #{link("no #{type_label}s open", type_link)}."
118
+ else
119
+ text "There #{are_is(number_of_type)} #{link("#{number_of_type} #{pluralize(type_label, number_of_type)} open", type_link)}."
120
+
121
+ unordered_list [
122
+ "Average age: #{a.send("average_#{type}_age")}.",
123
+ "#{link('Oldest ' + type_label, oldest['html_url'])} was opened on #{oldest['date'].strftime(date_format)}.",
124
+ "#{link('Newest ' + type_label, newest['html_url'])} was opened on #{newest['date'].strftime(date_format)}.",
125
+ ]
126
+ end
127
+ end
128
+ end
129
+ end
@@ -1,5 +1,5 @@
1
1
  require 'cgi'
2
- require 'how_is/pulse'
2
+ require 'how_is/report/base_report'
3
3
 
4
4
  module HowIs
5
5
  class HtmlReport < BaseReport
@@ -9,29 +9,42 @@ module HowIs
9
9
 
10
10
  def title(_text)
11
11
  @title = _text
12
- @r += "<h1>#{_text}</h1>"
12
+ @r += "\n<h1>#{_text}</h1>\n"
13
13
  end
14
14
 
15
15
  def header(_text)
16
- @r += "<h2>#{_text}</h2>"
16
+ @r += "\n<h2>#{_text}</h2>\n"
17
17
  end
18
18
 
19
19
  def link(_text, url)
20
20
  %Q[<a href="#{url}">#{_text}</a>]
21
21
  end
22
22
 
23
- def monthly_summary
24
- pulse.html_summary
23
+ def text(_text)
24
+ @r += "<p>#{_text}</p>\n"
25
+ end
26
+
27
+ def unordered_list(arr)
28
+ @r += "\n<ul>\n"
29
+ arr.each do |item|
30
+ @r += " <li>#{item}</li>\n"
31
+ end
32
+ @r += "</ul>\n\n"
25
33
  end
26
34
 
27
35
  def horizontal_bar_graph(data)
36
+ if data.length == 1 && data[0][0] == "(No label)"
37
+ text "There are no open issues to graph."
38
+ return
39
+ end
40
+
28
41
  biggest = data.map { |x| x[1] }.max
29
42
  get_percentage = ->(number_of_issues) { number_of_issues * 100 / biggest }
30
43
 
31
44
  longest_label_length = data.map(&:first).map(&:length).max
32
45
  label_width = "#{longest_label_length}ch"
33
46
 
34
- @r += '<table class="horizontal-bar-graph">'
47
+ @r += "<table class=\"horizontal-bar-graph\">\n"
35
48
  data.each do |row|
36
49
  percentage = get_percentage.(row[1])
37
50
 
@@ -46,22 +59,23 @@ module HowIs
46
59
  <td style="width: #{label_width}">#{label_text}</td>
47
60
  <td><span class="fill" style="width: #{percentage}%">#{row[1]}</span></td>
48
61
  </tr>
62
+
49
63
  EOF
50
64
  end
51
- @r += "</table>"
65
+ @r += "</table>\n"
52
66
  end
53
67
 
54
- def text(_text)
55
- @r += "<p>#{_text}</p>"
68
+ def monthly_summary
69
+ pulse.html_summary
56
70
  end
57
71
 
58
- def export(&block)
72
+ def export
59
73
  @r = ''
60
- instance_exec(&block)
74
+ generate_report_text!
61
75
  end
62
76
 
63
- def export_file(file, &block)
64
- report = export(&block)
77
+ def export_file(file)
78
+ report = export
65
79
 
66
80
  File.open(file, 'w') do |f|
67
81
  f.puts <<-EOF
@@ -1,14 +1,16 @@
1
+ require 'how_is/report/base_report'
2
+
1
3
  module HowIs
2
4
  class JsonReport < BaseReport
3
5
  def format
4
6
  :json
5
7
  end
6
8
 
7
- def export(&block)
9
+ def export
8
10
  to_json
9
11
  end
10
12
 
11
- def export_file(file, &block)
13
+ def export_file(file)
12
14
  File.open(file, 'w') do |f|
13
15
  f.write export
14
16
  end
data/lib/how_is/report.rb CHANGED
@@ -8,102 +8,17 @@ module HowIs
8
8
  end
9
9
  end
10
10
 
11
- ##
12
- # Represents a completed report.
13
- class BaseReport < Struct.new(:analysis)
14
- def format
15
- raise NotImplementedError
16
- end
17
-
18
- def github_pulse_summary
19
- @pulse ||= HowIs::Pulse.new(analysis.repository)
20
- @pulse.send("#{format}_summary")
21
- end
22
-
23
- def to_h
24
- analysis.to_h
25
- end
26
- alias :to_hash :to_h
27
-
28
- def to_json
29
- to_h.to_json
30
- end
31
-
32
- private
33
- def pluralize(text, number)
34
- number == 1 ? text : "#{text}s"
35
- end
36
-
37
- def are_is(number)
38
- number == 1 ? "is" : "are"
39
- end
40
-
41
- def issue_or_pr_summary(type, type_label)
42
- oldest_date_format = "%b %e, %Y"
43
- a = analysis
44
-
45
- number_of_type = a.send("number_of_#{type}s")
46
-
47
- type_link = a.send("#{type}s_url")
48
- oldest = a.send("oldest_#{type}")
49
-
50
- if number_of_type == 0
51
- "There are #{link("no #{type_label}s open", type_link)}."
52
- else
53
- "There #{are_is(number_of_type)} #{link("#{number_of_type} #{pluralize(type_label, number_of_type)} open", type_link)}. " +
54
- "The average #{type_label} age is #{a.send("average_#{type}_age")}, and the " +
55
- "#{link("oldest", oldest['html_url'])} was opened on #{oldest['date'].strftime(oldest_date_format)}."
56
- end
57
- end
58
- end
59
-
60
11
  class Report
61
12
  require 'how_is/report/json'
62
13
  require 'how_is/report/html'
63
14
 
64
- # The way this entire class works is there is a REPORT_BLOCK proc which
65
- # calls various methods to create the report, and REPORT_BLOCK is eventually
66
- # instance_exec'd by the various *Report (HtmlReport, previously PdfReport)
67
- # classes, which define the methods required.
68
- #
69
- # The *Report class inherit from BaseReport, which implements the common
70
- # methods for them.
71
-
72
- REPORT_BLOCK = proc do
73
- title "How is #{analysis.repository}?"
74
-
75
- # DateTime#new_offset(0) sets the timezone to UTC. I think it does this
76
- # without changing anything besides the timezone, but who knows, 'cause
77
- # new_offset is entirely undocumented! (Even though it's used in the
78
- # DateTime documentation!)
79
- #
80
- # TODO: Stop pretending everyone who runs how_is is in UTC.
81
- text "Monthly report, ending on #{DateTime.now.new_offset(0).strftime('%B %e, %Y')}."
82
-
83
- text github_pulse_summary
84
-
85
- header "Pull Requests"
86
- text issue_or_pr_summary "pull", "pull request"
87
-
88
- header "Issues"
89
- text issue_or_pr_summary "issue", "issue"
90
-
91
- header "Issues Per Label"
92
- issues_per_label = analysis.issues_with_label.to_a.sort_by { |(k, v)| v['total'].to_i }.reverse
93
- issues_per_label.map! do |label, hash|
94
- [label, hash['total'], hash['link']]
95
- end
96
- issues_per_label << ["(No label)", analysis.issues_with_no_label['total'], nil]
97
- horizontal_bar_graph issues_per_label
98
- end
99
-
100
15
  ##
101
16
  # Export a report to a file.
102
17
  def self.export_file(analysis, file)
103
18
  format = file.split('.').last
104
19
  report = get_report_class(format).new(analysis)
105
20
 
106
- report.export_file(file, &REPORT_BLOCK)
21
+ report.export_file(file)
107
22
  end
108
23
 
109
24
  ##
@@ -111,7 +26,7 @@ module HowIs
111
26
  def self.export(analysis, format = HowIs::DEFAULT_FORMAT)
112
27
  report = get_report_class(format).new(analysis)
113
28
 
114
- report.export(&REPORT_BLOCK)
29
+ report.export
115
30
  end
116
31
 
117
32
  private
@@ -1,3 +1,3 @@
1
1
  module HowIs
2
- VERSION = "11.0.0"
2
+ VERSION = "12.0.0"
3
3
  end
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: 11.0.0
4
+ version: 12.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-13 00:00:00.000000000 Z
11
+ date: 2016-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: github_api
@@ -202,7 +202,6 @@ extra_rdoc_files: []
202
202
  files:
203
203
  - ".gitignore"
204
204
  - ".rspec"
205
- - ".rspec-ignore-tags"
206
205
  - ".travis.yml"
207
206
  - CHANGELOG.md
208
207
  - CODE_OF_CONDUCT.md
@@ -213,8 +212,9 @@ files:
213
212
  - bin/console
214
213
  - bin/setup
215
214
  - exe/how_is
216
- - fixtures/vcr_cassettes/how_is-example-repository.yml
217
- - fixtures/vcr_cassettes/how_is-with-config-file.yml
215
+ - fixtures/vcr_cassettes/how-is-example-empty-repository.yml
216
+ - fixtures/vcr_cassettes/how-is-example-repository.yml
217
+ - fixtures/vcr_cassettes/how-is-with-config-file.yml
218
218
  - how_is.gemspec
219
219
  - lib/how_is.rb
220
220
  - lib/how_is/analyzer.rb
@@ -223,6 +223,7 @@ files:
223
223
  - lib/how_is/fetcher.rb
224
224
  - lib/how_is/pulse.rb
225
225
  - lib/how_is/report.rb
226
+ - lib/how_is/report/base_report.rb
226
227
  - lib/how_is/report/html.rb
227
228
  - lib/how_is/report/json.rb
228
229
  - lib/how_is/version.rb
@@ -247,7 +248,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
247
248
  version: '0'
248
249
  requirements: []
249
250
  rubyforge_project:
250
- rubygems_version: 2.6.8
251
+ rubygems_version: 2.4.5.2
251
252
  signing_key:
252
253
  specification_version: 4
253
254
  summary: Quantify the health of a GitHub repository is.
data/.rspec-ignore-tags DELETED
@@ -1,2 +0,0 @@
1
- --format documentation
2
- --color