gh_inspector 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3f8de4f9d4d5514333162e28e5720005e56269c9
4
+ data.tar.gz: e419d38377a555adeb73a106204353df7aef5284
5
+ SHA512:
6
+ metadata.gz: 3e47a02594b03d101277e3a24e3f57b06aab704dd521b251bab3ec4971837809a005cbb0328112f4f6730083272491ea3ed7acb5bb038d184357574a8931680a
7
+ data.tar.gz: b252704668fd6a34cfd5c990e632a41a63d9ef8fa6aca64663f7d54ce7f16f20ed742ba32dfc50d7a931ca613cdb100e82a2c5c3d3bcedfee7e55d349c4ff9a5
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /.idea
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,123 @@
1
+ Style/ClassVars:
2
+ Enabled: false
3
+
4
+ Style/ClassCheck:
5
+ EnforcedStyle: kind_of?
6
+
7
+ # Cop supports --auto-correct.
8
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
9
+ Style/BracesAroundHashParameters:
10
+ Enabled: false
11
+
12
+ Lint/UselessAssignment:
13
+ Exclude:
14
+ - 'spec/**/*'
15
+
16
+ # Cop supports --auto-correct.
17
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
18
+ Style/IndentHash:
19
+ Enabled: false
20
+
21
+ Style/RaiseArgs:
22
+ EnforcedStyle: exploded
23
+
24
+ Style/DoubleNegation:
25
+ Enabled: false
26
+
27
+ Lint/HandleExceptions:
28
+ Enabled: false
29
+
30
+ # Cop supports --auto-correct.
31
+ Lint/UnusedBlockArgument:
32
+ Enabled: false
33
+
34
+ # Needed for $verbose
35
+ Style/GlobalVars:
36
+ Enabled: false
37
+
38
+ Style/FileName:
39
+ Enabled: false
40
+
41
+ # $? Exit
42
+ Style/SpecialGlobalVars:
43
+ Enabled: false
44
+
45
+ # the let(:key) { ... } should be allowed in tests
46
+ Lint/ParenthesesAsGroupedExpression:
47
+ Exclude:
48
+ - 'spec/**/*'
49
+
50
+ # options.rb might be large, we know that
51
+ Metrics/MethodLength:
52
+ Max: 60
53
+ Exclude:
54
+ - 'lib/*/options.rb'
55
+
56
+ # Both string notations are okay
57
+ Style/StringLiterals:
58
+ Enabled: false
59
+
60
+ # The %w might be confusing for new users
61
+ Style/WordArray:
62
+ MinSize: 19
63
+
64
+ # Not a good thing
65
+ Style/RedundantSelf:
66
+ Enabled: false
67
+
68
+ # raise and fail are both okay
69
+ Style/SignalException:
70
+ Enabled: false
71
+
72
+ # Better too much 'return' than one missing
73
+ Style/RedundantReturn:
74
+ Enabled: false
75
+
76
+ # Having if in the same line might not always be good
77
+ Style/IfUnlessModifier:
78
+ Enabled: false
79
+
80
+ # That looks wrong
81
+ Style/AlignHash:
82
+ Enabled: false
83
+
84
+ # and and or is okay
85
+ Style/AndOr:
86
+ Enabled: false
87
+
88
+ # Offense count: 20
89
+ Metrics/AbcSize:
90
+ Max: 60
91
+
92
+ # Configuration parameters: CountComments.
93
+ Metrics/ClassLength:
94
+ Max: 320
95
+
96
+ Metrics/CyclomaticComplexity:
97
+ Max: 17
98
+
99
+ # Configuration parameters: AllowURI, URISchemes.
100
+ Metrics/LineLength:
101
+ Max: 370
102
+
103
+ # Configuration parameters: CountKeywordArgs.
104
+ Metrics/ParameterLists:
105
+ Max: 17
106
+
107
+ Metrics/PerceivedComplexity:
108
+ Max: 18
109
+
110
+ Style/DotPosition:
111
+ Enabled: false
112
+
113
+ Style/GuardClause:
114
+ Enabled: false
115
+
116
+ Style/Documentation:
117
+ Enabled: false
118
+
119
+ Style/ZeroLengthPredicate:
120
+ Enabled: false
121
+
122
+ Lint/UnusedMethodArgument:
123
+ Enabled: false
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.3
4
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gh-issues-inspector.gemspec
4
+ gemspec
@@ -0,0 +1,89 @@
1
+ # The Issues Inspector
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'gh_inspector'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ ## Usage
16
+
17
+ #### The Inspector
18
+
19
+ To get started using The Issues Inspector, you will need to
20
+ create an inspector instance. This class is main public API for querying issues.
21
+
22
+ #### Getting Started
23
+
24
+ Create an instance of `GhInspector::Inspector`, you can then ask it to search
25
+ based on your raised exception, or as a direct query yourself.
26
+
27
+ ``` ruby
28
+ require 'gh_inspector'
29
+ inspector = GhInspector::Inspector.new "orta", "eigen"
30
+ inspector.search_query "Someone set us up the bomb"
31
+ ```
32
+
33
+ By default this would output:
34
+
35
+ ```
36
+ Looking for related issues on CocoaPods/CocoaPods...
37
+
38
+ - undefined method `to_ary' for #<Pod::Specification name="iVersion">Did you mean? to_query
39
+ https://github.com/CocoaPods/CocoaPods/issues/4748 [closed] [1 comment]
40
+
41
+ - NoMethodError - undefined method `to_ary' for Pod EAIntroView
42
+ https://github.com/CocoaPods/CocoaPods/issues/4391 [closed] [15 comments]
43
+
44
+ - Do a search on GitHub for issues relating to a crash?
45
+ https://github.com/CocoaPods/CocoaPods/issues/4391 [open] [3 comments]
46
+
47
+ and 10 more at:
48
+ https://github.com/CocoaPods/CocoaPods/search?q=undefined+method+%60to_ary%27&type=Issues
49
+ ```
50
+ #### Presenting Your Report
51
+
52
+ The default user interface for the inspector, its public API should be
53
+ considered the protocol for other classes wanting to provide a user interface.
54
+
55
+ Your custom objects will be verified at runtime that they conform to the protocol.
56
+
57
+ You can see the default implmentation at
58
+ [lib/evidence.rb](/orta/gh-issues-inspector/tree/master/lib/evidence.rb).
59
+
60
+ Both `search_query` and `search_exception` take your custom delegate as a 2nd optional parameter.
61
+
62
+ ``` ruby
63
+ require 'gh_inspector'
64
+ inspector = GhInspector::Inspector.new "orta", "eigen"
65
+ inspector.search_query "Someone set us up the bomb", ArtsyUI.new
66
+ ```
67
+ Protocol for custom objects:
68
+
69
+ - `inspector_started_query(query, inspector)` - Called just as the investigation has begun.
70
+ - `inspector_successfully_recieved_report(report, inspector)` - Called once the inspector has recieved a report with more than one issue.
71
+ - `inspector_recieved_empty_report(report, inspector)` - Called once the report has been recieved, but when there are no issues found.
72
+ - `inspector_could_not_create_report(error, query, inspector)` - Called when there have been networking issues in creating the report.
73
+
74
+
75
+ ## Development
76
+
77
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
78
+
79
+ The usage section of this README is generated from inline documentation inside the classes, to update it run `rake readme`.
80
+
81
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
82
+
83
+ ## Vision
84
+
85
+ I don't expect this project to grow too much, there's space around improving the search query for an exception, mainly. Other than that the project is effectively done and just needs some production usage to iron out any kinks. This project is well tested, and has zero dependencies.
86
+
87
+ ## Contributing
88
+
89
+ Bug reports and pull requests are welcome on GitHub at https://github.com/orta/gh-issues-inspector.
@@ -0,0 +1,52 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:specs)
6
+
7
+ task default: :spec
8
+
9
+ task :spec do
10
+ Rake::Task['specs'].invoke
11
+ Rake::Task['rubocop'].invoke
12
+ end
13
+
14
+ desc 'Run RuboCop on the lib/specs directory'
15
+ RuboCop::RakeTask.new(:rubocop) do |task|
16
+ task.patterns = ['lib/**/*.rb', 'spec/**/*.rb']
17
+ end
18
+
19
+ task :readme do
20
+ readme = File.open("README.md", 'rb', &:read)
21
+
22
+ start_split = "## Usage"
23
+ end_split = "## Development"
24
+
25
+ start = readme.split(start_split)[0]
26
+ rest = readme.split(start_split)[1]
27
+ finale = rest.split(end_split)[1]
28
+
29
+ require 'yard'
30
+ files = ["lib/gh_inspector/inspector.rb", "lib/gh_inspector/sidekick.rb", "lib/gh_inspector/evidence.rb"]
31
+ docs = YARD::Registry.load(files, true)
32
+
33
+ usage = "\n\n"
34
+ usage << "#### The Inspector\n\n"
35
+ usage << docs.at("GhInspector::Inspector").docstring
36
+ usage << "\n"
37
+
38
+ usage << "#### Presenting Your Report \n\n"
39
+ evidence = docs.at("GhInspector::Evidence")
40
+ usage << evidence.docstring
41
+
42
+ usage << "\nProtocol for custom objects:\n\n"
43
+ evidence.children.each do |method|
44
+ next unless method.name.to_s.start_with? "inspector"
45
+ params = method.parameters.flatten.compact
46
+ usage << " - `#{method.name}(#{params.join ', '})` - #{method.docstring}\n"
47
+ end
48
+ usage << "\n\n"
49
+
50
+ new_file = start + start_split + usage + end_split + finale
51
+ File.open("README.md", 'w') { |f| f.write new_file }
52
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'gh_inspector'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ require 'pry'
10
+ Pry.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gh_inspector/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'gh_inspector'
8
+ spec.version = GhInspector::VERSION
9
+ spec.authors = ['Orta Therox', 'Felix Krause']
10
+ spec.email = ['orta.therox@gmail.com', 'gh_inspector@krausefx.com']
11
+
12
+ spec.summary = 'Search through GitHub issues for your project for existing issues about a Ruby Error.'
13
+ spec.homepage = 'https://github.com/orta/gh_inspector'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ spec.bindir = 'exe'
17
+ spec.require_paths = ['lib']
18
+
19
+ spec.add_development_dependency 'bundler', '~> 1.11'
20
+ spec.add_development_dependency 'rake', '~> 10.0'
21
+ spec.add_development_dependency 'rspec', '~> 3.0'
22
+ spec.add_development_dependency 'pry'
23
+ spec.add_development_dependency 'rubocop'
24
+ end
@@ -0,0 +1,8 @@
1
+ require 'gh_inspector/version'
2
+ require 'gh_inspector/inspector'
3
+ require 'gh_inspector/sidekick'
4
+ require 'gh_inspector/evidence'
5
+ require 'gh_inspector/exception_hound'
6
+
7
+ module GhInspector
8
+ end
@@ -0,0 +1,89 @@
1
+ require 'gh_inspector/version'
2
+ require 'time'
3
+
4
+ module GhInspector
5
+ # The default user interface for the inspector, its public API should be
6
+ # considered the protocol for other classes wanting to provide a user interface.
7
+ #
8
+ # Your custom objects will be verified at runtime that they conform to the protocol.
9
+ #
10
+ # You can see the default implmentation at
11
+ # [lib/evidence.rb](/orta/gh-issues-inspector/tree/master/lib/evidence.rb).
12
+ #
13
+ # Both `search_query` and `search_exception` take your custom delegate as a 2nd optional parameter.
14
+ #
15
+ # ``` ruby
16
+ # require 'gh_inspector'
17
+ # inspector = GhInspector::Inspector.new "orta", "eigen"
18
+ # inspector.search_query "Someone set us up the bomb", ArtsyUI.new
19
+ # ```
20
+ #
21
+
22
+ NUMBER_OF_ISSUES_INLINE = 3
23
+
24
+ class Evidence
25
+ # Called just as the investigation has begun.
26
+ def inspector_started_query(query, inspector)
27
+ puts "Looking for related GitHub issues on #{inspector.repo_owner}/#{inspector.repo_name}..."
28
+ puts "Search query: #{query}" if inspector.verbose
29
+ puts ""
30
+ end
31
+
32
+ # Called once the inspector has recieved a report with more than one issue.
33
+ def inspector_successfully_recieved_report(report, inspector)
34
+ report.issues[0..(NUMBER_OF_ISSUES_INLINE - 1)].each { |issue| print_issue_full(issue) }
35
+
36
+ if report.issues.count > NUMBER_OF_ISSUES_INLINE
37
+ puts "and #{report.total_results - NUMBER_OF_ISSUES_INLINE} more at: #{report.url}"
38
+ puts ""
39
+ end
40
+ end
41
+
42
+ # Called once the report has been recieved, but when there are no issues found.
43
+ def inspector_recieved_empty_report(report, inspector)
44
+ puts "Found no similar issues. To create a new issue, please visit:"
45
+ puts "https://github.com/#{inspector.repo_owner}/#{inspector.repo_name}/issues/new"
46
+ end
47
+
48
+ # Called when there have been networking issues in creating the report.
49
+ def inspector_could_not_create_report(error, query, inspector)
50
+ puts "Could not access the GitHub API, you may have better luck via the website."
51
+ puts "https://github.com/#{inspector.repo_owner}/#{inspector.repo_name}/search?q=#{query}&type=Issues&utf8=✓"
52
+ puts "Error: #{error.name}"
53
+ end
54
+
55
+ private
56
+
57
+ def print_issue_full(issue)
58
+ puts " - #{issue.title}"
59
+ puts " #{issue.html_url} [#{issue.state}] [#{issue.comments} comment#{issue.comments == 1 ? '' : 's'}]"
60
+ puts " #{Time.parse(issue.updated_at).to_pretty}"
61
+ puts ""
62
+ end
63
+ end
64
+ end
65
+
66
+ # Taken from https://stackoverflow.com/questions/195740/how-do-you-do-relative-time-in-rails
67
+
68
+ module PrettyDate
69
+ def to_pretty
70
+ a = (Time.now - self).to_i
71
+
72
+ case a
73
+ when 0 then 'just now'
74
+ when 1 then 'a second ago'
75
+ when 2..59 then a.to_s + ' seconds ago'
76
+ when 60..119 then 'a minute ago' # 120 = 2 minutes
77
+ when 120..3540 then (a / 60).to_i.to_s + ' minutes ago'
78
+ when 3541..7100 then 'an hour ago' # 3600 = 1 hour
79
+ when 7101..82_800 then ((a + 99) / 3600).to_i.to_s + ' hours ago'
80
+ when 82_801..172_000 then 'a day ago' # 86400 = 1 day
81
+ when 172_001..518_400 then ((a + 800) / (60 * 60 * 24)).to_i.to_s + ' days ago'
82
+ when 518_400..1_036_800 then 'a week ago'
83
+ when 1_036_801..4_147_204 then ((a + 180_000) / (60 * 60 * 24 * 7)).to_i.to_s + ' weeks ago'
84
+ else strftime("%d %b %Y")
85
+ end
86
+ end
87
+ end
88
+
89
+ Time.send :include, PrettyDate
@@ -0,0 +1,45 @@
1
+ module GhInspector
2
+ class ExceptionHound
3
+ attr_accessor :message
4
+
5
+ def initialize(error)
6
+ self.message = find_message error
7
+ end
8
+
9
+ def find_message(error)
10
+ error.to_s
11
+ end
12
+
13
+ def query
14
+ undefined
15
+ simple_nil
16
+ demangle_instances
17
+
18
+ message
19
+ end
20
+
21
+ private
22
+
23
+ def undefined
24
+ self.message = message.gsub "undefined local variable or method", "undefined"
25
+ end
26
+
27
+ def simple_nil
28
+ self.message = message.gsub "nil:NilClass", "nil"
29
+ end
30
+
31
+ def demangle_instances
32
+ self.message = regex_replace(message, /(#<.*>)/, /#<(.*):/)
33
+ end
34
+
35
+ def regex_replace(string, find, replace)
36
+ if string.match find
37
+ full = string.match(find)[0]
38
+ simple = string.match(replace)[1]
39
+ string.gsub full, simple
40
+ else
41
+ string
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,68 @@
1
+ # Note that the README is generated from the class comments, so it's a bit
2
+ # wider scope than your average class comment.
3
+
4
+ module GhInspector
5
+ # To get started using The Issues Inspector, you will need to
6
+ # create an inspector instance. This class is main public API for querying issues.
7
+ #
8
+ # #### Getting Started
9
+ #
10
+ # Create an instance of `GhInspector::Inspector`, you can then ask it to search
11
+ # based on your raised exception, or as a direct query yourself.
12
+ #
13
+ # ``` ruby
14
+ # require 'gh_inspector'
15
+ # inspector = GhInspector::Inspector.new "orta", "eigen"
16
+ # inspector.search_query "Someone set us up the bomb"
17
+ # ```
18
+ #
19
+ # By default this would output:
20
+ #
21
+ # ```
22
+ # Looking for related issues on CocoaPods/CocoaPods...
23
+ #
24
+ # - undefined method `to_ary' for #<Pod::Specification name="iVersion">Did you mean? to_query
25
+ # https://github.com/CocoaPods/CocoaPods/issues/4748 [closed] [1 comment]
26
+ #
27
+ # - NoMethodError - undefined method `to_ary' for Pod EAIntroView
28
+ # https://github.com/CocoaPods/CocoaPods/issues/4391 [closed] [15 comments]
29
+ #
30
+ # - Do a search on GitHub for issues relating to a crash?
31
+ # https://github.com/CocoaPods/CocoaPods/issues/4391 [open] [3 comments]
32
+ #
33
+ # and 10 more at:
34
+ # https://github.com/CocoaPods/CocoaPods/search?q=undefined+method+%60to_ary%27&type=Issues
35
+ # ```
36
+ #
37
+
38
+ class Inspector
39
+ attr_accessor :repo_owner, :repo_name, :query, :sidekick, :verbose
40
+
41
+ # Class init function with a "orta/project" style string
42
+ def self.from_slug(slug)
43
+ details = slug.split '/'
44
+ Inspector.new details.first, details.last
45
+ end
46
+
47
+ # Init function with "orta", "project"
48
+ def initialize(repo_owner, repo_name, verbose: false)
49
+ self.repo_owner = repo_owner
50
+ self.repo_name = repo_name
51
+ self.verbose = verbose
52
+ self.sidekick = Sidekick.new(self, repo_owner, repo_name)
53
+ end
54
+
55
+ # Will do some magic to try and pull out a reasonable search query
56
+ # for an exception, then searches with that
57
+ def search_exception(exception, delegate = nil)
58
+ query = ExceptionHound.new(exception).query
59
+ search_query(query, delegate)
60
+ end
61
+
62
+ # Queries for an specific search string
63
+ def search_query(query, delegate = nil)
64
+ delegate ||= Evidence.new
65
+ sidekick.search(query, delegate)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,110 @@
1
+ require "net/http"
2
+ require 'uri'
3
+
4
+ module GhInspector
5
+ # The Sidekick is the one who does all the real work.
6
+ # They take the query, get the GitHub API results, etc
7
+ # then pass them back to the inspector who gets the public API credit.
8
+
9
+ class Sidekick
10
+ attr_accessor :repo_owner, :repo_name, :inspector
11
+
12
+ def initialize(inspector, repo_owner, repo_name)
13
+ self.inspector = inspector
14
+ self.repo_owner = repo_owner
15
+ self.repo_name = repo_name
16
+ end
17
+
18
+ # Searches for a query, with a UI delegate
19
+ def search(query, delegate)
20
+ validate_delegate(delegate)
21
+
22
+ delegate.inspector_started_query(query, inspector)
23
+ url = url_for_request query
24
+
25
+ begin
26
+ results = get_api_results(url)
27
+ rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
28
+ delegate.inspector_could_not_create_report(e, query, inspector)
29
+ return
30
+ end
31
+
32
+ report = parse_results query, results
33
+
34
+ # TODO: progress callback
35
+
36
+ if report.issues.any?
37
+ delegate.inspector_successfully_recieved_report(report, inspector)
38
+ else
39
+ delegate.inspector_recieved_empty_report(report, inspector)
40
+ end
41
+
42
+ report
43
+ end
44
+
45
+ def verbose
46
+ self.inspector.verbose
47
+ end
48
+
49
+ private
50
+
51
+ require 'json'
52
+
53
+ # Generates a URL for the request
54
+ def url_for_request(query, sort_by: nil, order: nil)
55
+ url = "https://api.github.com/search/issues?q="
56
+ url += URI.escape(query)
57
+ url += "+repo:#{repo_owner}/#{repo_name}"
58
+ url += "&sort=#{sort_by}" if sort_by
59
+ url += "&order=#{order}" if order
60
+
61
+ url
62
+ end
63
+
64
+ # Gets the search results
65
+ def get_api_results(url)
66
+ uri = URI.parse(url)
67
+ puts "URL: #{url}" if self.verbose
68
+ http = Net::HTTP.new(uri.host, uri.port)
69
+ http.use_ssl = true
70
+
71
+ request = Net::HTTP::Get.new(uri.request_uri)
72
+ response = http.request(request)
73
+
74
+ JSON.parse(response.body)
75
+ end
76
+
77
+ # Converts a GitHub search JSON into a InspectionReport
78
+ def parse_results(query, results)
79
+ report = InspectionReport.new
80
+ report.url = "https://github.com/#{repo_owner}/#{repo_name}/search?q=#{query}&type=Issues&utf8=✓"
81
+ report.query = query
82
+ report.total_results = results['total_count']
83
+ report.issues = results['items'].map { |item| Issue.new(item) }
84
+ report
85
+ end
86
+
87
+ def validate_delegate(delegate)
88
+ e = Evidence.new
89
+ protocol = e.public_methods false
90
+ protocol.each do |m|
91
+ raise "#{delegate} does not handle #{m}" unless delegate.methods.include? m
92
+ end
93
+ end
94
+ end
95
+
96
+ class InspectionReport
97
+ attr_accessor :issues, :url, :query, :total_results
98
+ end
99
+
100
+ class Issue
101
+ attr_accessor :title, :number, :html_url, :state, :body, :comments, :updated_at
102
+
103
+ # Hash -> public attributes
104
+ def initialize(*h)
105
+ if h.length == 1 && h.first.kind_of?(Hash)
106
+ h.first.each { |k, v| send("#{k}=", v) if public_methods.include?("#{k}=".to_sym) }
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,3 @@
1
+ module GhInspector
2
+ VERSION = '1.0.0'.freeze
3
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gh_inspector
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Orta Therox
8
+ - Felix Krause
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2016-06-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.11'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.11'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '10.0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '10.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '3.0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '3.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: pry
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rubocop
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ description:
85
+ email:
86
+ - orta.therox@gmail.com
87
+ - gh_inspector@krausefx.com
88
+ executables: []
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - ".gitignore"
93
+ - ".rspec"
94
+ - ".rubocop.yml"
95
+ - ".travis.yml"
96
+ - Gemfile
97
+ - README.md
98
+ - Rakefile
99
+ - bin/console
100
+ - bin/setup
101
+ - gh_inspector.gemspec
102
+ - lib/gh_inspector.rb
103
+ - lib/gh_inspector/evidence.rb
104
+ - lib/gh_inspector/exception_hound.rb
105
+ - lib/gh_inspector/inspector.rb
106
+ - lib/gh_inspector/sidekick.rb
107
+ - lib/gh_inspector/version.rb
108
+ homepage: https://github.com/orta/gh_inspector
109
+ licenses: []
110
+ metadata: {}
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 2.2.2
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: Search through GitHub issues for your project for existing issues about a
131
+ Ruby Error.
132
+ test_files: []