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 +5 -5
- data/.gitignore +1 -1
- data/.rubocop.yml +36 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +17 -0
- data/Gemfile +2 -8
- data/Gemfile.lock +110 -0
- data/README.md +0 -5
- data/Rakefile +9 -4
- data/exe/how_is +3 -2
- data/how_is.gemspec +3 -2
- data/lib/how_is/analyzer.rb +20 -16
- data/lib/how_is/cli.rb +14 -1
- data/lib/how_is/fetcher.rb +52 -44
- data/lib/how_is/pulse.rb +7 -4
- data/lib/how_is/report/base_report.rb +14 -11
- data/lib/how_is/report/html.rb +47 -44
- data/lib/how_is/report/json.rb +2 -0
- data/lib/how_is/report.rb +3 -1
- data/lib/how_is/version.rb +3 -1
- data/lib/how_is.rb +28 -8
- metadata +22 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: aa512f40b28b33221fb83a6db55d83efe39e5b5c3f5a5160a5eabb1441a58638
|
|
4
|
+
data.tar.gz: 4dc0c71bd1a56bb32e29efebbbc7405b21456566b47ae8b4b1fcc8ebafe90cae
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4f2ffd1e34fa07420631add37aa8b084956f58b6b8d67d14ccb4d58942f60a167ad9c7106bd14ce3c53db73498255e1542c2e56559733fccc05dfba157876c46
|
|
7
|
+
data.tar.gz: 40a4bf011b459a31a7ab9e9fedf50b8672f64f8ba3d5e62fa4492260eab05aed27f88b882f87583e128fc2fcf0891508229be723c4d75399dbb43735e0dac9de
|
data/.gitignore
CHANGED
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
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(&
|
|
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.
|
|
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
|
|
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.
|
|
23
|
-
spec.add_runtime_dependency "contracts", "~> 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
|
data/lib/how_is/analyzer.rb
CHANGED
|
@@ -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
|
|
66
|
+
hash = data.map { |k, v|
|
|
65
67
|
v = DateTime.parse(v) if k.end_with?('_date')
|
|
66
68
|
|
|
67
69
|
[k, v]
|
|
68
|
-
|
|
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,
|
|
144
|
-
k
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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)
|
data/lib/how_is/fetcher.rb
CHANGED
|
@@ -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
|
|
8
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
39
|
+
private
|
|
40
|
+
|
|
38
41
|
# Fetch Pulse page from GitHub for scraping.
|
|
39
|
-
def fetch_pulse!(repository
|
|
40
|
-
Tessellator::Fetcher.new.call('get', "https://github.com/#{repository}/pulse
|
|
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 { |(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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)
|
data/lib/how_is/report/html.rb
CHANGED
|
@@ -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(
|
|
11
|
-
@title =
|
|
12
|
-
@r += "\n<h1>#{
|
|
12
|
+
def title(content)
|
|
13
|
+
@title = content
|
|
14
|
+
@r += "\n<h1>#{content}</h1>\n"
|
|
13
15
|
end
|
|
14
16
|
|
|
15
|
-
def header(
|
|
16
|
-
@r += "\n<h2>#{
|
|
17
|
+
def header(content)
|
|
18
|
+
@r += "\n<h2>#{content}</h2>\n"
|
|
17
19
|
end
|
|
18
20
|
|
|
19
|
-
def link(
|
|
20
|
-
%
|
|
21
|
+
def link(content, url)
|
|
22
|
+
%[<a href="#{url}">#{content}</a>]
|
|
21
23
|
end
|
|
22
24
|
|
|
23
|
-
def text(
|
|
24
|
-
@r += "<p>#{
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
|
78
|
-
<!DOCTYPE html>
|
|
79
|
-
<html>
|
|
80
|
-
<head>
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
</head>
|
|
100
|
-
<body>
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
data/lib/how_is/report/json.rb
CHANGED
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
|
data/lib/how_is/version.rb
CHANGED
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|