git_hooks 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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,2 @@
1
+ require 'git_hooks/notifier/jabber_client'
2
+ require 'git_hooks/notifier/tracker_client'
@@ -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,13 @@
1
+ require 'git_hooks/utils/config'
2
+
3
+ module GitHooks
4
+ module Utils
5
+
6
+ class <<self
7
+ def hostname
8
+ `hostname -s`.strip
9
+ end
10
+ end
11
+
12
+ end
13
+ 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
@@ -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
@@ -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
@@ -0,0 +1,9 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Utils" do
4
+
5
+ it "should find out the hostname" do
6
+ GitHooks::Utils.hostname.should_not be(nil)
7
+ end
8
+
9
+ end
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