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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0d03e9957e3cfefe6c95927bf11693ee2556d318
4
- data.tar.gz: 9159d25f1cd1f7d221a21fb7d0d38a844a271fda
3
+ metadata.gz: 8f8b7397035c52022ad95011075e202e3f4e271e
4
+ data.tar.gz: 1bc5444c77188717a43d667e36d84185576bb6f6
5
5
  SHA512:
6
- metadata.gz: bad3e1bd77fa4958c81c497b3002309121efc4575c8f5b45e31d302abb7ce23a0332999bcf631e08b735a612acb32ae0eb57e4b35df4d7b332b3adf2618506a2
7
- data.tar.gz: f6989dc7995c9aaf8215f1dd813d9173a14aa54fc9003bec21d91885e6335ac26c2a33c76ceaad4791a6243e0b3e9291cd89a5f65b3c7ecd190e72057e95926f
6
+ metadata.gz: 003439cd51e94bd6e7136cfae977bb8bcb1f7b5f3d9a1b5b3ebf7404f8d3d21ab668901c87565314d17bd1b2bd78e2481151c4ccbcc593b3418a006063c8e407
7
+ data.tar.gz: 040161c89aa03c12083fcae5c0e944776298b75c65087c0ac5e24b0c85b8dc10312d3b6f2b7c02356dfde0835e99e678e8540aa9e8aaf27806cde3982d8db607
data/.travis.yml CHANGED
@@ -1,6 +1,4 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.2
4
- - jruby
5
- - rbx-2
6
4
  before_install: gem install bundler -v 1.11.2
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
1
  [![Stories in Ready](https://badge.waffle.io/duckinator/how_is.png?label=ready&title=Ready)](https://waffle.io/duckinator/how_is)
2
+ [![Build Status](https://travis-ci.org/duckinator/how_is.svg?branch=master)](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", "CSV file containing the report") do |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"
@@ -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
- oldest_issue_date: oldest_date_for(issues),
39
- oldest_pull_date: oldest_date_for(pulls),
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 oldest_date_for(issues_or_pulls)
133
- issues_or_pulls.map {|x| DateTime.parse(x['created_at']) }.sort.first
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
@@ -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(&:last).max
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}">#{row[0]}</td>
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
@@ -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
- def issue_or_pr_summary(type, type_label)
22
- oldest_date_format = "%b %e, %Y"
23
- a = analysis
21
+ def issue_or_pr_summary(type, type_label)
22
+ oldest_date_format = "%b %e, %Y"
23
+ a = analysis
24
24
 
25
- number_of_type = a.send("number_of_#{type}s")
25
+ number_of_type = a.send("number_of_#{type}s")
26
26
 
27
- "There are #{number_of_type} #{type_label}s open. " +
28
- "The average #{type_label} age is #{a.send("average_#{type}_age")}, and the " +
29
- "oldest was opened on #{a.send("oldest_#{type}_date").strftime(oldest_date_format)}."
30
- end
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 << ["(No label)", analysis.issues_with_no_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
 
@@ -1,3 +1,3 @@
1
1
  module HowIs
2
- VERSION = "2.0.0"
2
+ VERSION = "3.0.0"
3
3
  end
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: 2.0.0
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-06-27 00:00:00.000000000 Z
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: configru
28
+ name: contracts
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 3.6.0
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: 3.6.0
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: contracts
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: prawn
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: mini_magick
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"}