how_is 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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"}