how_is 10.0.0 → 11.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/CHANGELOG.md +34 -0
- data/README.md +43 -7
- data/fixtures/vcr_cassettes/how_is-example-repository.yml +951 -0
- data/fixtures/vcr_cassettes/how_is-with-config-file.yml +23582 -0
- data/how_is.gemspec +2 -0
- data/lib/how_is/analyzer.rb +21 -0
- data/lib/how_is/cli/parser.rb +22 -15
- data/lib/how_is/cli.rb +6 -0
- data/lib/how_is/fetcher.rb +4 -1
- data/lib/how_is/pulse.rb +10 -2
- data/lib/how_is/report/html.rb +2 -2
- data/lib/how_is/report/json.rb +1 -1
- data/lib/how_is/report.rb +42 -6
- data/lib/how_is/version.rb +1 -1
- data/lib/how_is.rb +11 -1
- data/roadmap.markdown +50 -17
- metadata +34 -6
- data/data/issues.plg +0 -22
- data/lib/how_is/chart.rb +0 -83
- data/lib/how_is/report/pdf.rb +0 -78
data/how_is.gemspec
CHANGED
@@ -35,4 +35,6 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.add_development_dependency "rake", "~> 11.2"
|
36
36
|
spec.add_development_dependency "rspec", "~> 3.5"
|
37
37
|
spec.add_development_dependency "timecop", "~> 0.8.1"
|
38
|
+
spec.add_development_dependency "vcr", "~> 3.0"
|
39
|
+
spec.add_development_dependency "webmock"
|
38
40
|
end
|
data/lib/how_is/analyzer.rb
CHANGED
@@ -12,12 +12,16 @@ module HowIs
|
|
12
12
|
class Analyzer
|
13
13
|
include Contracts::Core
|
14
14
|
|
15
|
+
##
|
16
|
+
# Raised when attempting to export to an unsupported format.
|
15
17
|
class UnsupportedImportFormat < StandardError
|
16
18
|
def initialize(format)
|
17
19
|
super("Unsupported import format: #{format}")
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
23
|
+
##
|
24
|
+
# Generates and returns an analysis.
|
21
25
|
Contract Fetcher::Results, C::KeywordArgs[analysis_class: C::Optional[Class]] => Analysis
|
22
26
|
def call(data, analysis_class: Analysis)
|
23
27
|
issues = data.issues
|
@@ -43,6 +47,8 @@ module HowIs
|
|
43
47
|
)
|
44
48
|
end
|
45
49
|
|
50
|
+
##
|
51
|
+
# Generates an analysis from a JSON report.
|
46
52
|
def from_file(file)
|
47
53
|
extension = file.split('.').last
|
48
54
|
raise UnsupportedImportFormat, extension unless extension == 'json'
|
@@ -82,10 +88,13 @@ module HowIs
|
|
82
88
|
hash
|
83
89
|
end
|
84
90
|
|
91
|
+
# Returns the number of issues with no label.
|
85
92
|
def num_with_no_label(issues)
|
86
93
|
issues.select { |x| x['labels'].empty? }.length
|
87
94
|
end
|
88
95
|
|
96
|
+
# Given an Array of dates, average the timestamps and return the date that
|
97
|
+
# represents.
|
89
98
|
def average_date_for(issues_or_pulls)
|
90
99
|
timestamps = issues_or_pulls.map { |iop| Date.parse(iop['created_at']).strftime('%s').to_i }
|
91
100
|
average_timestamp = timestamps.reduce(:+) / issues_or_pulls.length
|
@@ -94,7 +103,10 @@ module HowIs
|
|
94
103
|
end
|
95
104
|
|
96
105
|
# Given an Array of issues or pulls, return the average age of them.
|
106
|
+
# Returns nil if no issues or pulls are provided.
|
97
107
|
def average_age_for(issues_or_pulls)
|
108
|
+
return nil if issues_or_pulls.empty?
|
109
|
+
|
98
110
|
ages = issues_or_pulls.map {|iop| time_ago_in_seconds(iop['created_at'])}
|
99
111
|
raw_average = ages.reduce(:+) / ages.length
|
100
112
|
|
@@ -136,15 +148,21 @@ module HowIs
|
|
136
148
|
end
|
137
149
|
|
138
150
|
# Given an Array of issues or pulls, return the creation date of the oldest.
|
151
|
+
# Returns nil if no issues or pulls are provided.
|
139
152
|
def oldest_for(issues_or_pulls)
|
153
|
+
return nil if issues_or_pulls.empty?
|
154
|
+
|
140
155
|
issues_or_pulls.sort_by {|x| DateTime.parse(x['created_at']) }.first
|
141
156
|
end
|
142
157
|
|
158
|
+
# Given an issue or PR, returns the date it was created.
|
143
159
|
def date_for(issue_or_pull)
|
144
160
|
DateTime.parse(issue_or_pull['created_at'])
|
145
161
|
end
|
146
162
|
|
147
163
|
private
|
164
|
+
# Takes an Array of labels, and returns amodified list that includes links
|
165
|
+
# to each label.
|
148
166
|
def with_label_links(labels, repository)
|
149
167
|
labels.map do |label, num_issues|
|
150
168
|
label_link = "https://github.com/#{repository}/issues?q=" + CGI.escape("is:open is:issue label:\"#{label}\"")
|
@@ -153,11 +171,14 @@ module HowIs
|
|
153
171
|
end.to_h
|
154
172
|
end
|
155
173
|
|
174
|
+
# Returns how many seconds ago a date (as a String) was.
|
156
175
|
def time_ago_in_seconds(x)
|
157
176
|
DateTime.now.strftime("%s").to_i - DateTime.parse(x).strftime("%s").to_i
|
158
177
|
end
|
159
178
|
|
160
179
|
def issue_or_pull_to_hash(iop)
|
180
|
+
return nil if iop.nil?
|
181
|
+
|
161
182
|
ret = {}
|
162
183
|
|
163
184
|
ret['html_url'] = iop['html_url']
|
data/lib/how_is/cli/parser.rb
CHANGED
@@ -22,14 +22,16 @@ class HowIs::CLI
|
|
22
22
|
class Parser
|
23
23
|
attr_reader :opts
|
24
24
|
|
25
|
+
# Parses +argv+ to generate an options Hash to control the behavior of
|
26
|
+
# the library.
|
25
27
|
def call(argv)
|
26
28
|
opts = Slop::Options.new
|
27
29
|
opts.banner =
|
28
30
|
<<-EOF.gsub(/ *\| ?/, '')
|
29
|
-
| Usage: how_is REPOSITORY [--report REPORT_FILE]
|
31
|
+
| Usage: how_is REPOSITORY [--report REPORT_FILE] [--from JSON_FILE]
|
30
32
|
| how_is --config CONFIG_FILE
|
31
33
|
|
|
32
|
-
| Where REPOSITORY is
|
34
|
+
| Where REPOSITORY is <GitHub username or org>/<repository name>.
|
33
35
|
| CONFIG_FILE defaults to how_is.yml.
|
34
36
|
|
|
35
37
|
| E.g., if you wanted to check https://github.com/how-is/how_is,
|
@@ -53,28 +55,33 @@ class HowIs::CLI
|
|
53
55
|
|
54
56
|
options[:report] ||= DEFAULT_REPORT_FILE
|
55
57
|
|
56
|
-
# The following are only useful if
|
58
|
+
# The following are only useful if they're not nil or false.
|
57
59
|
# Removing them here simplifies contracts and keyword args for other APIs.
|
58
60
|
options.delete(:config) unless options[:config]
|
59
61
|
options.delete(:help) unless options[:help]
|
60
62
|
options.delete(:version) unless options[:version]
|
61
63
|
|
64
|
+
# Raise an exception if the file can't be exported.
|
62
65
|
unless HowIs.can_export_to?(options[:report])
|
63
66
|
raise InvalidOutputFileError, "Invalid file: #{options[:report_file]}. Supported formats: #{HowIs.supported_formats.join(', ')}"
|
64
67
|
end
|
65
68
|
|
66
|
-
|
67
|
-
#
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
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
|
78
85
|
end
|
79
86
|
|
80
87
|
{
|
data/lib/how_is/cli.rb
CHANGED
@@ -28,12 +28,16 @@ class HowIs::CLI
|
|
28
28
|
YAML.dump(frontmatter)
|
29
29
|
end
|
30
30
|
|
31
|
+
##
|
32
|
+
# Generates a series of report files based on a YAML config file.
|
31
33
|
def from_config_file(config_file = nil, **kwargs)
|
32
34
|
config_file ||= DEFAULT_CONFIG_FILE
|
33
35
|
|
34
36
|
from_config(YAML.load_file(config_file), **kwargs)
|
35
37
|
end
|
36
38
|
|
39
|
+
##
|
40
|
+
# Generates a series of report files based on a config Hash.
|
37
41
|
def from_config(config,
|
38
42
|
github: nil,
|
39
43
|
report_class: nil)
|
@@ -67,6 +71,8 @@ class HowIs::CLI
|
|
67
71
|
end
|
68
72
|
end
|
69
73
|
|
74
|
+
# Combine the frontmatter, report data, and raw report into a report with
|
75
|
+
# frontmatter.
|
70
76
|
def build_report(frontmatter, report_data, report)
|
71
77
|
str = StringIO.new
|
72
78
|
|
data/lib/how_is/fetcher.rb
CHANGED
@@ -24,6 +24,8 @@ class HowIs::Fetcher
|
|
24
24
|
end
|
25
25
|
|
26
26
|
|
27
|
+
##
|
28
|
+
# Fetches repository information from GitHub and returns a Results object.
|
27
29
|
Contract String, C::Or[C::RespondTo[:issues, :pulls], nil] => Results
|
28
30
|
def call(repository,
|
29
31
|
github = nil)
|
@@ -39,7 +41,8 @@ class HowIs::Fetcher
|
|
39
41
|
)
|
40
42
|
end
|
41
43
|
|
42
|
-
|
44
|
+
private
|
45
|
+
def obj_to_array_of_hashes(object)
|
43
46
|
object.to_a.map(&:to_h)
|
44
47
|
end
|
45
48
|
end
|
data/lib/how_is/pulse.rb
CHANGED
@@ -14,8 +14,16 @@ module HowIs
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def html_summary
|
17
|
-
|
18
|
-
.
|
17
|
+
parts =
|
18
|
+
@pulse_page_response.body
|
19
|
+
.split('<div class="section diffstat-summary">')
|
20
|
+
|
21
|
+
if parts.length == 1
|
22
|
+
return "There hasn't been any activity on #{@repository} in the last month."
|
23
|
+
end
|
24
|
+
|
25
|
+
parts
|
26
|
+
.last
|
19
27
|
.split('</div>').first
|
20
28
|
.gsub('<a href="/', '<a href="https://github.com/')
|
21
29
|
.strip
|
data/lib/how_is/report/html.rb
CHANGED
@@ -38,7 +38,7 @@ module HowIs
|
|
38
38
|
if row[2]
|
39
39
|
label_text = link(row[0], row[2])
|
40
40
|
else
|
41
|
-
label_text = row[
|
41
|
+
label_text = row[0]
|
42
42
|
end
|
43
43
|
|
44
44
|
@r += <<-EOF
|
@@ -60,7 +60,7 @@ module HowIs
|
|
60
60
|
instance_exec(&block)
|
61
61
|
end
|
62
62
|
|
63
|
-
def
|
63
|
+
def export_file(file, &block)
|
64
64
|
report = export(&block)
|
65
65
|
|
66
66
|
File.open(file, 'w') do |f|
|
data/lib/how_is/report/json.rb
CHANGED
data/lib/how_is/report.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'how_is/pulse'
|
3
|
+
|
1
4
|
module HowIs
|
2
5
|
class UnsupportedExportFormat < StandardError
|
3
6
|
def initialize(format)
|
@@ -27,6 +30,14 @@ module HowIs
|
|
27
30
|
end
|
28
31
|
|
29
32
|
private
|
33
|
+
def pluralize(text, number)
|
34
|
+
number == 1 ? text : "#{text}s"
|
35
|
+
end
|
36
|
+
|
37
|
+
def are_is(number)
|
38
|
+
number == 1 ? "is" : "are"
|
39
|
+
end
|
40
|
+
|
30
41
|
def issue_or_pr_summary(type, type_label)
|
31
42
|
oldest_date_format = "%b %e, %Y"
|
32
43
|
a = analysis
|
@@ -36,20 +47,39 @@ module HowIs
|
|
36
47
|
type_link = a.send("#{type}s_url")
|
37
48
|
oldest = a.send("oldest_#{type}")
|
38
49
|
|
39
|
-
|
40
|
-
|
41
|
-
|
50
|
+
if number_of_type == 0
|
51
|
+
"There are #{link("no #{type_label}s open", type_link)}."
|
52
|
+
else
|
53
|
+
"There #{are_is(number_of_type)} #{link("#{number_of_type} #{pluralize(type_label, number_of_type)} open", type_link)}. " +
|
54
|
+
"The average #{type_label} age is #{a.send("average_#{type}_age")}, and the " +
|
55
|
+
"#{link("oldest", oldest['html_url'])} was opened on #{oldest['date'].strftime(oldest_date_format)}."
|
56
|
+
end
|
42
57
|
end
|
43
58
|
end
|
44
59
|
|
45
60
|
class Report
|
46
|
-
require 'how_is/report/pdf'
|
47
61
|
require 'how_is/report/json'
|
48
62
|
require 'how_is/report/html'
|
49
63
|
|
64
|
+
# The way this entire class works is there is a REPORT_BLOCK proc which
|
65
|
+
# calls various methods to create the report, and REPORT_BLOCK is eventually
|
66
|
+
# instance_exec'd by the various *Report (HtmlReport, previously PdfReport)
|
67
|
+
# classes, which define the methods required.
|
68
|
+
#
|
69
|
+
# The *Report class inherit from BaseReport, which implements the common
|
70
|
+
# methods for them.
|
71
|
+
|
50
72
|
REPORT_BLOCK = proc do
|
51
73
|
title "How is #{analysis.repository}?"
|
52
74
|
|
75
|
+
# DateTime#new_offset(0) sets the timezone to UTC. I think it does this
|
76
|
+
# without changing anything besides the timezone, but who knows, 'cause
|
77
|
+
# new_offset is entirely undocumented! (Even though it's used in the
|
78
|
+
# DateTime documentation!)
|
79
|
+
#
|
80
|
+
# TODO: Stop pretending everyone who runs how_is is in UTC.
|
81
|
+
text "Monthly report, ending on #{DateTime.now.new_offset(0).strftime('%B %e, %Y')}."
|
82
|
+
|
53
83
|
text github_pulse_summary
|
54
84
|
|
55
85
|
header "Pull Requests"
|
@@ -67,13 +97,17 @@ module HowIs
|
|
67
97
|
horizontal_bar_graph issues_per_label
|
68
98
|
end
|
69
99
|
|
70
|
-
|
100
|
+
##
|
101
|
+
# Export a report to a file.
|
102
|
+
def self.export_file(analysis, file)
|
71
103
|
format = file.split('.').last
|
72
104
|
report = get_report_class(format).new(analysis)
|
73
105
|
|
74
|
-
report.
|
106
|
+
report.export_file(file, &REPORT_BLOCK)
|
75
107
|
end
|
76
108
|
|
109
|
+
##
|
110
|
+
# Export a report to a String.
|
77
111
|
def self.export(analysis, format = HowIs::DEFAULT_FORMAT)
|
78
112
|
report = get_report_class(format).new(analysis)
|
79
113
|
|
@@ -81,6 +115,8 @@ module HowIs
|
|
81
115
|
end
|
82
116
|
|
83
117
|
private
|
118
|
+
# Given a format name (+format+), returns the corresponding <blah>Report
|
119
|
+
# class.
|
84
120
|
def self.get_report_class(format)
|
85
121
|
class_name = "#{format.capitalize}Report"
|
86
122
|
|
data/lib/how_is/version.rb
CHANGED
data/lib/how_is.rb
CHANGED
@@ -15,27 +15,37 @@ module HowIs
|
|
15
15
|
|
16
16
|
DEFAULT_FORMAT = :html
|
17
17
|
|
18
|
+
##
|
19
|
+
# Generate a report file.
|
18
20
|
def self.generate_report_file(report:, **kw_args)
|
19
21
|
analysis = self.generate_analysis(**kw_args)
|
20
22
|
|
21
|
-
Report.
|
23
|
+
Report.export_file(analysis, report)
|
22
24
|
end
|
23
25
|
|
26
|
+
##
|
27
|
+
# Generates and returns a report as a String.
|
24
28
|
def self.generate_report(format:, **kw_args)
|
25
29
|
analysis = self.generate_analysis(**kw_args)
|
26
30
|
|
27
31
|
Report.export(analysis, format)
|
28
32
|
end
|
29
33
|
|
34
|
+
##
|
35
|
+
# Returns a list of possible export formats.
|
30
36
|
def self.supported_formats
|
31
37
|
report_constants = HowIs.constants.grep(/.Report/) - [:BaseReport]
|
32
38
|
report_constants.map {|x| x.to_s.split('Report').first.downcase }
|
33
39
|
end
|
34
40
|
|
41
|
+
##
|
42
|
+
# Returns whether or not the specified +file+ can be exported to.
|
35
43
|
def self.can_export_to?(file)
|
44
|
+
# TODO: Check if the file is writable?
|
36
45
|
supported_formats.include?(file.split('.').last)
|
37
46
|
end
|
38
47
|
|
48
|
+
# Generate an analysis. Used internally for generate_report{,_file}.
|
39
49
|
Contract C::KeywordArgs[repository: String,
|
40
50
|
from: C::Optional[C::Or[String, nil]],
|
41
51
|
fetcher: C::Optional[Class],
|
data/roadmap.markdown
CHANGED
@@ -1,14 +1,24 @@
|
|
1
1
|
# How_is Roadmap
|
2
2
|
|
3
|
+
2016-09-01
|
4
|
+
|
3
5
|
A brief overview of how_is' goals and current status.
|
4
6
|
|
5
|
-
##
|
7
|
+
## Current Progress
|
8
|
+
|
9
|
+
So far, HTML and JSON reports work extremely well. PDF support has lagged
|
10
|
+
due to difficulties finding a library that can do everything needed.
|
11
|
+
There is [an integration test that fails for an unknown reason](https://github.com/how-is/how_is/issues/36).
|
6
12
|
|
7
|
-
|
13
|
+
Reports can be generated using a config file, typically named
|
14
|
+
how_is.yml. This has been successfully used for
|
15
|
+
[how-is.github.io/how-is-rubygems](https://how-is.github.io/how-is-rubygems/)
|
16
|
+
([how_is.yml source](https://github.com/how-is/how-is-rubygems/blob/gh-pages/how_is.yml)).
|
8
17
|
|
9
|
-
|
18
|
+
how_is can be used as either an executable or a library, however
|
19
|
+
[library usage is currently undocumented](https://github.com/how-is/how_is/issues/45).
|
10
20
|
|
11
|
-
|
21
|
+
Metrics that have been implemented include:
|
12
22
|
|
13
23
|
* number of open Issues,
|
14
24
|
* number of open Pull Requests,
|
@@ -18,6 +28,19 @@ Simple metrics will include:
|
|
18
28
|
* date oldest Issue was opened,
|
19
29
|
* date oldest Pull Request was opened.
|
20
30
|
|
31
|
+
HTML reports contain a graph showing the issues assigned each label (or no
|
32
|
+
label). PDF reports contain a less-nice variant of
|
33
|
+
that graph.
|
34
|
+
|
35
|
+
## Goals
|
36
|
+
|
37
|
+
The next major steps are complex metrics and creating a web
|
38
|
+
dashboard for multiple projects.
|
39
|
+
|
40
|
+
Complex metrics require things like cloning the repository or making multiple API requests.
|
41
|
+
|
42
|
+
### Complex Metrics
|
43
|
+
|
21
44
|
Complex metrics will include:
|
22
45
|
|
23
46
|
* code churn (code change over time),
|
@@ -26,24 +49,34 @@ Complex metrics will include:
|
|
26
49
|
|
27
50
|
These metrics serve to either quantify the state of the repository, quantify the state of the codebase itself, or both. By quantifying the state of the issue tracker and codebase, it will hopefully be easier to decide what needs to be done.
|
28
51
|
|
29
|
-
|
30
|
-
|
31
|
-
## Current Status
|
32
|
-
|
33
|
-
As of June 15th 2016, how_is supports exports to JSON or PDF, but not HTML. For JSON and PDF, all Simple metrics have been implemented in some form, although they made need some polish ([#8](https://github.com/duckinator/how_is/issues/8)). HTML export is not implemented, and no Complex metrics are implemented. Tracking the number of issues without labels has also not been implemented ([#1](https://github.com/duckinator/how_is/issues/1)).
|
52
|
+
### Dashboard
|
34
53
|
|
35
|
-
|
54
|
+
The end goal for the dashboard is to have a website where you can view
|
55
|
+
information about multiple projects, and identify trends.
|
36
56
|
|
37
|
-
|
57
|
+
Currently, there is a way to generate reports based on a configuration
|
58
|
+
file, which has been successfully used to generate [reports for RubyGems](https://how-is.github.io/how-is-rubygems/).
|
59
|
+
However, these have to be manually generated each month.
|
38
60
|
|
39
|
-
|
61
|
+
Idealy, these could be generated automatically, and would be stored in a
|
62
|
+
database. Once that is done, the information can be more easily retrieved
|
63
|
+
in groups and used to generate graphs or more complex summaries.
|
40
64
|
|
41
|
-
|
65
|
+
## Milestones
|
42
66
|
|
43
|
-
|
67
|
+
Before beginning work on the dashboard, the how_is APIs need to be
|
68
|
+
documented and possibly cleaned up.
|
44
69
|
|
45
|
-
Once
|
70
|
+
Once that's done, the plan for beginning work on the dashboard is
|
71
|
+
roughly:
|
46
72
|
|
47
|
-
|
73
|
+
1. decide what the dashboard will eventually contain,
|
74
|
+
2. create a design for the finished dashboard (so we know what's being
|
75
|
+
worked towards),
|
76
|
+
3. figure out the software architecture required to support this,
|
77
|
+
4. determine what parts of the dashboard are currently implementable,
|
78
|
+
5. create an intermediate design for what how_is can actually support
|
79
|
+
(this should be a subset of the original design).
|
48
80
|
|
49
|
-
|
81
|
+
Once these have been done, it should be possible to have people work on
|
82
|
+
the dashboard in parallel.
|
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:
|
4
|
+
version: 11.0.0
|
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: 2016-
|
11
|
+
date: 2016-11-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: github_api
|
@@ -164,6 +164,34 @@ dependencies:
|
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: 0.8.1
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: vcr
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '3.0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '3.0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: webmock
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
167
195
|
description:
|
168
196
|
email:
|
169
197
|
- me@duckie.co
|
@@ -176,6 +204,7 @@ files:
|
|
176
204
|
- ".rspec"
|
177
205
|
- ".rspec-ignore-tags"
|
178
206
|
- ".travis.yml"
|
207
|
+
- CHANGELOG.md
|
179
208
|
- CODE_OF_CONDUCT.md
|
180
209
|
- Gemfile
|
181
210
|
- LICENSE.txt
|
@@ -183,12 +212,12 @@ files:
|
|
183
212
|
- Rakefile
|
184
213
|
- bin/console
|
185
214
|
- bin/setup
|
186
|
-
- data/issues.plg
|
187
215
|
- exe/how_is
|
216
|
+
- fixtures/vcr_cassettes/how_is-example-repository.yml
|
217
|
+
- fixtures/vcr_cassettes/how_is-with-config-file.yml
|
188
218
|
- how_is.gemspec
|
189
219
|
- lib/how_is.rb
|
190
220
|
- lib/how_is/analyzer.rb
|
191
|
-
- lib/how_is/chart.rb
|
192
221
|
- lib/how_is/cli.rb
|
193
222
|
- lib/how_is/cli/parser.rb
|
194
223
|
- lib/how_is/fetcher.rb
|
@@ -196,7 +225,6 @@ files:
|
|
196
225
|
- lib/how_is/report.rb
|
197
226
|
- lib/how_is/report/html.rb
|
198
227
|
- lib/how_is/report/json.rb
|
199
|
-
- lib/how_is/report/pdf.rb
|
200
228
|
- lib/how_is/version.rb
|
201
229
|
- roadmap.markdown
|
202
230
|
homepage: https://github.com/duckinator/how_is
|
@@ -219,7 +247,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
219
247
|
version: '0'
|
220
248
|
requirements: []
|
221
249
|
rubyforge_project:
|
222
|
-
rubygems_version: 2.
|
250
|
+
rubygems_version: 2.6.8
|
223
251
|
signing_key:
|
224
252
|
specification_version: 4
|
225
253
|
summary: Quantify the health of a GitHub repository is.
|
data/data/issues.plg
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
if (!exists("chartsize")) chartsize = '500,500'
|
2
|
-
if (!exists("labelfont")) labelfont = 'Helvetica,12'
|
3
|
-
if (!exists("chartfont")) chartfont = 'Helvetica,12'
|
4
|
-
if (!exists("data")) data = 'issues-per-label.dat'
|
5
|
-
if (!exists("pngfile")) data = 'issues-per-label.png'
|
6
|
-
|
7
|
-
set terminal png size chartsize font chartfont
|
8
|
-
|
9
|
-
set output pngfile
|
10
|
-
|
11
|
-
unset key
|
12
|
-
unset border
|
13
|
-
set tics nomirror
|
14
|
-
unset xtics
|
15
|
-
|
16
|
-
set style fill solid 0.15 border
|
17
|
-
|
18
|
-
plot data using 1:2 with boxes, data using 1:(0):3 with \
|
19
|
-
labels left \
|
20
|
-
rotate by 90 \
|
21
|
-
font labelfont \
|
22
|
-
offset 0,0.45
|