git_hooks 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.rdoc +31 -0
- data/bin/hook-post-receive +10 -0
- data/lib/git_hooks.rb +30 -0
- data/lib/git_hooks/git_adapter.rb +68 -0
- data/lib/git_hooks/logger.rb +23 -0
- data/lib/git_hooks/notifier.rb +2 -0
- data/lib/git_hooks/notifier/jabber_client.rb +99 -0
- data/lib/git_hooks/notifier/tracker_client.rb +45 -0
- data/lib/git_hooks/post_receive_hook.rb +28 -0
- data/lib/git_hooks/utils.rb +13 -0
- data/lib/git_hooks/utils/config.rb +57 -0
- data/spec/config_spec.rb +74 -0
- data/spec/git_adapter_spec.rb +28 -0
- data/spec/git_hooks_spec.rb +22 -0
- data/spec/jabber_client_spec.rb +122 -0
- data/spec/post_receive_hook_spec.rb +37 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/tracker_client_spec.rb +68 -0
- data/spec/utils_spec.rb +9 -0
- metadata +163 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Dirk Breuer
|
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.rdoc
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
= git-hooks
|
2
|
+
|
3
|
+
This is a small library which allows you to easily build Git hooks. The
|
4
|
+
interaction with Git is done through the Grit library, which allows a clean
|
5
|
+
and straight forward Ruby way of talking with Git.
|
6
|
+
|
7
|
+
== Config Example
|
8
|
+
|
9
|
+
:post_receive_hooks:
|
10
|
+
- :jabber:
|
11
|
+
:jid: JABBER_USERNAME
|
12
|
+
:password: JABBER_PASSWORD
|
13
|
+
:server: JABBER_SERVER
|
14
|
+
:recipients: [ "recipient@jabber.id" ]
|
15
|
+
|
16
|
+
- :pivotal_tracker:
|
17
|
+
:api_key: API_KEY
|
18
|
+
|
19
|
+
== Note on Patches/Pull Requests
|
20
|
+
|
21
|
+
* Fork the project.
|
22
|
+
* Make your feature addition or bug fix.
|
23
|
+
* Add tests for it. This is important so I don't break it in a
|
24
|
+
future version unintentionally.
|
25
|
+
* Commit, do not mess with rakefile, version, or history.
|
26
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
27
|
+
* Send me a pull request. Bonus points for topic branches.
|
28
|
+
|
29
|
+
== Copyright
|
30
|
+
|
31
|
+
Copyright (c) 2010 Dirk Breuer. See LICENSE for details.
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'git_hooks'
|
5
|
+
|
6
|
+
# will receive something like this: 034e985b8c1df2869aff99017b66600acb052617 462b4131bf6dd2fea41e3959b2b22380fd10be99 refs/heads/master
|
7
|
+
|
8
|
+
GitHooks::Logger.info "running hooks (#{File.basename(__FILE__)}) ..."
|
9
|
+
|
10
|
+
GitHooks.run_hook(:post_receive)
|
data/lib/git_hooks.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
|
2
|
+
|
3
|
+
require 'active_support/core_ext/string'
|
4
|
+
|
5
|
+
require 'git_hooks/notifier'
|
6
|
+
require 'git_hooks/git_adapter'
|
7
|
+
require 'git_hooks/post_receive_hook'
|
8
|
+
require 'git_hooks/logger'
|
9
|
+
require 'git_hooks/utils'
|
10
|
+
|
11
|
+
module GitHooks
|
12
|
+
|
13
|
+
class <<self
|
14
|
+
attr_writer :config_file
|
15
|
+
|
16
|
+
def config
|
17
|
+
@config_instance ||= Utils::Config.new(config_file)
|
18
|
+
end
|
19
|
+
|
20
|
+
def config_file
|
21
|
+
@config_file || "~/.git_hooks_config"
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_hook(name_of_hook, *args)
|
25
|
+
hook = "GitHooks::#{name_of_hook.to_s.camelize}Hook".constantize.new
|
26
|
+
hook.run(*args)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'grit'
|
2
|
+
|
3
|
+
module GitHooks
|
4
|
+
class GitAdapter
|
5
|
+
include Grit
|
6
|
+
|
7
|
+
class Commits
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
attr_reader :ref_name, :repo_name
|
11
|
+
|
12
|
+
def initialize(commits, ref_name, repo)
|
13
|
+
@commits = commits
|
14
|
+
self.ref_name = ref_name
|
15
|
+
self.repo_name = repo
|
16
|
+
end
|
17
|
+
|
18
|
+
def each
|
19
|
+
@commits.each { |commit| yield commit }
|
20
|
+
end
|
21
|
+
|
22
|
+
def size
|
23
|
+
@commits.size
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def ref_name=(ref_name)
|
29
|
+
@ref_name ||= ref_name.split("/").last
|
30
|
+
end
|
31
|
+
|
32
|
+
def repo_name=(repo)
|
33
|
+
return @repo if @repo
|
34
|
+
|
35
|
+
splitted_path = repo.path.split("/")
|
36
|
+
@repo_name = if (splitted_path.last =~ /\.git/) > 0
|
37
|
+
splitted_path.last.split(".").first
|
38
|
+
else
|
39
|
+
splitted_path[-2]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_reader :repo
|
46
|
+
|
47
|
+
def initialize
|
48
|
+
@repo = Repo.new(GitAdapter.find_git_root)
|
49
|
+
end
|
50
|
+
|
51
|
+
def find_commits_since_last_receive(prev_rev, current_rev, ref_name = 'master')
|
52
|
+
commits = repo.commits_between(prev_rev, current_rev)
|
53
|
+
|
54
|
+
return Commits.new(commits, ref_name, @repo)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.find_git_root
|
58
|
+
current_dir = Dir.pwd.split('/')
|
59
|
+
while current_dir.last !~ /\.git/
|
60
|
+
current_dir.pop
|
61
|
+
break if current_dir.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
return current_dir.join('/')
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module GitHooks
|
4
|
+
class Logger
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
class <<self
|
8
|
+
def method_missing(meth, *args, &blk)
|
9
|
+
if instance.logger.respond_to? meth
|
10
|
+
instance.logger.send(meth, *args)
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :logger
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
@logger = ::Logger.new("/tmp/git_hooks.log")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'xmpp4r'
|
2
|
+
require 'xmpp4r/roster'
|
3
|
+
|
4
|
+
module GitHooks
|
5
|
+
module Notifier
|
6
|
+
class JabberClient
|
7
|
+
include Jabber
|
8
|
+
|
9
|
+
class Buddy
|
10
|
+
attr_reader :jid
|
11
|
+
|
12
|
+
def initialize(jid, roster_reference)
|
13
|
+
@jid = Jabber::JID.new(jid)
|
14
|
+
@roster = roster_reference
|
15
|
+
end
|
16
|
+
|
17
|
+
def subscribed?
|
18
|
+
roster_item = @roster[jid]
|
19
|
+
if roster_item
|
20
|
+
return roster_item.subscription == :both ? true : false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(jabber_options)
|
26
|
+
@jabber_options = jabber_options
|
27
|
+
init_jabber_backend!
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_recipients(recipients)
|
31
|
+
[recipients].flatten.map do |recipient|
|
32
|
+
recipient.is_a?(Buddy) ? recipient : Buddy.new(recipient, roster)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def buddies
|
37
|
+
roster.items.map { |roster_item| Buddy.new(roster_item.last.jid, roster) }
|
38
|
+
end
|
39
|
+
|
40
|
+
def roster
|
41
|
+
@roster ||= Roster::Helper.new(backend)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.deliver(options)
|
45
|
+
commits = options.delete(:commits)
|
46
|
+
recipients = options.delete(:recipients)
|
47
|
+
|
48
|
+
client_instance = new(options)
|
49
|
+
client_instance.deliver(commits, recipients)
|
50
|
+
end
|
51
|
+
|
52
|
+
def deliver(commits, recipients)
|
53
|
+
send_message_to create_message(commits), recipients
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
private unless $TESTING
|
58
|
+
|
59
|
+
def init_jabber_backend!
|
60
|
+
@backend = Client.new(JID.new(@jabber_options[:jid]))
|
61
|
+
@backend.connect(@jabber_options[:server])
|
62
|
+
@backend.auth(@jabber_options[:password])
|
63
|
+
end
|
64
|
+
|
65
|
+
def backend
|
66
|
+
@backend
|
67
|
+
end
|
68
|
+
|
69
|
+
def create_message(from_commits)
|
70
|
+
message = "[#{GitHooks::Utils.hostname}] #{from_commits.size} commits have been pushed to '#{from_commits.repo_name}' on '#{from_commits.ref_name}':\n"
|
71
|
+
from_commits.each do |commit|
|
72
|
+
message << "\t#{commit.id[0...5]}...: '#{commit.short_message}' by #{commit.author.name}\n"
|
73
|
+
end
|
74
|
+
|
75
|
+
message
|
76
|
+
end
|
77
|
+
|
78
|
+
def request_authorization_of(recipient)
|
79
|
+
request = Jabber::Presence.new
|
80
|
+
request.to = recipient.respond_to?(:jid) ? recipient.jid : recipient
|
81
|
+
request.type = :subscribe
|
82
|
+
backend.send request
|
83
|
+
end
|
84
|
+
|
85
|
+
def send_message_to(message, recipients)
|
86
|
+
create_recipients(recipients).each do |recipient|
|
87
|
+
subject = "Git commit notification"
|
88
|
+
|
89
|
+
request_authorization_of(recipient) unless recipient.subscribed?
|
90
|
+
|
91
|
+
msg = Message::new(recipient.jid, message).set_type(:normal).set_id('1').set_subject(subject)
|
92
|
+
GitHooks::Logger.debug "msg: #{msg}"
|
93
|
+
backend.send msg
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'curb'
|
2
|
+
|
3
|
+
module GitHooks
|
4
|
+
module Notifier
|
5
|
+
class TrackerClient
|
6
|
+
|
7
|
+
attr_reader :curl
|
8
|
+
|
9
|
+
def self.deliver(options)
|
10
|
+
commits = options.delete(:commits)
|
11
|
+
|
12
|
+
client_instance = new(options)
|
13
|
+
client_instance.deliver(commits)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(tracker_options)
|
17
|
+
@curl = Curl::Easy.new("http://www.pivotaltracker.com/services/v3/source_commits") do |curl|
|
18
|
+
curl.headers["X-TrackerToken"] = tracker_options[:api_key]
|
19
|
+
curl.headers["Content-type"] = "application/xml"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def deliver(commits)
|
24
|
+
create_payloads(commits) do |payload|
|
25
|
+
curl.http_post(payload)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_payloads(commits, &block)
|
30
|
+
payloads = commits.map do |commit|
|
31
|
+
<<-XML
|
32
|
+
<source_commit>
|
33
|
+
<message>#{commit.message}</message>
|
34
|
+
<author>#{commit.author.name}</author>
|
35
|
+
<commit_id>#{commit.id}</commit_id>
|
36
|
+
</source_commit>
|
37
|
+
XML
|
38
|
+
end
|
39
|
+
|
40
|
+
payloads.each(&block)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module GitHooks
|
2
|
+
class PostReceiveHook
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@git_adapter = GitAdapter.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def run(*args)
|
9
|
+
arguments = read_arguments_from_stdin
|
10
|
+
commits = @git_adapter.find_commits_since_last_receive(*arguments)
|
11
|
+
|
12
|
+
GitHooks.config.post_receive_hooks.each do |hook|
|
13
|
+
hook.hook_class.deliver(hook.options.merge(:commits => commits))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def read_arguments_from_stdin
|
18
|
+
arguments = []
|
19
|
+
|
20
|
+
while arguments << STDIN.gets
|
21
|
+
break if arguments.last.nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
arguments.compact.first.split(" ")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module GitHooks
|
4
|
+
module Utils
|
5
|
+
|
6
|
+
class Config
|
7
|
+
|
8
|
+
class HookWrapper
|
9
|
+
|
10
|
+
attr_reader :options
|
11
|
+
|
12
|
+
def initialize(options)
|
13
|
+
@hook_class_name = options.keys.first
|
14
|
+
@options = options.values.first
|
15
|
+
end
|
16
|
+
|
17
|
+
def hook_class
|
18
|
+
@hook_class ||= "GitHooks::Notifier::#{@hook_class_name.to_s.camelize}Client".constantize
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :config
|
24
|
+
|
25
|
+
def initialize(config_file)
|
26
|
+
@config = if config_file.respond_to?(:read)
|
27
|
+
YAML.load(config_file.read)
|
28
|
+
else
|
29
|
+
YAML.load_file(File.expand_path(config_file))
|
30
|
+
end
|
31
|
+
rescue Errno::ENOENT
|
32
|
+
GitHooks::Logger.error("Config File '#{config_file}' couldn't be loaded!")
|
33
|
+
raise "Config File '#{config_file}' couldn't be loaded!"
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_missing(hook_name, *args, &blk)
|
37
|
+
if hook_definitions = config[hook_name]
|
38
|
+
|
39
|
+
hooks = hook_definitions.map { |hook_definition| HookWrapper.new(hook_definition) }
|
40
|
+
instance_variable_set("@#{hook_name}", hooks)
|
41
|
+
|
42
|
+
instance_eval <<-RUBY
|
43
|
+
def #{hook_name}
|
44
|
+
@#{hook_name}
|
45
|
+
end
|
46
|
+
RUBY
|
47
|
+
|
48
|
+
send(hook_name)
|
49
|
+
else
|
50
|
+
super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "Utils" do
|
4
|
+
|
5
|
+
describe "Config" do
|
6
|
+
|
7
|
+
it "should have read from a config file located in the home directory" do
|
8
|
+
File.should_receive(:expand_path).with("~/.git_hooks_config").and_return(path_to_config = "/Users/dbreuer/.git_hooks_config")
|
9
|
+
YAML.should_receive(:load_file).with(path_to_config).and_return({:post_receive_hooks => [{:jabber => {:jid => "jabber@example.com", :password => "password"}}]})
|
10
|
+
|
11
|
+
config_instance = GitHooks::Utils::Config.new("~/.git_hooks_config")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should alternatively init the config from a YAML StringIO" do
|
15
|
+
config_yaml = StringIO.new <<-YAML
|
16
|
+
:post_receive_hooks:
|
17
|
+
- :jabber:
|
18
|
+
:jid: JABBER_USERNAME
|
19
|
+
:password: JABBER_PASSWORD
|
20
|
+
:server: JABBER_SERVER
|
21
|
+
:recipients:
|
22
|
+
:group: [ "recipient@jabber.id" ]
|
23
|
+
|
24
|
+
- :pivotal_tracker:
|
25
|
+
:api_key: API_KEY
|
26
|
+
YAML
|
27
|
+
|
28
|
+
config_instance = GitHooks::Utils::Config.new(config_yaml)
|
29
|
+
config_instance.config.should be_a_kind_of(Hash)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return all available hooks as an array of hook wrapper classes" do
|
33
|
+
GitHooks.config.post_receive_hooks.each do |hook|
|
34
|
+
hook.should be_a_kind_of(GitHooks::Utils::Config::HookWrapper)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "HookWrapper" do
|
39
|
+
|
40
|
+
before(:each) do
|
41
|
+
hook_options = {
|
42
|
+
:jabber => {
|
43
|
+
:jid => "jabber@example.com",
|
44
|
+
:password => "password",
|
45
|
+
:recipients => [
|
46
|
+
"bender.rodriguez@planetexpress.com"
|
47
|
+
]
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
@hook_wrapper = GitHooks::Utils::Config::HookWrapper.new(hook_options)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should know its backing class" do
|
55
|
+
@hook_wrapper.hook_class.should == GitHooks::Notifier::JabberClient
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should know the options for this hook" do
|
59
|
+
expected_options = {
|
60
|
+
:jid => "jabber@example.com",
|
61
|
+
:password => "password",
|
62
|
+
:recipients => [
|
63
|
+
"bender.rodriguez@planetexpress.com"
|
64
|
+
]
|
65
|
+
}
|
66
|
+
|
67
|
+
@hook_wrapper.options.should == expected_options
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "GitAdapter" do
|
4
|
+
it "should initialize with a Grit repository" do
|
5
|
+
GitHooks::GitAdapter.should_receive(:find_git_root)
|
6
|
+
Grit::Repo.should_receive(:new)
|
7
|
+
|
8
|
+
git_adapter = GitHooks::GitAdapter.new
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should find the Git root directory based on the current directory" do
|
12
|
+
git_adapter = GitHooks::GitAdapter.new
|
13
|
+
commits = git_adapter.find_commits_since_last_receive("7eb08614", "58c3455c")
|
14
|
+
commits.size.should be(2)
|
15
|
+
commits.ref_name.should == "master"
|
16
|
+
commits.repo_name.should =~ /(git_hooks|workspace)/
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should find commits since last commit" do
|
20
|
+
Dir.should_receive(:pwd).and_return("/srv/example.com/git/repositories/git_hooks.git/hooks")
|
21
|
+
git_root = GitHooks::GitAdapter.find_git_root
|
22
|
+
git_root.should == "/srv/example.com/git/repositories/git_hooks.git"
|
23
|
+
|
24
|
+
Dir.should_receive(:pwd).and_return("/home/dbreuer/projects/git_hooks/.git/hooks")
|
25
|
+
git_root = GitHooks::GitAdapter.find_git_root
|
26
|
+
git_root.should == "/home/dbreuer/projects/git_hooks/.git"
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "GitHooks" do
|
4
|
+
|
5
|
+
it "should run a hook identified by a symbol" do
|
6
|
+
post_receive_hook_mock = mock("PostReceiveHook")
|
7
|
+
post_receive_hook_mock.should_receive(:run)
|
8
|
+
GitHooks::PostReceiveHook.should_receive(:new).and_return(post_receive_hook_mock)
|
9
|
+
|
10
|
+
GitHooks.run_hook(:post_receive)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should provide access to a config instance" do
|
14
|
+
GitHooks.config.should be_a_kind_of(GitHooks::Utils::Config)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should provide a setter for the config file path" do
|
18
|
+
GitHooks.config_file = "/path/to/config.yml"
|
19
|
+
GitHooks.config_file.should == "/path/to/config.yml"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "JabberClient" do
|
4
|
+
|
5
|
+
describe "Buddy" do
|
6
|
+
|
7
|
+
it "should have a JID and a roster reference" do
|
8
|
+
buddy = GitHooks::Notifier::JabberClient::Buddy.new("lela.starr@jabber.org", mock("RosterMock"))
|
9
|
+
buddy.jid.should be_a_kind_of(Jabber::JID)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should should know if already subscribed" do
|
13
|
+
roster_mock = mock("RosterMock")
|
14
|
+
|
15
|
+
roster_mock.should_receive(:[]).with(Jabber::JID.new("lela.starr@jabber.org")).and_return(mock("RosterItemMock", :subscription => :both))
|
16
|
+
buddy = GitHooks::Notifier::JabberClient::Buddy.new("lela.starr@jabber.org", roster_mock)
|
17
|
+
buddy.subscribed?.should be(true)
|
18
|
+
|
19
|
+
roster_mock.should_receive(:[]).with(Jabber::JID.new("lela.starr@jabber.org")).and_return(mock("RosterItemMock", :subscription => :none))
|
20
|
+
buddy = GitHooks::Notifier::JabberClient::Buddy.new("lela.starr@jabber.org", roster_mock)
|
21
|
+
buddy.subscribed?.should be(false)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
before(:each) do
|
27
|
+
@jabber_client_opts = GitHooks.config.post_receive_hooks.first.options
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should initialize with a XMPP client" do
|
31
|
+
Jabber::JID.should_receive(:new).and_return(jid_mock = mock("JIDMock"))
|
32
|
+
Jabber::Client.should_receive(:new).with(jid_mock).and_return(client_mock = mock("ClientMock"))
|
33
|
+
client_mock.should_receive(:connect).with("JABBER_SERVER")
|
34
|
+
client_mock.should_receive(:auth)
|
35
|
+
|
36
|
+
jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should transform a collection of Jabber IDs to Buddy objects" do
|
40
|
+
GitHooks::Notifier::JabberClient.any_instance.stubs(:init_jabber_backend!)
|
41
|
+
jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
|
42
|
+
jabber_client.should_receive(:roster)
|
43
|
+
|
44
|
+
|
45
|
+
jabber_client.create_recipients(["bender.rodriguez@planetexpress.com"]).each do |buddy|
|
46
|
+
buddy.should be_a_kind_of(GitHooks::Notifier::JabberClient::Buddy)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should not transform recipients that are already Buddy objects" do
|
51
|
+
GitHooks::Notifier::JabberClient.any_instance.stubs(:init_jabber_backend!)
|
52
|
+
jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
|
53
|
+
jabber_client.should_receive(:roster)
|
54
|
+
|
55
|
+
buddy = GitHooks::Notifier::JabberClient::Buddy.new("fry@planetexpress.com", nil)
|
56
|
+
|
57
|
+
jabber_client.create_recipients(["bender.rodriguez@planetexpress.com", buddy]).each do |buddy|
|
58
|
+
buddy.should be_a_kind_of(GitHooks::Notifier::JabberClient::Buddy)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should have a list of buddies" do
|
63
|
+
GitHooks::Notifier::JabberClient.any_instance.stubs(:init_jabber_backend!)
|
64
|
+
jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
|
65
|
+
jabber_client.should_receive(:roster).
|
66
|
+
at_least(2).times.
|
67
|
+
and_return(roster_mock = mock("RosterMock"))
|
68
|
+
|
69
|
+
GitHooks::Notifier::JabberClient::Buddy.should_receive(:new).
|
70
|
+
with("lela.starr@jabber.org", roster_mock).
|
71
|
+
and_return(lela_starr = mock("BuddyMock"))
|
72
|
+
|
73
|
+
roster_mock.should_receive(:items).
|
74
|
+
and_return({:jabber_internal => mock("RosterItem", :jid => "lela.starr@jabber.org")})
|
75
|
+
|
76
|
+
jabber_client.buddies.should == [lela_starr]
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should create a message out of a bunch of commits" do
|
80
|
+
GitHooks::Notifier::JabberClient.any_instance.stubs(:init_jabber_backend!)
|
81
|
+
jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
|
82
|
+
|
83
|
+
commit = mock("CommitMock")
|
84
|
+
commit.should_receive(:id).and_return("c1be3c82cafc755754ee2247ec8dae1e6a64857f")
|
85
|
+
commit.should_receive(:short_message).and_return("This was a simple test commit.")
|
86
|
+
commit.should_receive(:author).and_return(mock("Author", :name => "Dirk Breuer"))
|
87
|
+
|
88
|
+
commits = mock("CommitsMock")
|
89
|
+
commits.should_receive(:ref_name).and_return("master")
|
90
|
+
commits.should_receive(:repo_name).and_return("git_hooks")
|
91
|
+
commits.should_receive(:each).and_yield(commit)
|
92
|
+
commits.should_receive(:size).and_return(1)
|
93
|
+
|
94
|
+
jabber_client.create_message(commits)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should request a recipient for authorization if she is not a subscribed buddy" do
|
98
|
+
GitHooks::Notifier::JabberClient.any_instance.stubs(:init_jabber_backend!)
|
99
|
+
jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
|
100
|
+
jabber_client.should_receive(:backend).and_return(mock("JabberBackend", :send => true))
|
101
|
+
|
102
|
+
jabber_client.should_receive(:roster).and_return(roster_mock = mock("RosterMock"))
|
103
|
+
|
104
|
+
GitHooks::Notifier::JabberClient::Buddy.should_receive(:new).
|
105
|
+
with("lela.starr@jabber.org", roster_mock).
|
106
|
+
and_return(buddy = mock("BuddyMock", :subscribed? => false, :jid => "lela.starr@jabber.org"))
|
107
|
+
|
108
|
+
jabber_client.should_receive(:request_authorization_of).with(buddy)
|
109
|
+
|
110
|
+
jabber_client.send_message_to "My testing message", "lela.starr@jabber.org"
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should send the notification based on the given options" do
|
114
|
+
GitHooks::Notifier::JabberClient.any_instance.stubs(:init_jabber_backend!)
|
115
|
+
jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
|
116
|
+
commits = [mock("Commit")]
|
117
|
+
jabber_client.should_receive(:create_message).with(commits).and_return(message = "Message")
|
118
|
+
jabber_client.should_receive(:send_message_to).with(message, "lela.starr@jabber.org")
|
119
|
+
jabber_client.deliver(commits, "lela.starr@jabber.org")
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "PostReceiveHook" do
|
4
|
+
|
5
|
+
it "should should read arguments given by Git from stdin" do
|
6
|
+
STDIN.expects(:gets).times(2).returns("old_sha new_sha refs/head/master\n").then.returns(nil)
|
7
|
+
|
8
|
+
post_receive_hook = GitHooks::PostReceiveHook.new
|
9
|
+
arguments = post_receive_hook.read_arguments_from_stdin
|
10
|
+
arguments.should == ["old_sha", "new_sha", "refs/head/master"]
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should promote the received commits to all registered post_receive hooks" do
|
14
|
+
post_receive_hook = GitHooks::PostReceiveHook.new
|
15
|
+
|
16
|
+
post_receive_hook.should_receive(:read_arguments_from_stdin).
|
17
|
+
and_return(["old_sha", "new_sha", "refs/head/master"])
|
18
|
+
|
19
|
+
GitHooks::GitAdapter.any_instance.
|
20
|
+
expects(:find_commits_since_last_receive).
|
21
|
+
with("old_sha", "new_sha", "refs/head/master").
|
22
|
+
returns(commits = [mock("Commit")])
|
23
|
+
|
24
|
+
jabber_hook = mock("HookMock")
|
25
|
+
jabber_hook.should_receive(:hook_class).and_return(GitHooks::Notifier::JabberClient)
|
26
|
+
jabber_hook.should_receive(:options).and_return({:other_jabber_option => "Option"})
|
27
|
+
|
28
|
+
post_receive_hooks = [jabber_hook]
|
29
|
+
|
30
|
+
GitHooks.config.should_receive(:post_receive_hooks).and_return(post_receive_hooks)
|
31
|
+
|
32
|
+
GitHooks::Notifier::JabberClient.should_receive(:deliver).with({:other_jabber_option => "Option", :commits => commits})
|
33
|
+
|
34
|
+
post_receive_hook.run
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require 'spec/autorun'
|
4
|
+
require 'mocha'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
8
|
+
|
9
|
+
$TESTING = true
|
10
|
+
|
11
|
+
require 'git_hooks'
|
12
|
+
|
13
|
+
# init the config class with testing config
|
14
|
+
config_yaml = StringIO.new <<-YAML
|
15
|
+
:post_receive_hooks:
|
16
|
+
- :jabber:
|
17
|
+
:jid: JABBER_USERNAME
|
18
|
+
:password: JABBER_PASSWORD
|
19
|
+
:server: JABBER_SERVER
|
20
|
+
:recipients: [ "recipient@jabber.id" ]
|
21
|
+
|
22
|
+
- :pivotal_tracker:
|
23
|
+
:api_key: API_KEY
|
24
|
+
YAML
|
25
|
+
GitHooks.config_file = config_yaml
|
26
|
+
|
27
|
+
Spec::Runner.configure do |config|
|
28
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "TrackerClient" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@tracker_options = { :api_key => "MY_API_KEY" }
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should create a pivotal tracker ready payload for each passed commit" do
|
10
|
+
commit = mock("CommitMock")
|
11
|
+
commit.should_receive(:id).and_return("SHA_ID")
|
12
|
+
commit.should_receive(:message).and_return("[#1234] Commit Message")
|
13
|
+
commit.should_receive(:author).and_return(mock("AuthorMock", :name => "Seras Victoria"))
|
14
|
+
|
15
|
+
expected_payload = <<-XML
|
16
|
+
<source_commit>
|
17
|
+
<message>[#1234] Commit Message</message>
|
18
|
+
<author>Seras Victoria</author>
|
19
|
+
<commit_id>SHA_ID</commit_id>
|
20
|
+
</source_commit>
|
21
|
+
XML
|
22
|
+
|
23
|
+
client = GitHooks::Notifier::TrackerClient.new(@tracker_options)
|
24
|
+
client.create_payloads([commit]) do |payload|
|
25
|
+
payload.should == expected_payload
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should send commit messages to pivotal tracker" do
|
30
|
+
commits = [mock("CommitMock")]
|
31
|
+
payload = "some test payload"
|
32
|
+
curl = mock("CurlMock")
|
33
|
+
curl.should_receive(:http_post).with(payload)
|
34
|
+
|
35
|
+
client = GitHooks::Notifier::TrackerClient.new(@tracker_options)
|
36
|
+
client.should_receive(:create_payloads).with(commits).and_yield(payload)
|
37
|
+
client.should_receive(:curl).and_return(curl)
|
38
|
+
|
39
|
+
client.deliver(commits)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should initialize client with a curb client ready to post to pivotal tracker" do
|
43
|
+
curb = mock("CurbMock")
|
44
|
+
headers = {}
|
45
|
+
curb.should_receive(:headers).twice.and_return(headers)
|
46
|
+
|
47
|
+
Curl::Easy.should_receive(:new).with("http://www.pivotaltracker.com/services/v3/source_commits").and_yield(curb)
|
48
|
+
|
49
|
+
client = GitHooks::Notifier::TrackerClient.new(@tracker_options)
|
50
|
+
|
51
|
+
headers["X-TrackerToken"].should == @tracker_options[:api_key]
|
52
|
+
headers["Content-type"].should == "application/xml"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should provide class level deliver methods" do
|
56
|
+
deliver_options = {
|
57
|
+
:commits => [mock("CommitMock")],
|
58
|
+
:api_key => "MY_API_KEY"
|
59
|
+
}
|
60
|
+
|
61
|
+
client = mock("TrackerClientMock")
|
62
|
+
client.should_receive(:deliver).with(deliver_options[:commits])
|
63
|
+
GitHooks::Notifier::TrackerClient.should_receive(:new).with({:api_key => "MY_API_KEY"}).and_return(client)
|
64
|
+
|
65
|
+
GitHooks::Notifier::TrackerClient.deliver(deliver_options)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/spec/utils_spec.rb
ADDED
metadata
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git_hooks
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Dirk Breuer
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-10 00:00:00 +02:00
|
18
|
+
default_executable: hook-post-receive
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: grit
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 2
|
29
|
+
- 0
|
30
|
+
- 0
|
31
|
+
version: 2.0.0
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: xmpp4r
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 5
|
44
|
+
version: "0.5"
|
45
|
+
type: :runtime
|
46
|
+
version_requirements: *id002
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: curb
|
49
|
+
prerelease: false
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
- 7
|
57
|
+
- 1
|
58
|
+
version: 0.7.1
|
59
|
+
type: :runtime
|
60
|
+
version_requirements: *id003
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: activesupport
|
63
|
+
prerelease: false
|
64
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
segments:
|
69
|
+
- 3
|
70
|
+
- 0
|
71
|
+
- 0
|
72
|
+
- beta
|
73
|
+
version: 3.0.0.beta
|
74
|
+
type: :runtime
|
75
|
+
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: rspec
|
78
|
+
prerelease: false
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
segments:
|
84
|
+
- 1
|
85
|
+
- 2
|
86
|
+
- 9
|
87
|
+
version: 1.2.9
|
88
|
+
type: :development
|
89
|
+
version_requirements: *id005
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: mocha
|
92
|
+
prerelease: false
|
93
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
- 9
|
100
|
+
- 8
|
101
|
+
version: 0.9.8
|
102
|
+
type: :development
|
103
|
+
version_requirements: *id006
|
104
|
+
description: The goal is to provide a pluggable hook infrastructure, where you can easily use different hooks for different purposes.
|
105
|
+
email: dirk.breuer@gmail.com
|
106
|
+
executables:
|
107
|
+
- hook-post-receive
|
108
|
+
extensions: []
|
109
|
+
|
110
|
+
extra_rdoc_files:
|
111
|
+
- LICENSE
|
112
|
+
- README.rdoc
|
113
|
+
files:
|
114
|
+
- README.rdoc
|
115
|
+
- lib/git_hooks.rb
|
116
|
+
- lib/git_hooks/git_adapter.rb
|
117
|
+
- lib/git_hooks/logger.rb
|
118
|
+
- lib/git_hooks/notifier.rb
|
119
|
+
- lib/git_hooks/notifier/jabber_client.rb
|
120
|
+
- lib/git_hooks/notifier/tracker_client.rb
|
121
|
+
- lib/git_hooks/post_receive_hook.rb
|
122
|
+
- lib/git_hooks/utils.rb
|
123
|
+
- lib/git_hooks/utils/config.rb
|
124
|
+
- LICENSE
|
125
|
+
has_rdoc: true
|
126
|
+
homepage: http://github.com/railsbros/git-hooks
|
127
|
+
licenses: []
|
128
|
+
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options:
|
131
|
+
- --charset=UTF-8
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
segments:
|
139
|
+
- 0
|
140
|
+
version: "0"
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
segments:
|
146
|
+
- 0
|
147
|
+
version: "0"
|
148
|
+
requirements: []
|
149
|
+
|
150
|
+
rubyforge_project:
|
151
|
+
rubygems_version: 1.3.6
|
152
|
+
signing_key:
|
153
|
+
specification_version: 3
|
154
|
+
summary: A small Gem to provide various Git-Hooks based on Grit.
|
155
|
+
test_files:
|
156
|
+
- spec/config_spec.rb
|
157
|
+
- spec/git_adapter_spec.rb
|
158
|
+
- spec/git_hooks_spec.rb
|
159
|
+
- spec/jabber_client_spec.rb
|
160
|
+
- spec/post_receive_hook_spec.rb
|
161
|
+
- spec/spec_helper.rb
|
162
|
+
- spec/tracker_client_spec.rb
|
163
|
+
- spec/utils_spec.rb
|