tracker-hook-forwarder 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +69 -0
- data/Rakefile +9 -0
- data/config.ru +6 -0
- data/lib/tracker-hook-forwarder.rb +91 -0
- data/lib/tracker-hook-forwarder/forwarding.rb +30 -0
- data/lib/tracker-hook-forwarder/rack_integration.rb +10 -0
- data/lib/tracker-hook-forwarder/version.rb +3 -0
- data/spec/forwarding_spec.rb +120 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/tracker-hook-forwarder_spec.rb +73 -0
- data/tracker-hook-forwarder.gemspec +26 -0
- metadata +142 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Capita Unternehmensberatung GmbH
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Pivotal Tracker Activity Webhook Forwarder
|
2
|
+
|
3
|
+
**A simple Rack app that allows you to use any number of Activity Web Hooks on your Pivotal Tracker projects by acting as an endpoint to them and forwarding the calls from Tracker to any number of configurable other urls**
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
In a new app folder, add those files:
|
8
|
+
|
9
|
+
A `Gemfile` containing:
|
10
|
+
|
11
|
+
source :rubygems
|
12
|
+
gem 'tracker-hook-forwarder'
|
13
|
+
|
14
|
+
A `config.ru` containing:
|
15
|
+
|
16
|
+
require 'bundler/setup'
|
17
|
+
require 'tracker-hook-forwarder'
|
18
|
+
|
19
|
+
forward 'project_a', 'https://your.endpoint.com/for/tracker'
|
20
|
+
forward 'project_a', 'https://someother.com/tracker?token=1234'
|
21
|
+
|
22
|
+
forward 'project_b', 'https://someother.com/tracker?token=1234'
|
23
|
+
|
24
|
+
run TrackerHookForwarder
|
25
|
+
|
26
|
+
Deploy the application using a rack-compatible web server (or Heroku, see section below), then configure your individual Pivotal Tracker projects to post Activity Web Hooks to:
|
27
|
+
|
28
|
+
http://yourproxy.url/activity/project_a # for Project A
|
29
|
+
http://yourproxy.url/activity/project_b # for Project B
|
30
|
+
|
31
|
+
For example, we use it to notify both our [Hipchat](http://www.hipchat.com) team room and our own
|
32
|
+
[Redmine-Tracker plugin](https://github.com/capita/redmine_trackmine) using a config like this:
|
33
|
+
|
34
|
+
forward 'some_project', 'http://redmine.url.com/pivotal_activity.xml'
|
35
|
+
forward 'some_project', 'https://api.hipchat.com/v1/webhooks/pivotaltracker/?auth_token=API_TOKEN&room_id=ROOM_ID'
|
36
|
+
|
37
|
+
## Running on Heroku
|
38
|
+
|
39
|
+
Arguably the easiest way to get the proxy up and running is to spin up a Heroku app.
|
40
|
+
Assuming you've got the `heroku` gem installed and configured and the configuration
|
41
|
+
set up as above using git, run:
|
42
|
+
|
43
|
+
heroku create your-app-name --stack cedar
|
44
|
+
|
45
|
+
You might also want to add `thin` to your Gemfile and a `Procfile` containing:
|
46
|
+
|
47
|
+
web: bundle exec thin start -p $PORT
|
48
|
+
|
49
|
+
Then commit your changes and push your app to heroku:
|
50
|
+
|
51
|
+
git push heroku master
|
52
|
+
|
53
|
+
Going to your newly created app's url should now give you "Hello."
|
54
|
+
|
55
|
+
**Important:** Heroku by default idles out free applications (those that only use 1 dyno)
|
56
|
+
after a couple of minutes and further requests need to spin up a whole new instance, which
|
57
|
+
takes some time. To prevent your app from idling out, and also to get the benefit of availability monitoring, use a service like [WasItUp](http://wasitup.com/) to monitor
|
58
|
+
the site. Simply go to WasItUp, enter your app url, expect the content to be "Hello." and
|
59
|
+
enter your mail address. Your proxy should be up all night.
|
60
|
+
|
61
|
+
## Developer notes
|
62
|
+
|
63
|
+
* Clone the project
|
64
|
+
* bundle install
|
65
|
+
* rake test
|
66
|
+
|
67
|
+
## Copyright
|
68
|
+
|
69
|
+
Copyright (c) 2011 Christoph Olszowka, Capita Unternehmensberatung GmbH. See LICENSE for details.
|
data/Rakefile
ADDED
data/config.ru
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
class TrackerHookForwarder
|
4
|
+
autoload :Forwarding, 'tracker-hook-forwarder/forwarding'
|
5
|
+
autoload :RackIntegration, 'tracker-hook-forwarder/rack_integration'
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def call(env)
|
9
|
+
new(env).process
|
10
|
+
end
|
11
|
+
|
12
|
+
def logger
|
13
|
+
return @logger if @logger
|
14
|
+
@logger = Logger.new(STDOUT)
|
15
|
+
@logger.level = Logger::INFO
|
16
|
+
@logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
17
|
+
@logger
|
18
|
+
end
|
19
|
+
|
20
|
+
def forwardings
|
21
|
+
@forwardings ||= {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_forwarding(project, url)
|
25
|
+
forwardings[project.to_sym] ||= []
|
26
|
+
forwardings[project.to_sym] << Forwarding.new(url)
|
27
|
+
end
|
28
|
+
|
29
|
+
def forwardings_for(project)
|
30
|
+
return nil if project.nil? or project.length == 0
|
31
|
+
forwardings[project.to_sym]
|
32
|
+
end
|
33
|
+
|
34
|
+
def reset_forwardings!
|
35
|
+
@forwardings = nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_reader :env, :request
|
40
|
+
private :env, :request
|
41
|
+
|
42
|
+
def initialize(env)
|
43
|
+
@env = env
|
44
|
+
@request = Rack::Request.new(env)
|
45
|
+
TrackerHookForwarder.logger.info "#{request.request_method} #{request.fullpath}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def process
|
49
|
+
if activity_hook_triggered?
|
50
|
+
TrackerHookForwarder.logger.info "Activity Hook triggered for #{requested_project_name} with:\n#{post_body}"
|
51
|
+
forwardings.each {|forwarding| forwarding.forward post_body }
|
52
|
+
return [201, {"Content-Type" => 'application/xml'}, [post_body]]
|
53
|
+
|
54
|
+
elsif request.get? and request.path == '/'
|
55
|
+
return [200, {"Content-Type" => 'text/plain'}, ['Hello.']]
|
56
|
+
else
|
57
|
+
TrackerHookForwarder.logger.info "Could not find #{request.request_method} #{request.fullpath}"
|
58
|
+
return [404, {"Content-Type" => 'text/plain'}, ['Resource not found']]
|
59
|
+
end
|
60
|
+
rescue => err
|
61
|
+
TrackerHookForwarder.logger.warn "#{request.request_method} #{request.fullpath} caused an exception: #{err}\n#{err.backtrace}"
|
62
|
+
return [500, {"Content-Type" => 'text/plain'}, ['Something went wrong :(']]
|
63
|
+
end
|
64
|
+
|
65
|
+
def activity_hook_triggered?
|
66
|
+
request.post? and not forwardings.nil?
|
67
|
+
end
|
68
|
+
|
69
|
+
def post_body
|
70
|
+
return @post_body if @post_body
|
71
|
+
@post_body = ""
|
72
|
+
while data = request.body.read(1024)
|
73
|
+
@post_body << data
|
74
|
+
end
|
75
|
+
@post_body
|
76
|
+
end
|
77
|
+
|
78
|
+
def requested_project_name
|
79
|
+
path_parts = request.path.split('/').reject {|part| part.strip.length == 0 }
|
80
|
+
if path_parts.count == 2 and path_parts.first == 'activity'
|
81
|
+
path_parts[1]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def forwardings
|
86
|
+
@forwardings ||= TrackerHookForwarder.forwardings_for(requested_project_name)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Rack config.ru shorthand for setting up forwardings
|
91
|
+
Rack::Builder.send :include, TrackerHookForwarder::RackIntegration if defined?(Rack::Builder)
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
class TrackerHookForwarder
|
5
|
+
class Forwarding
|
6
|
+
attr_reader :url
|
7
|
+
include HTTParty
|
8
|
+
|
9
|
+
def initialize(url)
|
10
|
+
@url = url.freeze
|
11
|
+
unless [URI::HTTP, URI::HTTPS].include? URI.parse(url).class
|
12
|
+
raise ArgumentError, "Forwarding url must be either http or https!"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def forward(body)
|
17
|
+
response = Forwarding.post(url, :body => body, :headers => {"Content-Type" => 'application/xml'}).response
|
18
|
+
if response.kind_of?(Net::HTTPSuccess)
|
19
|
+
TrackerHookForwarder.logger.info "Forwarded to #{url}:\n#{body}"
|
20
|
+
true
|
21
|
+
else
|
22
|
+
TrackerHookForwarder.logger.warn "Forwarding to #{url} failed with #{response.class}:\n#{body}"
|
23
|
+
false
|
24
|
+
end
|
25
|
+
rescue => err
|
26
|
+
TrackerHookForwarder.logger.error "Forwarding to #{url} caused an error #{err}:\n#{body}"
|
27
|
+
false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Makes it possible to simply use the following in config.ru
|
2
|
+
#
|
3
|
+
# forward 'my_project', 'https://xyz.com'
|
4
|
+
#
|
5
|
+
module TrackerHookForwarder::RackIntegration
|
6
|
+
def forward(project, url)
|
7
|
+
TrackerHookForwarder.add_forwarding project, url
|
8
|
+
STDOUT.puts "Will forward POSTs on /activity/#{project} to #{url}"
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe TrackerHookForwarder::Forwarding do
|
4
|
+
before do
|
5
|
+
TrackerHookForwarder.reset_forwardings!
|
6
|
+
@forwarding = TrackerHookForwarder::Forwarding.new('http://foo.bar/pivotal_hook')
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'url' do
|
10
|
+
it "should return the correct url" do
|
11
|
+
@forwarding.url.must_equal 'http://foo.bar/pivotal_hook'
|
12
|
+
end
|
13
|
+
it "should have freezed the url" do
|
14
|
+
@forwarding.url.frozen?.must_equal true
|
15
|
+
lambda { @forwarding.url.gsub!('http', 'https') }.must_raise(RuntimeError)
|
16
|
+
end
|
17
|
+
it "should raise an error when the url is not http(s)" do
|
18
|
+
lambda { TrackerHookForwarder::Forwarding.new('ftp://foo.bar/pivotal_hook') }.must_raise(ArgumentError)
|
19
|
+
lambda { TrackerHookForwarder::Forwarding.new('telnet://foo.bar/pivotal_hook') }.must_raise(ArgumentError)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "configuration" do
|
24
|
+
it "should be empty initially" do
|
25
|
+
TrackerHookForwarder.forwardings.empty?.must_equal true
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should not be empty after adding a forwarding" do
|
29
|
+
TrackerHookForwarder.add_forwarding 'awesome_project', 'https://foo'
|
30
|
+
TrackerHookForwarder.forwardings.empty?.must_equal false
|
31
|
+
TrackerHookForwarder.forwardings.keys.must_equal [:awesome_project]
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "having multiple forwardings configured" do
|
35
|
+
before do
|
36
|
+
TrackerHookForwarder.add_forwarding 'awesome_project', 'https://foo'
|
37
|
+
TrackerHookForwarder.add_forwarding :awesome_project, 'http://foo.com'
|
38
|
+
TrackerHookForwarder.add_forwarding :other_project, 'http://foo.com'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should have the 2 projects configured" do
|
42
|
+
TrackerHookForwarder.forwardings.keys.sort.must_equal [:awesome_project, :other_project]
|
43
|
+
end
|
44
|
+
it "should have 2 forwardings for awesome_project" do
|
45
|
+
TrackerHookForwarder.forwardings_for(:awesome_project).count.must_equal 2
|
46
|
+
TrackerHookForwarder.forwardings_for(:awesome_project).first.url.must_equal 'https://foo'
|
47
|
+
TrackerHookForwarder.forwardings_for("awesome_project").last.url.must_equal 'http://foo.com'
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should have 1 forwarding for the other project" do
|
51
|
+
TrackerHookForwarder.forwardings_for(:other_project).count.must_equal 1
|
52
|
+
TrackerHookForwarder.forwardings_for(:other_project).first.url.must_equal 'http://foo.com'
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return nil for unknown_project for forwardings" do
|
56
|
+
TrackerHookForwarder.forwardings_for(:unknown_project).must_be_nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should return nil for empty or nil project name" do
|
60
|
+
TrackerHookForwarder.forwardings_for('').must_be_nil
|
61
|
+
TrackerHookForwarder.forwardings_for(nil).must_be_nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "forwarding to an actual endpoint" do
|
67
|
+
before do
|
68
|
+
# Simple rack app that receives the POSTs from the forwarding
|
69
|
+
Artifice.activate_with lambda { |env|
|
70
|
+
request = Rack::Request.new(env)
|
71
|
+
body = request.body.read
|
72
|
+
if request.fullpath == '/project'
|
73
|
+
raise "Requst should have been post!" unless request.post?
|
74
|
+
raise "Wrong url: #{request.url}" unless request.url == 'https://awesome.com/project'
|
75
|
+
raise "Wrong body: #{body}" unless body == '<myxml></myxml>'
|
76
|
+
[200, {}, []]
|
77
|
+
else
|
78
|
+
[404, {}, []]
|
79
|
+
end
|
80
|
+
}
|
81
|
+
|
82
|
+
TrackerHookForwarder.add_forwarding 'awesome_project', 'https://awesome.com/project'
|
83
|
+
TrackerHookForwarder.add_forwarding 'awesome_project', 'https://awesome.com/404'
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should forward the given body to our configured valid endpoint" do
|
87
|
+
TrackerHookForwarder.forwardings_for('awesome_project').first.forward('<myxml></myxml>').must_equal true
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should forward the given body to our configured invalid endpoint and handle failure gracefully" do
|
91
|
+
TrackerHookForwarder.forwardings_for('awesome_project').last.forward('<myxml></myxml>').must_equal false
|
92
|
+
end
|
93
|
+
|
94
|
+
after do
|
95
|
+
Artifice.deactivate
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "forwarding to an endpoint with query params" do
|
100
|
+
before do
|
101
|
+
# Simple rack app that receives the POSTs from the forwarding
|
102
|
+
Artifice.activate_with lambda { |env|
|
103
|
+
request = Rack::Request.new(env)
|
104
|
+
raise "Wrong token passed on!" if request.params["token"] != '123123asdf'
|
105
|
+
raise "Wrong room passed on!" if request.params["room"] != 'abcdef'
|
106
|
+
[200, {}, []]
|
107
|
+
}
|
108
|
+
|
109
|
+
TrackerHookForwarder.add_forwarding 'awesome_project', 'https://awesome.com/project/?token=123123asdf&room=abcdef'
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should forward the given body to our configured valid endpoint including the expected params" do
|
113
|
+
TrackerHookForwarder.forwardings_for('awesome_project').first.forward('<myxml></myxml>').must_equal true
|
114
|
+
end
|
115
|
+
|
116
|
+
after do
|
117
|
+
Artifice.deactivate
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start do
|
4
|
+
add_filter 'spec'
|
5
|
+
end
|
6
|
+
require 'bundler/setup'
|
7
|
+
require 'minitest/spec'
|
8
|
+
require 'minitest/autorun'
|
9
|
+
require 'minitest/mock'
|
10
|
+
require 'rack/test'
|
11
|
+
require 'rr'
|
12
|
+
require 'artifice'
|
13
|
+
require 'tracker-hook-forwarder'
|
14
|
+
|
15
|
+
# Do not show log statements while testing
|
16
|
+
TrackerHookForwarder.logger.level = Logger::FATAL
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe TrackerHookForwarder do
|
4
|
+
include Rack::Test::Methods
|
5
|
+
include RR::Adapters::TestUnit
|
6
|
+
|
7
|
+
def app
|
8
|
+
TrackerHookForwarder
|
9
|
+
end
|
10
|
+
|
11
|
+
before { TrackerHookForwarder.reset_forwardings! }
|
12
|
+
|
13
|
+
describe "GET /" do
|
14
|
+
before(:each) { get "/" }
|
15
|
+
it "should respond with status 200" do
|
16
|
+
last_response.status.must_equal 200
|
17
|
+
end
|
18
|
+
it "should give a greeting in response body" do
|
19
|
+
last_response.body.must_equal "Hello."
|
20
|
+
end
|
21
|
+
it "should respond with Content-Type text/plain" do
|
22
|
+
last_response.headers["Content-Type"].must_equal 'text/plain'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "POST /" do
|
27
|
+
before(:each) { post "/" }
|
28
|
+
it "should respond with status 404" do
|
29
|
+
last_response.status.must_equal 404
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "GET /foobar" do
|
34
|
+
before(:each) { get "/foobar" }
|
35
|
+
it "should respond with status 404" do
|
36
|
+
last_response.status.must_equal 404
|
37
|
+
end
|
38
|
+
it "should give an error in response body" do
|
39
|
+
last_response.body.must_equal "Resource not found"
|
40
|
+
end
|
41
|
+
it "should respond with Content-Type text/plain" do
|
42
|
+
last_response.headers["Content-Type"].must_equal 'text/plain'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "POST /activity/unknown" do
|
47
|
+
before(:each) { post '/activity/unknown', "<xml></xml>" }
|
48
|
+
it "should respond with status 404" do
|
49
|
+
last_response.status.must_equal 404
|
50
|
+
end
|
51
|
+
it "should give an error in response body" do
|
52
|
+
last_response.body.must_equal "Resource not found"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "POST /activity/my_project with forwardings" do
|
57
|
+
before(:each) do
|
58
|
+
TrackerHookForwarder.add_forwarding 'my_project', 'http://localhost:9292'
|
59
|
+
|
60
|
+
# Expect forward method to be called on this only forwarding, using the request body
|
61
|
+
# and returning true
|
62
|
+
mock(TrackerHookForwarder.forwardings_for(:my_project).first).forward('<xml></xml>') { true }
|
63
|
+
|
64
|
+
post '/activity/my_project', "<xml></xml>"
|
65
|
+
end
|
66
|
+
it "should respond with status 201" do
|
67
|
+
last_response.status.must_equal 201
|
68
|
+
end
|
69
|
+
it "should echo the request body" do
|
70
|
+
last_response.body.must_equal "<xml></xml>"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/tracker-hook-forwarder/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Christoph Olszowka"]
|
6
|
+
gem.email = ["colszowka at capita.de"]
|
7
|
+
gem.description = %q{A simple rack app that acts as an Activity Web Hook endpoint to Pivotal Tracker and forwards activity to any number of other endpoints, allowing you to have multiple Tracker Activity Web Hooks for any project}
|
8
|
+
gem.summary = %q{A simple rack app that acts as an Activity Web Hook endpoint to Pivotal Tracker and forwards activity to any number of other endpoints, allowing you to have multiple Tracker Activity Web Hooks for any project}
|
9
|
+
gem.homepage = "https://github.com/capita/tracker-hook-forwarder"
|
10
|
+
|
11
|
+
gem.add_dependency 'rack', '~> 1.3.5'
|
12
|
+
gem.add_dependency 'httparty', '~> 0.8.1'
|
13
|
+
|
14
|
+
gem.add_development_dependency 'minitest', '~> 2.6.2'
|
15
|
+
gem.add_development_dependency 'rack-test', '~> 0.6.1'
|
16
|
+
gem.add_development_dependency 'rr', '~> 1.0.4'
|
17
|
+
gem.add_development_dependency 'artifice', '~> 0.6'
|
18
|
+
gem.add_development_dependency 'simplecov'
|
19
|
+
|
20
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
|
+
gem.files = `git ls-files`.split("\n")
|
22
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
+
gem.name = "tracker-hook-forwarder"
|
24
|
+
gem.require_paths = ["lib"]
|
25
|
+
gem.version = TrackerHookForwarder::VERSION
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tracker-hook-forwarder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Christoph Olszowka
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-10-24 00:00:00.000000000 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rack
|
17
|
+
requirement: &5918860 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.3.5
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *5918860
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: httparty
|
28
|
+
requirement: &5917400 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.8.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *5917400
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: minitest
|
39
|
+
requirement: &5915220 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 2.6.2
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *5915220
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rack-test
|
50
|
+
requirement: &5928600 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 0.6.1
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *5928600
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: rr
|
61
|
+
requirement: &5976080 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ~>
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 1.0.4
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *5976080
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: artifice
|
72
|
+
requirement: &6000360 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0.6'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: *6000360
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: simplecov
|
83
|
+
requirement: &6014720 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: *6014720
|
92
|
+
description: A simple rack app that acts as an Activity Web Hook endpoint to Pivotal
|
93
|
+
Tracker and forwards activity to any number of other endpoints, allowing you to
|
94
|
+
have multiple Tracker Activity Web Hooks for any project
|
95
|
+
email:
|
96
|
+
- colszowka at capita.de
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- Gemfile
|
103
|
+
- LICENSE
|
104
|
+
- README.md
|
105
|
+
- Rakefile
|
106
|
+
- config.ru
|
107
|
+
- lib/tracker-hook-forwarder.rb
|
108
|
+
- lib/tracker-hook-forwarder/forwarding.rb
|
109
|
+
- lib/tracker-hook-forwarder/rack_integration.rb
|
110
|
+
- lib/tracker-hook-forwarder/version.rb
|
111
|
+
- spec/forwarding_spec.rb
|
112
|
+
- spec/spec_helper.rb
|
113
|
+
- spec/tracker-hook-forwarder_spec.rb
|
114
|
+
- tracker-hook-forwarder.gemspec
|
115
|
+
has_rdoc: true
|
116
|
+
homepage: https://github.com/capita/tracker-hook-forwarder
|
117
|
+
licenses: []
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ! '>='
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
requirements: []
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 1.6.2
|
137
|
+
signing_key:
|
138
|
+
specification_version: 3
|
139
|
+
summary: A simple rack app that acts as an Activity Web Hook endpoint to Pivotal Tracker
|
140
|
+
and forwards activity to any number of other endpoints, allowing you to have multiple
|
141
|
+
Tracker Activity Web Hooks for any project
|
142
|
+
test_files: []
|