github_deprecations 0.0.1
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.
- data/.gitignore +17 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +61 -0
- data/Rakefile +10 -0
- data/github_deprecations.gemspec +27 -0
- data/lib/github_deprecations/version.rb +3 -0
- data/lib/github_deprecations.rb +111 -0
- data/test/github_deprecations_test.rb +42 -0
- data/test/integration_test.rb +55 -0
- data/test/test_helper.rb +6 -0
- metadata +156 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Jerry Cheung
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# GithubDeprecations
|
2
|
+
|
3
|
+
Create GitHub issues for `ActiveSupport::Deprecation` messages.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'github_deprecations'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install github_deprecations
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
To catch as many deprecations as possible, require this as early as possible.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'github_deprecations'
|
25
|
+
|
26
|
+
GithubDeprecations.configure({
|
27
|
+
:login => 'jch',
|
28
|
+
:oauth_token => 'oauth2token',
|
29
|
+
:repo => 'org/repo-name',
|
30
|
+
|
31
|
+
:subscribe => %r{^deprecation}, # optional: string or regex of deprecation types
|
32
|
+
:labels => ['deprecations'] # optional: labels to apply to created issues
|
33
|
+
}).register!
|
34
|
+
```
|
35
|
+
|
36
|
+
## Development
|
37
|
+
|
38
|
+
To run integration tests, you need to specify two environment variables:
|
39
|
+
|
40
|
+
* `GH_LOGIN` - your github login
|
41
|
+
* `GH_OAUTH_TOKEN` - oauth access token with 'repo,delete_repo' scopes
|
42
|
+
|
43
|
+
## Contributing
|
44
|
+
|
45
|
+
1. Fork it
|
46
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
47
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
48
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
49
|
+
5. Create new Pull Request
|
50
|
+
|
51
|
+
|
52
|
+
## TODO
|
53
|
+
|
54
|
+
* better way to test with octokit
|
55
|
+
* pluggable background job backends. Would be nice to use Rails Queue API
|
56
|
+
* bin/github-access-token prompts for user/pass and returns an access token
|
57
|
+
* integrate with haystack
|
58
|
+
* smarter search
|
59
|
+
* optionally also log the deprecation
|
60
|
+
* error handling
|
61
|
+
* if issue is already closed, add a comment and re-open it?
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'github_deprecations/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "github_deprecations"
|
8
|
+
gem.version = GithubDeprecations::VERSION
|
9
|
+
gem.authors = ["Jerry Cheung"]
|
10
|
+
gem.email = ["jch@whatcodecraves.com"]
|
11
|
+
gem.description = %q{Create GitHub issues based on ActiveSupport deprecation errors}
|
12
|
+
gem.summary = %q{Create GitHub issues based on ActiveSupport deprecation errors}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency 'activesupport', '~> 3'
|
21
|
+
gem.add_dependency 'octokit', '~> 1.7'
|
22
|
+
gem.add_dependency 'resque', '~> 1.19'
|
23
|
+
gem.add_dependency 'hashie', '~> 1'
|
24
|
+
|
25
|
+
gem.add_development_dependency 'mocha', '~> 0.12'
|
26
|
+
gem.add_development_dependency 'resque-mock', '~> 0.1'
|
27
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require "active_support" # should be lazy anyways
|
2
|
+
require "date"
|
3
|
+
require "hashie"
|
4
|
+
require "github_deprecations/version"
|
5
|
+
require "octokit"
|
6
|
+
require "resque"
|
7
|
+
|
8
|
+
module GithubDeprecations
|
9
|
+
def configure(options = {}, &blk)
|
10
|
+
config = Config.new(options)
|
11
|
+
blk.call(config) if blk
|
12
|
+
config
|
13
|
+
end
|
14
|
+
module_function :configure
|
15
|
+
|
16
|
+
class Config < Hashie::Dash # add Dash#verify! so that it's not checked on initialization
|
17
|
+
property :login, :required => true
|
18
|
+
property :oauth_token, :required => true
|
19
|
+
property :repo, :required => true
|
20
|
+
property :subscribe, :default => %r{^deprecation}
|
21
|
+
property :labels, :default => ['deprecations']
|
22
|
+
|
23
|
+
# Register to intercept deprecation warnings.
|
24
|
+
#
|
25
|
+
# For each deprecation, enqueue a background job
|
26
|
+
# to create or update an issue.
|
27
|
+
def register!
|
28
|
+
ActiveSupport::Deprecation.behavior = :notify
|
29
|
+
@subscriber = ActiveSupport::Notifications.subscribe(@subscribe) do |*args|
|
30
|
+
Resque.enqueue Worker, self, args
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def reset!
|
35
|
+
ActiveSupport::Notifications.unsubscribe(@subscriber) if @subscriber
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Worker
|
40
|
+
@queue = :deprecations
|
41
|
+
|
42
|
+
def self.perform(options, event_params)
|
43
|
+
new(options).submit_issue!(event_params)
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize(options)
|
47
|
+
@options = Hashie::Mash.new(options) # serialization drops mash
|
48
|
+
end
|
49
|
+
|
50
|
+
# Create or update an issue based on deprecation warning.
|
51
|
+
#
|
52
|
+
# if we wanted to be fancy
|
53
|
+
# calculating an edit-distance probably removes a lot of duplicates
|
54
|
+
# test: when title is too long, then what? what about sha-ing the title and prefixing that to the title?
|
55
|
+
def submit_issue!(event_params)
|
56
|
+
# datetime objects are being serialized to string?
|
57
|
+
event_params[1] = DateTime.parse(event_params[1])
|
58
|
+
event_params[2] = DateTime.parse(event_params[2])
|
59
|
+
|
60
|
+
event = ActiveSupport::Notifications::Event.new(*event_params)
|
61
|
+
payload = Hashie::Mash.new(event.payload)
|
62
|
+
title = normalize_title(payload[:message])
|
63
|
+
body = "```\n" + payload[:callstack].join("\n") + "\n```\n" # ghetto markdown-ify
|
64
|
+
|
65
|
+
create_labels
|
66
|
+
match = find_issue(title)
|
67
|
+
res = match ?
|
68
|
+
update_issue(match.number, title, body) :
|
69
|
+
create_issue(title, body)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Create any missing issue labels.
|
73
|
+
def create_labels
|
74
|
+
@options.labels.each do |label|
|
75
|
+
client.add_label(@options.repo, label)
|
76
|
+
end
|
77
|
+
rescue Octokit::UnprocessableEntity => e
|
78
|
+
# assume label already exists and do nothing
|
79
|
+
end
|
80
|
+
|
81
|
+
# Find an existing issue with the same message.
|
82
|
+
#
|
83
|
+
# Returns Hashie::Mash of issue if found, otherwise nil
|
84
|
+
def find_issue(title)
|
85
|
+
issues = client.list_issues(@options.repo, :labels => @options.labels.join(','))
|
86
|
+
issues.detect {|i| i.title == title}
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_issue(title, body)
|
90
|
+
client.create_issue(@options.repo, title, body, :labels => @options.labels)
|
91
|
+
end
|
92
|
+
|
93
|
+
def update_issue(issue_number, title, body)
|
94
|
+
client.update_issue(@options.repo, issue_number, title, body)
|
95
|
+
end
|
96
|
+
|
97
|
+
def client
|
98
|
+
@client ||= Octokit::Client.new({
|
99
|
+
:login => @options.login,
|
100
|
+
:oauth_token => @options.oauth_token
|
101
|
+
})
|
102
|
+
end
|
103
|
+
|
104
|
+
# Shorten warnings and remove common stuff
|
105
|
+
def normalize_title(warning)
|
106
|
+
warning.
|
107
|
+
gsub(%r{DEPRECATION WARNING: ?}, '').
|
108
|
+
gsub(%r{ *\(called from.*}, '')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class GithubDeprecations::WorkerTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@worker = GithubDeprecations::Worker.new({
|
6
|
+
:login => 'jch',
|
7
|
+
:oauth_token => 'oauth2token',
|
8
|
+
:repo => 'org/repo-name',
|
9
|
+
:labels => []
|
10
|
+
})
|
11
|
+
# name, start, ending, transaction_id, payload. see ActiveSupport::Notifications::Event
|
12
|
+
@event = [
|
13
|
+
'deprecation.rails',
|
14
|
+
'2012-07-27 20:33:56 -0700',
|
15
|
+
'2012-07-27 20:34:03 -0700',
|
16
|
+
'13',
|
17
|
+
{
|
18
|
+
:message => "DEPRECATION WARNING: Ooga Booga. (called from irb_binding at (irb):1)",
|
19
|
+
:callstack => ['stack1', 'stack2']
|
20
|
+
}
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_create_issue
|
25
|
+
# name, start, ending, transaction_id, payload
|
26
|
+
@worker.stubs(:find_issue).returns(nil)
|
27
|
+
@worker.expects(:create_issue)
|
28
|
+
@worker.submit_issue!(@event)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_update_existing_issue
|
32
|
+
issue = stub(:number => '5')
|
33
|
+
@worker.stubs(:find_issue).returns(issue)
|
34
|
+
@worker.expects(:update_issue).with('5', any_parameters, any_parameters)
|
35
|
+
@worker.submit_issue!(@event)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_title_normalization
|
39
|
+
normalized = @worker.normalize_title("DEPRECATION WARNING: Ooga Booga. (called from irb_binding at (irb):1)")
|
40
|
+
assert_equal "Ooga Booga.", normalized
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# Access token requires 'repo,delete_repo' scope
|
4
|
+
class IntegrationTest < Test::Unit::TestCase
|
5
|
+
if ENV['GH_LOGIN'] && ENV['GH_OAUTH_TOKEN']
|
6
|
+
def setup
|
7
|
+
@test_repo = "github_deprecations_test_#{Time.now.to_i + rand(1000)}"
|
8
|
+
@user_repo = [ENV['GH_LOGIN'], @test_repo].join('/')
|
9
|
+
|
10
|
+
Resque.mock!
|
11
|
+
@app = GithubDeprecations.configure({
|
12
|
+
:login => ENV['GH_LOGIN'],
|
13
|
+
:oauth_token => ENV['GH_OAUTH_TOKEN'],
|
14
|
+
:repo => @user_repo
|
15
|
+
})
|
16
|
+
@app.register!
|
17
|
+
end
|
18
|
+
|
19
|
+
def teardown
|
20
|
+
@app.reset!
|
21
|
+
end
|
22
|
+
|
23
|
+
def with_repo(&blk)
|
24
|
+
client.create_repository(@test_repo)
|
25
|
+
blk.call @user_repo
|
26
|
+
ensure
|
27
|
+
client.delete_repository(@user_repo)
|
28
|
+
end
|
29
|
+
|
30
|
+
def client
|
31
|
+
@client ||= Octokit::Client.new({
|
32
|
+
:login => ENV['GH_LOGIN'],
|
33
|
+
:oauth_token => ENV['GH_OAUTH_TOKEN'],
|
34
|
+
})
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_create
|
38
|
+
with_repo do |repo|
|
39
|
+
ActiveSupport::Deprecation.warn "Roh oh #{Time.now.to_i}"
|
40
|
+
issues = client.list_issues(repo)
|
41
|
+
assert_equal 1, issues.size
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_update
|
46
|
+
with_repo do |repo|
|
47
|
+
num = Time.now.to_i
|
48
|
+
ActiveSupport::Deprecation.warn "Roh oh #{num}"
|
49
|
+
ActiveSupport::Deprecation.warn "Roh oh #{num}"
|
50
|
+
issues = client.list_issues(repo)
|
51
|
+
assert_equal 1, issues.size
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: github_deprecations
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jerry Cheung
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-31 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: octokit
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.7'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.7'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: resque
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.19'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.19'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: hashie
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '1'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: mocha
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0.12'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0.12'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: resque-mock
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0.1'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0.1'
|
110
|
+
description: Create GitHub issues based on ActiveSupport deprecation errors
|
111
|
+
email:
|
112
|
+
- jch@whatcodecraves.com
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- .gitignore
|
118
|
+
- Gemfile
|
119
|
+
- LICENSE.txt
|
120
|
+
- README.md
|
121
|
+
- Rakefile
|
122
|
+
- github_deprecations.gemspec
|
123
|
+
- lib/github_deprecations.rb
|
124
|
+
- lib/github_deprecations/version.rb
|
125
|
+
- test/github_deprecations_test.rb
|
126
|
+
- test/integration_test.rb
|
127
|
+
- test/test_helper.rb
|
128
|
+
homepage: ''
|
129
|
+
licenses: []
|
130
|
+
post_install_message:
|
131
|
+
rdoc_options: []
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ! '>='
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
+
none: false
|
142
|
+
requirements:
|
143
|
+
- - ! '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
requirements: []
|
147
|
+
rubyforge_project:
|
148
|
+
rubygems_version: 1.8.23
|
149
|
+
signing_key:
|
150
|
+
specification_version: 3
|
151
|
+
summary: Create GitHub issues based on ActiveSupport deprecation errors
|
152
|
+
test_files:
|
153
|
+
- test/github_deprecations_test.rb
|
154
|
+
- test/integration_test.rb
|
155
|
+
- test/test_helper.rb
|
156
|
+
has_rdoc:
|