how_is 13.0.0 → 14.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -1
- data/README.md +7 -12
- data/exe/how_is +0 -1
- data/fixtures/vcr_cassettes/how-is-from-config-frontmatter.yml +1299 -0
- data/lib/how_is/analyzer.rb +2 -0
- data/lib/how_is/cli.rb +88 -5
- data/lib/how_is/fetcher.rb +15 -7
- data/lib/how_is/report/base_report.rb +1 -10
- data/lib/how_is/report/html.rb +0 -4
- data/lib/how_is/report.rb +0 -1
- data/lib/how_is/version.rb +1 -1
- metadata +2 -2
- data/lib/how_is/cli/parser.rb +0 -94
data/lib/how_is/analyzer.rb
CHANGED
data/lib/how_is/cli.rb
CHANGED
@@ -1,10 +1,93 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "how_is"
|
4
|
+
require "slop"
|
5
5
|
|
6
6
|
class HowIs::CLI
|
7
|
-
|
7
|
+
DEFAULT_REPORT_FILE = "report.#{HowIs::DEFAULT_FORMAT}"
|
8
|
+
|
9
|
+
class OptionsError < StandardError
|
10
|
+
end
|
11
|
+
|
12
|
+
class InvalidOutputFileError < OptionsError
|
13
|
+
end
|
14
|
+
|
15
|
+
class InvalidInputFileError < OptionsError
|
16
|
+
end
|
17
|
+
|
18
|
+
class NoRepositoryError < OptionsError
|
19
|
+
end
|
20
|
+
|
21
|
+
class Parser
|
22
|
+
attr_reader :opts
|
23
|
+
|
24
|
+
# Parses +argv+ to generate an options Hash to control the behavior of
|
25
|
+
# the library.
|
26
|
+
def call(argv)
|
27
|
+
opts = Slop::Options.new
|
28
|
+
opts.banner =
|
29
|
+
<<-EOF.gsub(/ *\| ?/, '')
|
30
|
+
| Usage: how_is REPOSITORY [--report REPORT_FILE] [--from JSON_FILE]
|
31
|
+
| how_is --config CONFIG_FILE
|
32
|
+
|
|
33
|
+
| Where REPOSITORY is <GitHub username or org>/<repository name>.
|
34
|
+
| CONFIG_FILE defaults to how_is.yml.
|
35
|
+
|
|
36
|
+
| E.g., if you wanted to check https://github.com/how-is/how_is,
|
37
|
+
| you'd run `how_is how-is/how_is`.
|
38
|
+
|
|
39
|
+
EOF
|
40
|
+
|
41
|
+
opts.separator ""
|
42
|
+
opts.separator "Options:"
|
43
|
+
|
44
|
+
opts.bool "-h", "--help", "Print help text"
|
45
|
+
opts.string "--config", "YAML config file, used to generate a group of reports"
|
46
|
+
opts.string "--from", "JSON report file, used instead of fetching the data again"
|
47
|
+
opts.string "--report", "output file for the report (valid extensions: #{HowIs.supported_formats.join(', ')}; default: #{DEFAULT_REPORT_FILE})"
|
48
|
+
opts.bool "-v", "--version", "prints the version"
|
49
|
+
|
50
|
+
parser = Slop::Parser.new(opts)
|
51
|
+
result = parser.parse(argv)
|
52
|
+
options = result.to_hash
|
53
|
+
arguments = result.arguments
|
54
|
+
|
55
|
+
options[:report] ||= DEFAULT_REPORT_FILE
|
56
|
+
|
57
|
+
# The following are only useful if they're not nil or false.
|
58
|
+
# Removing them here simplifies contracts and keyword args for other APIs.
|
59
|
+
options.delete(:config) unless options[:config]
|
60
|
+
options.delete(:help) unless options[:help]
|
61
|
+
options.delete(:version) unless options[:version]
|
62
|
+
|
63
|
+
# Raise an exception if the file can't be exported.
|
64
|
+
unless HowIs.can_export_to?(options[:report])
|
65
|
+
raise InvalidOutputFileError, "Invalid file: #{options[:report_file]}. Supported formats: #{HowIs.supported_formats.join(', ')}"
|
66
|
+
end
|
67
|
+
|
68
|
+
unless options[:config]
|
69
|
+
# If we pass --config, other options (excluding --help and --version)
|
70
|
+
# are ignored. As such, everything in this `unless` block is irrelevant.
|
71
|
+
|
72
|
+
if options[:from]
|
73
|
+
raise InvalidInputFileError, "No such file: #{options[:from]}" unless File.file?(options[:from])
|
8
74
|
|
75
|
+
# Opening the file here is a bit gross, but I couldn't find a better
|
76
|
+
# way to do it. -@duckinator
|
77
|
+
options[:repository] = JSON.parse(open(options[:from_file]).read)['repository']
|
78
|
+
raise InvalidInputFileError, "Invalid JSON report file." unless options[:repository]
|
79
|
+
elsif argv.length >= 1
|
80
|
+
options[:repository] = argv.delete_at(0)
|
81
|
+
else
|
82
|
+
raise NoRepositoryError, "No repository specified."
|
83
|
+
end
|
84
|
+
end
|
9
85
|
|
86
|
+
{
|
87
|
+
opts: opts,
|
88
|
+
options: options,
|
89
|
+
arguments: arguments,
|
90
|
+
}
|
91
|
+
end
|
92
|
+
end
|
10
93
|
end
|
data/lib/how_is/fetcher.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'contracts'
|
2
2
|
require 'github_api'
|
3
|
+
require 'how_is/pulse'
|
3
4
|
|
4
5
|
##
|
5
6
|
# Fetches data from GitHub.
|
@@ -11,12 +12,12 @@ class HowIs::Fetcher
|
|
11
12
|
#
|
12
13
|
# Implemented as a class instead of passing around a Hash so that it can
|
13
14
|
# be more easily referenced by Contracts.
|
14
|
-
class Results < Struct.new(:repository, :issues, :pulls)
|
15
|
+
class Results < Struct.new(:repository, :issues, :pulls, :pulse)
|
15
16
|
include Contracts::Core
|
16
17
|
|
17
|
-
Contract String, C::ArrayOf[Hash], C::ArrayOf[Hash] => nil
|
18
|
-
def initialize(repository, issues, pulls)
|
19
|
-
super(repository, issues, pulls)
|
18
|
+
Contract String, C::ArrayOf[Hash], C::ArrayOf[Hash], String => nil
|
19
|
+
def initialize(repository, issues, pulls, pulse)
|
20
|
+
super(repository, issues, pulls, pulse)
|
20
21
|
end
|
21
22
|
|
22
23
|
# Struct defines #to_h, but not #to_hash, so we alias them.
|
@@ -26,10 +27,14 @@ class HowIs::Fetcher
|
|
26
27
|
|
27
28
|
##
|
28
29
|
# Fetches repository information from GitHub and returns a Results object.
|
29
|
-
Contract String,
|
30
|
+
Contract String,
|
31
|
+
C::Or[C::RespondTo[:issues, :pulls], nil],
|
32
|
+
C::Or[C::RespondTo[:html_summary], nil] => Results
|
30
33
|
def call(repository,
|
31
|
-
github = nil
|
34
|
+
github = nil,
|
35
|
+
pulse = nil)
|
32
36
|
github ||= Github.new(auto_pagination: true)
|
37
|
+
pulse ||= HowIs::Pulse.new(repository)
|
33
38
|
user, repo = repository.split('/', 2)
|
34
39
|
raise HowIs::CLI::OptionsError, 'To generate a report from GitHub, ' \
|
35
40
|
'provide the repository username/project. ' \
|
@@ -37,10 +42,13 @@ class HowIs::Fetcher
|
|
37
42
|
issues = github.issues.list user: user, repo: repo
|
38
43
|
pulls = github.pulls.list user: user, repo: repo
|
39
44
|
|
45
|
+
summary = pulse.html_summary
|
46
|
+
|
40
47
|
Results.new(
|
41
48
|
repository,
|
42
49
|
obj_to_array_of_hashes(issues),
|
43
|
-
obj_to_array_of_hashes(pulls)
|
50
|
+
obj_to_array_of_hashes(pulls),
|
51
|
+
summary,
|
44
52
|
)
|
45
53
|
end
|
46
54
|
|
@@ -18,7 +18,7 @@ class HowIs
|
|
18
18
|
# TODO: Stop pretending everyone who runs how_is is in UTC.
|
19
19
|
text "Monthly report, ending on #{DateTime.now.new_offset(0).strftime('%B %e, %Y')}."
|
20
20
|
|
21
|
-
text
|
21
|
+
text analysis.pulse
|
22
22
|
|
23
23
|
header "Pull Requests"
|
24
24
|
issue_or_pr_summary "pull", "pull request"
|
@@ -68,10 +68,6 @@ class HowIs
|
|
68
68
|
raise NotImplementedError
|
69
69
|
end
|
70
70
|
|
71
|
-
def monthly_summary
|
72
|
-
raise NotImplementedError
|
73
|
-
end
|
74
|
-
|
75
71
|
def export
|
76
72
|
raise NotImplementedError
|
77
73
|
end
|
@@ -90,11 +86,6 @@ class HowIs
|
|
90
86
|
end
|
91
87
|
|
92
88
|
private
|
93
|
-
def github_pulse_summary
|
94
|
-
@pulse ||= HowIs::Pulse.new(analysis.repository)
|
95
|
-
@pulse.send("#{format}_summary")
|
96
|
-
end
|
97
|
-
|
98
89
|
def pluralize(text, number)
|
99
90
|
number == 1 ? text : "#{text}s"
|
100
91
|
end
|
data/lib/how_is/report/html.rb
CHANGED
data/lib/how_is/report.rb
CHANGED
data/lib/how_is/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: how_is
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 14.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ellen Marie Dash
|
@@ -189,12 +189,12 @@ files:
|
|
189
189
|
- exe/how_is
|
190
190
|
- fixtures/vcr_cassettes/how-is-example-empty-repository.yml
|
191
191
|
- fixtures/vcr_cassettes/how-is-example-repository.yml
|
192
|
+
- fixtures/vcr_cassettes/how-is-from-config-frontmatter.yml
|
192
193
|
- fixtures/vcr_cassettes/how-is-with-config-file.yml
|
193
194
|
- how_is.gemspec
|
194
195
|
- lib/how_is.rb
|
195
196
|
- lib/how_is/analyzer.rb
|
196
197
|
- lib/how_is/cli.rb
|
197
|
-
- lib/how_is/cli/parser.rb
|
198
198
|
- lib/how_is/fetcher.rb
|
199
199
|
- lib/how_is/pulse.rb
|
200
200
|
- lib/how_is/report.rb
|
data/lib/how_is/cli/parser.rb
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "how_is"
|
4
|
-
require "how_is/cli"
|
5
|
-
require "slop"
|
6
|
-
|
7
|
-
class HowIs::CLI
|
8
|
-
DEFAULT_REPORT_FILE = "report.#{HowIs::DEFAULT_FORMAT}"
|
9
|
-
|
10
|
-
class OptionsError < StandardError
|
11
|
-
end
|
12
|
-
|
13
|
-
class InvalidOutputFileError < OptionsError
|
14
|
-
end
|
15
|
-
|
16
|
-
class InvalidInputFileError < OptionsError
|
17
|
-
end
|
18
|
-
|
19
|
-
class NoRepositoryError < OptionsError
|
20
|
-
end
|
21
|
-
|
22
|
-
class Parser
|
23
|
-
attr_reader :opts
|
24
|
-
|
25
|
-
# Parses +argv+ to generate an options Hash to control the behavior of
|
26
|
-
# the library.
|
27
|
-
def call(argv)
|
28
|
-
opts = Slop::Options.new
|
29
|
-
opts.banner =
|
30
|
-
<<-EOF.gsub(/ *\| ?/, '')
|
31
|
-
| Usage: how_is REPOSITORY [--report REPORT_FILE] [--from JSON_FILE]
|
32
|
-
| how_is --config CONFIG_FILE
|
33
|
-
|
|
34
|
-
| Where REPOSITORY is <GitHub username or org>/<repository name>.
|
35
|
-
| CONFIG_FILE defaults to how_is.yml.
|
36
|
-
|
|
37
|
-
| E.g., if you wanted to check https://github.com/how-is/how_is,
|
38
|
-
| you'd run `how_is how-is/how_is`.
|
39
|
-
|
|
40
|
-
EOF
|
41
|
-
|
42
|
-
opts.separator ""
|
43
|
-
opts.separator "Options:"
|
44
|
-
|
45
|
-
opts.bool "-h", "--help", "Print help text"
|
46
|
-
opts.string "--config", "YAML config file, used to generate a group of reports"
|
47
|
-
opts.string "--from", "JSON report file, used instead of fetching the data again"
|
48
|
-
opts.string "--report", "output file for the report (valid extensions: #{HowIs.supported_formats.join(', ')}; default: #{DEFAULT_REPORT_FILE})"
|
49
|
-
opts.bool "-v", "--version", "prints the version"
|
50
|
-
|
51
|
-
parser = Slop::Parser.new(opts)
|
52
|
-
result = parser.parse(argv)
|
53
|
-
options = result.to_hash
|
54
|
-
arguments = result.arguments
|
55
|
-
|
56
|
-
options[:report] ||= DEFAULT_REPORT_FILE
|
57
|
-
|
58
|
-
# The following are only useful if they're not nil or false.
|
59
|
-
# Removing them here simplifies contracts and keyword args for other APIs.
|
60
|
-
options.delete(:config) unless options[:config]
|
61
|
-
options.delete(:help) unless options[:help]
|
62
|
-
options.delete(:version) unless options[:version]
|
63
|
-
|
64
|
-
# Raise an exception if the file can't be exported.
|
65
|
-
unless HowIs.can_export_to?(options[:report])
|
66
|
-
raise InvalidOutputFileError, "Invalid file: #{options[:report_file]}. Supported formats: #{HowIs.supported_formats.join(', ')}"
|
67
|
-
end
|
68
|
-
|
69
|
-
unless options[:config]
|
70
|
-
# If we pass --config, other options (excluding --help and --version)
|
71
|
-
# are ignored. As such, everything in this `unless` block is irrelevant.
|
72
|
-
|
73
|
-
if options[:from]
|
74
|
-
raise InvalidInputFileError, "No such file: #{options[:from]}" unless File.file?(options[:from])
|
75
|
-
|
76
|
-
# Opening the file here is a bit gross, but I couldn't find a better
|
77
|
-
# way to do it. -@duckinator
|
78
|
-
options[:repository] = JSON.parse(open(options[:from_file]).read)['repository']
|
79
|
-
raise InvalidInputFileError, "Invalid JSON report file." unless options[:repository]
|
80
|
-
elsif argv.length >= 1
|
81
|
-
options[:repository] = argv.delete_at(0)
|
82
|
-
else
|
83
|
-
raise NoRepositoryError, "No repository specified."
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
{
|
88
|
-
opts: opts,
|
89
|
-
options: options,
|
90
|
-
arguments: arguments,
|
91
|
-
}
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|