how_is 13.0.0 → 14.0.0
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 +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
|