how_is 18.0.3 → 18.0.4

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
- 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.