how_is 18.0.3 → 18.0.4

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
- SHA1:
3
- metadata.gz: d6f35707314d01b26c01a857209228e882ab19e8
4
- data.tar.gz: 488bb2052b79301f7c3919f84504e7a786410506
2
+ SHA256:
3
+ metadata.gz: aa512f40b28b33221fb83a6db55d83efe39e5b5c3f5a5160a5eabb1441a58638
4
+ data.tar.gz: 4dc0c71bd1a56bb32e29efebbbc7405b21456566b47ae8b4b1fcc8ebafe90cae
5
5
  SHA512:
6
- metadata.gz: 73c0fd55cfae0d7a25dfb60e431bb99a5826872af8d03db6fdef9b44bdda900746210b32bc220026b03c0fe36bc95c7a0bdf0819cdb9ce9868932af915608bed
7
- data.tar.gz: 6fc00770653ba6af093c986d4135aa5b30fd187f8a6c89e260fc4b33ec18eee57ffb8323d90a2e2b1f8c2ecc3f08845cff37e8c642a07ed5ab9df3c65ae6e0d3
6
+ metadata.gz: 4f2ffd1e34fa07420631add37aa8b084956f58b6b8d67d14ccb4d58942f60a167ad9c7106bd14ce3c53db73498255e1542c2e56559733fccc05dfba157876c46
7
+ data.tar.gz: 40a4bf011b459a31a7ab9e9fedf50b8672f64f8ba3d5e62fa4492260eab05aed27f88b882f87583e128fc2fcf0891508229be723c4d75399dbb43735e0dac9de
data/.gitignore CHANGED
@@ -1,6 +1,6 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
- /Gemfile.lock
3
+ #/Gemfile.lock
4
4
  /_yardoc/
5
5
  /coverage/
6
6
  /doc/
data/.rubocop.yml CHANGED
@@ -1,8 +1,22 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+ Exclude:
4
+ - 'how_is.gemspec'
5
+ - 'bin/*'
6
+ - '**/*~'
7
+ - 'spec/capture_warnings.rb'
8
+ - 'lib/how_is/cli.rb' # FIXME: Make HowIs::CLI.parse not a disaster.
9
+
1
10
  # Exceptions should inherit from StandardError.
2
11
  # (RuboCop default is to inherit from RuntimeError.)
3
12
  Lint/InheritException:
4
13
  EnforcedStyle: standard_error
5
14
 
15
+ Metrics/BlockLength:
16
+ Exclude:
17
+ - 'spec/**/*_spec.rb'
18
+
19
+
6
20
  # The guiding principle of classes is SRP, SRP can't be accurately measured by LoC
7
21
  #Metrics/ClassLength:
8
22
  # Max: 1500
@@ -13,16 +27,32 @@ Lint/InheritException:
13
27
  # It may be worth revisiting this in the future and refactoring those lines.
14
28
  Metrics/LineLength:
15
29
  Max: 120
30
+ AllowHeredoc: true
16
31
 
17
32
  # Too short methods lead to extraction of single-use methods, which can make
18
33
  # the code easier to read (by naming things), but can also clutter the class
19
34
  Metrics/MethodLength:
20
35
  Max: 20
21
36
 
37
+ Style/Alias:
38
+ EnforcedStyle: prefer_alias_method
39
+
22
40
  # Most readable form.
23
41
  Style/AlignHash:
24
42
  EnforcedHashRocketStyle: table
25
43
  EnforcedColonStyle: table
44
+ # Disable because it wound up conflicting with a lot of things like:
45
+ # foo('bar',
46
+ # baz: 'asdf',
47
+ # beep: 'boop')
48
+ #
49
+ # I suspect these'll disappear when overarching architectural issues are
50
+ # addressed.
51
+ Enabled: false
52
+
53
+ Style/AlignParameters:
54
+ # See Style/AlignedHash.
55
+ Enabled: false
26
56
 
27
57
  # This codebase may be English, but some English words contain diacritics.
28
58
  Style/AsciiComments:
@@ -86,6 +116,8 @@ Style/PercentLiteralDelimiters:
86
116
  Enabled: true
87
117
  PreferredDelimiters:
88
118
  default: "[]"
119
+ '%w': '[]'
120
+ '%W': '[]'
89
121
 
90
122
  # `has_key?` and `has_value?` are clearer than `key?` and `value?`.
91
123
  Style/PreferredHashMethods:
@@ -115,6 +147,10 @@ Style/StringLiterals:
115
147
  Enabled: false
116
148
  #EnforcedStyle: double_quotes
117
149
 
150
+ # TODO: Maybe make it so you have to do [:foo, :bar] not %i[foo bar]?
151
+ Style/SymbolArray:
152
+ Enabled: false
153
+
118
154
  # Require parentheses around complex ternary conditions.
119
155
  Style/TernaryParentheses:
120
156
  Enabled: true
data/.travis.yml CHANGED
@@ -1,3 +1,4 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.3.3
4
+ - 2.4.1
data/CHANGELOG.md CHANGED
@@ -9,6 +9,23 @@ this project adheres to [Semantic Versioning](http://semver.org).
9
9
 
10
10
  (Nothing so far.)
11
11
 
12
+ ## [v18.0.4]
13
+
14
+ This release ([snapshot](https://github.com/how-is/how_is/tree/v18.0.4))
15
+ is exclusively cleaning up RuboCop violations and updating dependencies.
16
+ There should be no noticeable changes in functionality.
17
+
18
+ ### Miscellaneous
19
+
20
+ * Use Hashie stable; update Gemfile/add Gemfile.lock. ([#170](https://github.com/how-is/how_is/pull/170))
21
+ * Pass -w to Ruby when running 'rake spec'. ([#169](https://github.com/how-is/how_is/pull/169))
22
+ * Rubocop cleanup. ([#167](https://github.com/how-is/how_is/pull/167))
23
+ * Gemfile: use Hashie from master branch. ([#166](https://github.com/how-is/how_is/pull/166))
24
+ * Update github_api, contracst to latest. ([#165](https://github.com/how-is/how_is/pull/165))
25
+ * Fix (a significant number of) RuboCop violations. ([#162](https://github.com/how-is/how_is/pull/162))
26
+ * README: Drop from_config_file reference. ([#161](https://github.com/how-is/how_is/pull/161))
27
+ * Move rubocop dependency to gemspec. ([#160](https://github.com/how-is/how_is/pull/160))
28
+
12
29
  ## [v18.0.3]
13
30
 
14
31
  This release ([snapshot](https://github.com/how-is/how_is/tree/v18.0.3))
data/Gemfile CHANGED
@@ -1,12 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in how_is.gemspec
4
6
  gemspec
5
-
6
- # Everything says to put it here. It feels like it should go in the gemspec?
7
- # SOMEBODY WHO KNOWS WHAT THEY'RE DOING PLEASE LET ME KNOW WHAT TO DO HERE.
8
- group :test, :development do
9
- # Matches version used by Hound, even though there's newer releases.
10
- # https://github.com/houndci/linters/blob/master/Gemfile.lock
11
- gem 'rubocop', '~> 0.46.0', require: false
12
- end
data/Gemfile.lock ADDED
@@ -0,0 +1,110 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ how_is (18.0.4)
5
+ contracts (~> 0.16.0)
6
+ github_api (~> 0.17.0)
7
+ slop (~> 4.4.1)
8
+ tessellator-fetcher (~> 5.0.0)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ addressable (2.4.0)
14
+ ast (2.3.0)
15
+ contracts (0.16.0)
16
+ crack (0.4.3)
17
+ safe_yaml (~> 1.0.0)
18
+ curl_cacert (1.0.0)
19
+ default (1.0.0)
20
+ descendants_tracker (0.0.4)
21
+ thread_safe (~> 0.3, >= 0.3.1)
22
+ diff-lcs (1.3)
23
+ faraday (0.9.2)
24
+ multipart-post (>= 1.2, < 3)
25
+ github_api (0.17.0)
26
+ addressable (~> 2.4.0)
27
+ descendants_tracker (~> 0.0.4)
28
+ faraday (~> 0.8, < 0.10)
29
+ hashie (>= 3.4)
30
+ mime-types (>= 1.16, < 3.0)
31
+ oauth2 (~> 1.0)
32
+ hashdiff (0.3.4)
33
+ hashie (3.5.6)
34
+ heresy (4.0.0)
35
+ default (~> 1.0.0)
36
+ heresy-string (~> 1.0.0)
37
+ net-socket (~> 1.0.0)
38
+ heresy-string (1.0.0)
39
+ jwt (1.5.6)
40
+ mayhaps (0.3.0)
41
+ mime-types (2.99.3)
42
+ multi_json (1.12.1)
43
+ multi_xml (0.6.0)
44
+ multipart-post (2.0.0)
45
+ net-socket (1.0.0)
46
+ oauth2 (1.4.0)
47
+ faraday (>= 0.8, < 0.13)
48
+ jwt (~> 1.0)
49
+ multi_json (~> 1.3)
50
+ multi_xml (~> 0.5)
51
+ rack (>= 1.2, < 3)
52
+ openssl-better_defaults (0.0.1)
53
+ parser (2.4.0.0)
54
+ ast (~> 2.2)
55
+ powerpack (0.1.1)
56
+ rack (2.0.3)
57
+ rainbow (2.2.2)
58
+ rake
59
+ rake (11.3.0)
60
+ rspec (3.6.0)
61
+ rspec-core (~> 3.6.0)
62
+ rspec-expectations (~> 3.6.0)
63
+ rspec-mocks (~> 3.6.0)
64
+ rspec-core (3.6.0)
65
+ rspec-support (~> 3.6.0)
66
+ rspec-expectations (3.6.0)
67
+ diff-lcs (>= 1.2.0, < 2.0)
68
+ rspec-support (~> 3.6.0)
69
+ rspec-mocks (3.6.0)
70
+ diff-lcs (>= 1.2.0, < 2.0)
71
+ rspec-support (~> 3.6.0)
72
+ rspec-support (3.6.0)
73
+ rubocop (0.47.1)
74
+ parser (>= 2.3.3.1, < 3.0)
75
+ powerpack (~> 0.1)
76
+ rainbow (>= 1.99.1, < 3.0)
77
+ ruby-progressbar (~> 1.7)
78
+ unicode-display_width (~> 1.0, >= 1.0.1)
79
+ ruby-progressbar (1.8.1)
80
+ safe_yaml (1.0.4)
81
+ slop (4.4.3)
82
+ tessellator-fetcher (5.0.1)
83
+ curl_cacert
84
+ heresy (~> 4.0.0)
85
+ mayhaps (~> 0.3.0)
86
+ openssl-better_defaults
87
+ thread_safe (0.3.6)
88
+ timecop (0.8.1)
89
+ unicode-display_width (1.3.0)
90
+ vcr (3.0.3)
91
+ webmock (3.0.1)
92
+ addressable (>= 2.3.6)
93
+ crack (>= 0.3.2)
94
+ hashdiff
95
+
96
+ PLATFORMS
97
+ ruby
98
+
99
+ DEPENDENCIES
100
+ bundler (~> 1.11)
101
+ how_is!
102
+ rake (~> 11.2)
103
+ rspec (~> 3.5)
104
+ rubocop (~> 0.47.0)
105
+ timecop (~> 0.8.1)
106
+ vcr (~> 3.0)
107
+ webmock
108
+
109
+ BUNDLED WITH
110
+ 1.15.1
data/README.md CHANGED
@@ -102,11 +102,6 @@ Every value under `reports` is a format string, so you can do e.g.
102
102
  report = HowIs.new('<orgname>/<reponame>').to_html
103
103
  File.open('report.html', 'w') { |f| f.puts report }
104
104
 
105
- # Generate a report from a config file located at ./how_is.yml.
106
- # Example config file: https://github.com/how-is/how-is-rubygems/blob/gh-pages/how_is.yml
107
- require 'yaml'
108
- HowIs.from_config_file(YAML.load_file('how_is.yml'))
109
-
110
105
  # Generate a report from a config Hash.
111
106
  HowIs.from_config({
112
107
  repository: '<orgname>/<reponame>',
data/Rakefile CHANGED
@@ -1,16 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rspec/core/rake_task'
3
5
  require 'timecop'
4
- #require 'vcr'
5
6
  require './spec/vcr_helper.rb'
6
7
  require 'how_is'
7
8
 
8
- RSpec::Core::RakeTask.new(:spec)
9
+ RSpec::Core::RakeTask.new(:spec) do |t|
10
+ # Warning.warn() was added in Ruby 2.4.0, so don't use -w on older versions.
11
+ t.ruby_opts = '-w -r./spec/capture_warnings.rb' if RUBY_VERSION >= '2.4.0'
12
+ end
9
13
 
10
14
  task :default => :spec
11
15
 
16
+ # Helper functions used later in the Rakefile.
12
17
  class HelperFunctions
13
- def self.freeze_time(&block)
18
+ def self.freeze_time(&_block)
14
19
  date = DateTime.parse('2016-11-01').new_offset(0)
15
20
  Timecop.freeze(date) do
16
21
  yield
@@ -26,7 +31,7 @@ class HelperFunctions
26
31
  format: format,
27
32
  }
28
33
 
29
- cassette = repository.gsub('/', '-')
34
+ cassette = repository.tr('/', '-')
30
35
  VCR.use_cassette(cassette) do
31
36
  report = HowIs.generate_report(**options)
32
37
  end
data/exe/how_is CHANGED
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ # frozen_string_literal: true
4
+
3
5
  require "how_is"
4
6
  require "how_is/cli"
5
7
 
6
8
  begin
7
- result = HowIs::CLI.parse(ARGV)
9
+ result = HowIs::CLI.parse(ARGV)
8
10
  rescue HowIs::CLI::OptionsError => e
9
11
  if ENV['SHOW_TRACE']
10
12
  raise
@@ -42,7 +44,6 @@ begin
42
44
  HowIs::Report.to_format_based_on(options[:report], report)
43
45
  )
44
46
  end
45
-
46
47
  rescue => e
47
48
  if ENV['SHOW_TRACE']
48
49
  raise
data/how_is.gemspec CHANGED
@@ -19,8 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_runtime_dependency "github_api", "~> 0.14.5"
23
- spec.add_runtime_dependency "contracts", "~> 0.14.0"
22
+ spec.add_runtime_dependency "github_api", "~> 0.17.0"
23
+ spec.add_runtime_dependency "contracts", "~> 0.16.0"
24
24
  spec.add_runtime_dependency "slop", "~> 4.4.1"
25
25
 
26
26
  spec.add_runtime_dependency "tessellator-fetcher", "~> 5.0.0"
@@ -31,4 +31,5 @@ Gem::Specification.new do |spec|
31
31
  spec.add_development_dependency "timecop", "~> 0.8.1"
32
32
  spec.add_development_dependency "vcr", "~> 3.0"
33
33
  spec.add_development_dependency "webmock"
34
+ spec.add_development_dependency "rubocop", "~> 0.47.0"
34
35
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'contracts'
2
4
  require 'ostruct'
3
5
  require 'date'
@@ -52,7 +54,7 @@ class HowIs
52
54
  newest_issue: issue_or_pull_to_hash(newest_for(issues)),
53
55
  newest_pull: issue_or_pull_to_hash(newest_for(pulls)),
54
56
 
55
- pulse: data.pulse,
57
+ pulse: data.pulse
56
58
  )
57
59
  end
58
60
 
@@ -61,11 +63,11 @@ class HowIs
61
63
  #
62
64
  # @param data [Hash] The hash to generate an Analysis from.
63
65
  def self.from_hash(data)
64
- hash = data.map do |k, v|
66
+ hash = data.map { |k, v|
65
67
  v = DateTime.parse(v) if k.end_with?('_date')
66
68
 
67
69
  [k, v]
68
- end.to_h
70
+ }.to_h
69
71
 
70
72
  hash.keys.each do |key|
71
73
  next unless hash[key].is_a?(Hash) && hash[key]['date']
@@ -116,7 +118,7 @@ class HowIs
116
118
  def average_age_for(issues_or_pulls)
117
119
  return nil if issues_or_pulls.empty?
118
120
 
119
- ages = issues_or_pulls.map {|iop| time_ago_in_seconds(iop['created_at'])}
121
+ ages = issues_or_pulls.map { |iop| time_ago_in_seconds(iop['created_at']) }
120
122
  raw_average = ages.reduce(:+) / ages.length
121
123
 
122
124
  seconds_in_a_year = 31_556_926
@@ -140,24 +142,25 @@ class HowIs
140
142
  [months, "month"],
141
143
  [weeks, "week"],
142
144
  [days, "day"],
143
- ].reject {|(v, k)| v == 0}.map{ |(v,k)|
144
- k = k + 's' if v != 1
145
+ ].reject { |(v, _)| v == 0 }.map { |(v, k)|
146
+ k += 's' if v != 1
145
147
  [v, k]
146
148
  }
147
149
 
148
- most_significant = values[0, 2].map {|x| x.join(" ")}
150
+ most_significant = values[0, 2].map { |x| x.join(" ") }
149
151
 
150
- if most_significant.length < 2
151
- value = most_significant.first
152
- else
153
- value = most_significant.join(" and ")
154
- end
152
+ value =
153
+ if most_significant.length < 2
154
+ most_significant.first
155
+ else
156
+ most_significant.join(" and ")
157
+ end
155
158
 
156
159
  "approximately #{value}"
157
160
  end
158
161
 
159
162
  def sort_iops_by_created_at(issues_or_pulls)
160
- issues_or_pulls.sort_by {|x| DateTime.parse(x['created_at']) }
163
+ issues_or_pulls.sort_by { |x| DateTime.parse(x['created_at']) }
161
164
  end
162
165
 
163
166
  # Given an Array of issues or pulls, return the oldest.
@@ -181,15 +184,16 @@ class HowIs
181
184
  DateTime.parse(issue_or_pull['created_at'])
182
185
  end
183
186
 
184
- private
187
+ private
188
+
185
189
  # Takes an Array of labels, and returns amodified list that includes links
186
190
  # to each label.
187
191
  def with_label_links(labels, repository)
188
- labels.map do |label, num_issues|
192
+ labels.map { |label, num_issues|
189
193
  label_link = "https://github.com/#{repository}/issues?q=" + CGI.escape("is:open is:issue label:\"#{label}\"")
190
194
 
191
195
  [label, {'link' => label_link, 'total' => num_issues}]
192
- end.to_h
196
+ }.to_h
193
197
  end
194
198
 
195
199
  # Returns how many seconds ago a date (as a String) was.
data/lib/how_is/cli.rb CHANGED
@@ -1,8 +1,10 @@
1
+ # NOPE THIS IS BROKEN // frozen_string_literal: // true
2
+
1
3
  require "how_is"
2
4
  require "slop"
3
5
 
4
6
  class HowIs::CLI
5
- DEFAULT_REPORT_FILE = "report.#{HowIs::DEFAULT_FORMAT}"
7
+ DEFAULT_REPORT_FILE = "report.#{HowIs::DEFAULT_FORMAT}".freeze
6
8
 
7
9
  # Parent class of all exceptions raised in HowIs::CLI.
8
10
  class OptionsError < StandardError
@@ -44,6 +46,14 @@ class HowIs::CLI
44
46
  opts.separator ""
45
47
  opts.separator "Options:"
46
48
 
49
+ # The extra spaces make this a lot easier to comprehend, so we don't want
50
+ # RuboCop to complain about them.
51
+ #
52
+ # Same for line length.
53
+ #
54
+ # rubocop:disable Style/SpaceBeforeFirstArg
55
+ # rubocop:disable Metrics/LineLength
56
+
47
57
  # Allowed arguments:
48
58
  opts.bool "-h", "--help", "Print help text"
49
59
  opts.string "--config", "YAML config file, used to generate a group of reports"
@@ -51,6 +61,9 @@ class HowIs::CLI
51
61
  opts.string "--report", "output file for the report (valid extensions: #{HowIs.supported_formats.join(', ')}; default: #{DEFAULT_REPORT_FILE})"
52
62
  opts.bool "-v", "--version", "prints the version"
53
63
 
64
+ # rubocop:enable Style/SpaceBeforeFirstArg
65
+ # rubocop:enable Metrics/LineLength
66
+
54
67
  # Parse the arguments.
55
68
  parser = Slop::Parser.new(opts)
56
69
  result = parser.parse(argv)
@@ -1,59 +1,67 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'contracts'
2
4
  require 'github_api'
3
5
  require 'how_is/pulse'
4
6
 
5
7
  ##
6
8
  # Fetches data from GitHub.
7
- class HowIs::Fetcher
8
- include Contracts::Core
9
-
10
- ##
11
- # Standardized representation for fetcher results.
12
- #
13
- # Implemented as a class instead of passing around a Hash so that it can
14
- # be more easily referenced by Contracts.
15
- class Results < Struct.new(:repository, :issues, :pulls, :pulse)
9
+ class HowIs
10
+ class Fetcher
16
11
  include Contracts::Core
17
12
 
18
- Contract String, C::ArrayOf[Hash], C::ArrayOf[Hash], String => nil
19
- def initialize(repository, issues, pulls, pulse)
20
- super(repository, issues, pulls, pulse)
13
+ ##
14
+ # Standardized representation for fetcher results.
15
+ #
16
+ # Implemented as a class instead of passing around a Hash so that it can
17
+ # be more easily referenced by Contracts.
18
+ class Results < Struct.new(:repository, :issues, :pulls, :pulse)
19
+ include Contracts::Core
20
+
21
+ Contract String, C::ArrayOf[Hash], C::ArrayOf[Hash], String => nil
22
+ def initialize(repository, issues, pulls, pulse)
23
+ super(repository, issues, pulls, pulse)
24
+ end
25
+
26
+ # Struct defines #to_h, but not #to_hash, so we alias them.
27
+ alias_method :to_hash, :to_h
21
28
  end
22
29
 
23
- # Struct defines #to_h, but not #to_hash, so we alias them.
24
- alias_method :to_hash, :to_h
25
- end
30
+ ##
31
+ # Fetches repository information from GitHub and returns a Results object.
32
+ Contract String,
33
+ C::Or[C::RespondTo[:issues, :pulls], nil],
34
+ C::Or[C::RespondTo[:html_summary], nil] => Results
35
+ def call(repository,
36
+ github = nil,
37
+ pulse = nil)
38
+ github ||= Github.new(auto_pagination: true)
39
+ pulse ||= HowIs::Pulse.new(repository)
40
+ user, repo = repository.split('/', 2)
26
41
 
42
+ unless user && repo
43
+ raise HowIs::CLI::OptionsError, 'To generate a report from GitHub, ' \
44
+ 'provide the repository ' \
45
+ 'username/project. Quitting!'
46
+ end
27
47
 
28
- ##
29
- # Fetches repository information from GitHub and returns a Results object.
30
- Contract String,
31
- C::Or[C::RespondTo[:issues, :pulls], nil],
32
- C::Or[C::RespondTo[:html_summary], nil] => Results
33
- def call(repository,
34
- github = nil,
35
- pulse = nil)
36
- github ||= Github.new(auto_pagination: true)
37
- pulse ||= HowIs::Pulse.new(repository)
38
- user, repo = repository.split('/', 2)
39
- raise HowIs::CLI::OptionsError, 'To generate a report from GitHub, ' \
40
- 'provide the repository username/project. ' \
41
- 'Quitting!' unless user && repo
42
- issues = github.issues.list user: user, repo: repo
43
- pulls = github.pulls.list user: user, repo: repo
44
-
45
- summary = pulse.html_summary
46
-
47
- Results.new(
48
- repository,
49
- obj_to_array_of_hashes(issues),
50
- obj_to_array_of_hashes(pulls),
51
- summary,
52
- )
53
- end
48
+ issues = github.issues.list user: user, repo: repo
49
+ pulls = github.pulls.list user: user, repo: repo
54
50
 
55
- private
56
- def obj_to_array_of_hashes(object)
57
- object.to_a.map(&:to_h)
51
+ summary = pulse.html_summary
52
+
53
+ Results.new(
54
+ repository,
55
+ obj_to_array_of_hashes(issues),
56
+ obj_to_array_of_hashes(pulls),
57
+ summary
58
+ )
59
+ end
60
+
61
+ private
62
+
63
+ def obj_to_array_of_hashes(object)
64
+ object.to_a.map(&:to_h)
65
+ end
58
66
  end
59
67
  end
data/lib/how_is/pulse.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'tessellator/fetcher'
2
4
 
3
5
  class HowIs
@@ -19,7 +21,7 @@ class HowIs
19
21
 
20
22
  # Gets the HTML Pulse summary.
21
23
  def html_summary
22
- parts =
24
+ parts =
23
25
  @pulse_page_response.body
24
26
  .split('<div class="section diffstat-summary">')
25
27
 
@@ -34,10 +36,11 @@ class HowIs
34
36
  .strip
35
37
  end
36
38
 
37
- private
39
+ private
40
+
38
41
  # Fetch Pulse page from GitHub for scraping.
39
- def fetch_pulse!(repository, period='monthly')
40
- Tessellator::Fetcher.new.call('get', "https://github.com/#{repository}/pulse/#{period}")
42
+ def fetch_pulse!(repository)
43
+ Tessellator::Fetcher.new.call('get', "https://github.com/#{repository}/pulse/monthly")
41
44
  end
42
45
  end
43
46
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
 
3
5
  class HowIs
@@ -27,7 +29,7 @@ class HowIs
27
29
  issue_or_pr_summary "issue", "issue"
28
30
 
29
31
  header "Issues Per Label"
30
- issues_per_label = analysis.issues_with_label.to_a.sort_by { |(k, v)| v['total'].to_i }.reverse
32
+ issues_per_label = analysis.issues_with_label.to_a.sort_by { |(_, v)| v['total'].to_i }.reverse
31
33
  issues_per_label.map! do |label, hash|
32
34
  [label, hash['total'], hash['link']]
33
35
  end
@@ -50,37 +52,37 @@ class HowIs
50
52
 
51
53
  ##
52
54
  # Appends a title to the report.
53
- def title(_text)
55
+ def title(_content)
54
56
  raise NotImplementedError
55
57
  end
56
58
 
57
59
  ##
58
60
  # Appends a header to the report.
59
- def header(_text)
61
+ def header(_content)
60
62
  raise NotImplementedError
61
63
  end
62
64
 
63
65
  ##
64
66
  # Appends a line of text to the report.
65
- def text(_text)
67
+ def text(_content)
66
68
  raise NotImplementedError
67
69
  end
68
70
 
69
71
  ##
70
72
  # Appends a link to the report.
71
- def link(_text, url)
73
+ def link(_content, _url)
72
74
  raise NotImplementedError
73
75
  end
74
76
 
75
77
  ##
76
78
  # Appends an unordered list to the report.
77
- def unordered_list(arr)
79
+ def unordered_list(_arr)
78
80
  raise NotImplementedError
79
81
  end
80
82
 
81
83
  ##
82
84
  # Appends a horizontal bar graph to the report.
83
- def horizontal_bar_graph(data)
85
+ def horizontal_bar_graph(_data)
84
86
  raise NotImplementedError
85
87
  end
86
88
 
@@ -94,26 +96,27 @@ class HowIs
94
96
  # Exports a report to a file.
95
97
  #
96
98
  # NOTE: May be removed in the future.
97
- def export_file(file)
99
+ def export_file(_file)
98
100
  raise NotImplementedError
99
101
  end
100
102
 
101
103
  def to_h
102
104
  analysis.to_h
103
105
  end
104
- alias :to_hash :to_h
106
+ alias_method :to_hash, :to_h
105
107
 
106
108
  def to_json
107
109
  JSON.pretty_generate(to_h)
108
110
  end
109
111
 
110
112
  private
113
+
111
114
  def pluralize(text, number)
112
- number == 1 ? text : "#{text}s"
115
+ (number == 1) ? text : "#{text}s"
113
116
  end
114
117
 
115
118
  def are_is(number)
116
- number == 1 ? "is" : "are"
119
+ (number == 1) ? "is" : "are"
117
120
  end
118
121
 
119
122
  def issue_or_pr_summary(type, type_label)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'cgi'
2
4
  require 'how_is/report/base_report'
3
5
 
@@ -7,21 +9,21 @@ class HowIs
7
9
  :html
8
10
  end
9
11
 
10
- def title(_text)
11
- @title = _text
12
- @r += "\n<h1>#{_text}</h1>\n"
12
+ def title(content)
13
+ @title = content
14
+ @r += "\n<h1>#{content}</h1>\n"
13
15
  end
14
16
 
15
- def header(_text)
16
- @r += "\n<h2>#{_text}</h2>\n"
17
+ def header(content)
18
+ @r += "\n<h2>#{content}</h2>\n"
17
19
  end
18
20
 
19
- def link(_text, url)
20
- %Q[<a href="#{url}">#{_text}</a>]
21
+ def link(content, url)
22
+ %[<a href="#{url}">#{content}</a>]
21
23
  end
22
24
 
23
- def text(_text)
24
- @r += "<p>#{_text}</p>\n"
25
+ def text(content)
26
+ @r += "<p>#{content}</p>\n"
25
27
  end
26
28
 
27
29
  def unordered_list(arr)
@@ -46,13 +48,14 @@ class HowIs
46
48
 
47
49
  @r += "<table class=\"horizontal-bar-graph\">\n"
48
50
  data.each do |row|
49
- percentage = get_percentage.(row[1])
51
+ percentage = get_percentage.call(row[1])
50
52
 
51
- if row[2]
52
- label_text = link(row[0], row[2])
53
- else
54
- label_text = row[0]
55
- end
53
+ label_text =
54
+ if row[2]
55
+ link(row[0], row[2])
56
+ else
57
+ row[0]
58
+ end
56
59
 
57
60
  @r += <<-EOF
58
61
  <tr>
@@ -74,35 +77,35 @@ class HowIs
74
77
  report = export
75
78
 
76
79
  File.open(file, 'w') do |f|
77
- f.puts <<-EOF
78
- <!DOCTYPE html>
79
- <html>
80
- <head>
81
- <title>#{@title}</title>
82
- <style>
83
- body { font: sans-serif; }
84
- main {
85
- max-width: 600px;
86
- max-width: 72ch;
87
- margin: auto;
88
- }
89
-
90
- .horizontal-bar-graph {
91
- position: relative;
92
- width: 100%;
93
- }
94
- .horizontal-bar-graph .fill {
95
- display: inline-block;
96
- background: #CCC;
97
- }
98
- </style>
99
- </head>
100
- <body>
101
- <main>
102
- #{report}
103
- </main>
104
- </body>
105
- </html>
80
+ f.puts <<~EOF
81
+ <!DOCTYPE html>
82
+ <html>
83
+ <head>
84
+ <title>#{@title}</title>
85
+ <style>
86
+ body { font: sans-serif; }
87
+ main {
88
+ max-width: 600px;
89
+ max-width: 72ch;
90
+ margin: auto;
91
+ }
92
+
93
+ .horizontal-bar-graph {
94
+ position: relative;
95
+ width: 100%;
96
+ }
97
+ .horizontal-bar-graph .fill {
98
+ display: inline-block;
99
+ background: #CCC;
100
+ }
101
+ </style>
102
+ </head>
103
+ <body>
104
+ <main>
105
+ #{report}
106
+ </main>
107
+ </body>
108
+ </html>
106
109
  EOF
107
110
  end
108
111
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'how_is/report/base_report'
2
4
 
3
5
  class HowIs
data/lib/how_is/report.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'date'
2
4
  require "pathname"
3
5
 
@@ -63,7 +65,6 @@ class HowIs
63
65
  report.public_send("to_#{report_format}")
64
66
  end
65
67
 
66
- private
67
68
  # Given a format name (+format+), returns the corresponding <blah>Report
68
69
  # class.
69
70
  def self.get_report_class(format)
@@ -73,5 +74,6 @@ class HowIs
73
74
 
74
75
  HowIs.const_get(class_name)
75
76
  end
77
+ private_class_method :get_report_class
76
78
  end
77
79
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class HowIs
2
- VERSION = "18.0.3"
4
+ VERSION = "18.0.4"
3
5
  end
data/lib/how_is.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'how_is/version'
2
4
  require 'contracts'
3
5
  require 'cacert'
@@ -54,7 +56,7 @@ class HowIs
54
56
  # @return [HowIs] A HowIs object that can be used for generating other
55
57
  # reports, treating the JSON report as a cache.
56
58
  def self.from_json(json)
57
- self.from_hash(JSON.parse(json))
59
+ from_hash(JSON.parse(json))
58
60
  end
59
61
 
60
62
  ##
@@ -67,7 +69,7 @@ class HowIs
67
69
  def self.from_hash(data)
68
70
  analysis = HowIs::Analyzer.from_hash(data)
69
71
 
70
- self.new(analysis.repository, analysis)
72
+ new(analysis.repository, analysis)
71
73
  end
72
74
 
73
75
  ##
@@ -77,7 +79,7 @@ class HowIs
77
79
  # generate.
78
80
  def self.supported_formats
79
81
  report_constants = HowIs.constants.grep(/.Report/) - [:BaseReport]
80
- report_constants.map {|x| x.to_s.split('Report').first.downcase }
82
+ report_constants.map { |x| x.to_s.split('Report').first.downcase }
81
83
  end
82
84
 
83
85
  ##
@@ -93,6 +95,8 @@ class HowIs
93
95
 
94
96
  # Generate an analysis.
95
97
  # TODO: This may make more sense as Analysis.new().
98
+ # TODO: Nothing overrides +fetcher+ and +analyzer+. Remove ability to do so.
99
+ # FIXME: THIS CODE AND EVERYTHING ASSOCIATED WITH IT IS A FUCKING ATROCITY.
96
100
  Contract C::KeywordArgs[repository: String,
97
101
  fetcher: C::Optional[Class],
98
102
  analyzer: C::Optional[Class],
@@ -119,7 +123,9 @@ class HowIs
119
123
  report_data = convert_keys(report_data, :to_sym)
120
124
 
121
125
  frontmatter = frontmatter.map { |k, v|
122
- v = v % report_data
126
+ # Sometimes report_data has unused keys, which generates a warning, but
127
+ # we're okay with it.
128
+ v = silence_warnings { v % report_data }
123
129
 
124
130
  [k, v]
125
131
  }.to_h
@@ -142,7 +148,6 @@ class HowIs
142
148
  report_class ||= HowIs::Report
143
149
 
144
150
  date = Date.strptime(Time.now.to_i.to_s, '%s')
145
- date_string = date.strftime('%Y-%m-%d')
146
151
  friendly_date = date.strftime('%B %d, %y')
147
152
 
148
153
  analysis = HowIs.generate_analysis(repository: config['repository'], github: github)
@@ -156,7 +161,9 @@ class HowIs
156
161
  generated_reports = {}
157
162
 
158
163
  config['reports'].map do |format, report_config|
159
- filename = report_config['filename'] % report_data
164
+ # Sometimes report_data has unused keys, which generates a warning, but
165
+ # we're okay with it.
166
+ filename = silence_warnings { report_config['filename'] % report_data }
160
167
  file = File.join(report_config['directory'], filename)
161
168
 
162
169
  report = report_class.export(analysis, format)
@@ -187,11 +194,24 @@ class HowIs
187
194
  str.string
188
195
  end
189
196
 
190
- private
191
197
  # convert_keys({'foo' => 'bar'}, :to_sym)
192
198
  # => {:foo => 'bar'}
193
199
  def self.convert_keys(data, method_name)
194
- data.map {|k, v| [k.send(method_name), v]}.to_h
200
+ data.map { |k, v| [k.send(method_name), v] }.to_h
195
201
  end
202
+ private_class_method :convert_keys
196
203
 
204
+ def self.silence_warnings(&block)
205
+ with_warnings(nil, &block)
206
+ end
207
+ private_class_method :silence_warnings
208
+
209
+ def self.with_warnings(flag, &_block)
210
+ old_verbose = $VERBOSE
211
+ $VERBOSE = flag
212
+ yield
213
+ ensure
214
+ $VERBOSE = old_verbose
215
+ end
216
+ private_class_method :with_warnings
197
217
  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: 18.0.3
4
+ version: 18.0.4
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: 2017-05-25 00:00:00.000000000 Z
11
+ date: 2017-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: github_api
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.14.5
19
+ version: 0.17.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.14.5
26
+ version: 0.17.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: contracts
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.14.0
33
+ version: 0.16.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: 0.14.0
40
+ version: 0.16.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: slop
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +150,20 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: 0.47.0
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: 0.47.0
153
167
  description:
154
168
  email:
155
169
  - me@duckie.co
@@ -166,6 +180,7 @@ files:
166
180
  - CHANGELOG.md
167
181
  - CODE_OF_CONDUCT.md
168
182
  - Gemfile
183
+ - Gemfile.lock
169
184
  - ISSUES.md
170
185
  - LICENSE.txt
171
186
  - README.md
@@ -211,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
211
226
  version: '0'
212
227
  requirements: []
213
228
  rubyforge_project:
214
- rubygems_version: 2.6.8
229
+ rubygems_version: 2.6.12
215
230
  signing_key:
216
231
  specification_version: 4
217
232
  summary: Quantify the health of a GitHub repository.