cerberus 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,5 +1,31 @@
1
1
  = Cerberus Changelog
2
2
 
3
+ == Version 0.3.3
4
+ Major changes
5
+
6
+ * Fix Const load problem with Rails 1.2RC1
7
+ * Correctly implement Jabber publisher using XMPP4R library
8
+ * Upgrade Webgen to 0.4.1
9
+ * Added 'getting better/worse' to build messages' subject
10
+ * Added possibility to configure events on what you would like to receive messages.
11
+ By default used 'default' events. It means all except 'successful' state.
12
+ You could set to this options list of any valid states such as [broken, failed, revival, successful, setup] or predefined sets as
13
+ [all, default, none].
14
+
15
+ You could configure by setting :on_event option to :publisher options branch, or to concrete publisher configuration.
16
+ In case if this option added both to :publisher and :publisher,<PUBLISHER> then concrete configurations wins.
17
+
18
+ Examples of configuration
19
+
20
+ publisher:
21
+ on_event: broken, revival
22
+ mail:
23
+ on_event: all
24
+ jabber:
25
+ #nothing here
26
+
27
+ In given example we would send messages about ALL events by mail and only messages about brokeness and revivalness by Jabber.
28
+
3
29
  == Version 0.3.2
4
30
  Added Perforce SCM support
5
31
 
data/Rakefile CHANGED
@@ -52,8 +52,8 @@ GEM_SPEC = Gem::Specification.new do |s|
52
52
 
53
53
  s.add_dependency 'actionmailer', '>= 1.2.5'
54
54
  s.add_dependency 'rake', '>= 0.7.1'
55
- s.add_dependency 'jabber4r', '>= 0.8.0'
56
- s.add_dependency 'Ruby-IRC', '>= 1.0.3'
55
+ s.add_dependency 'xmpp4r', '>= 0.3'
56
+ s.add_dependency 'Ruby-IRC', '>= 1.0.7'
57
57
 
58
58
  s.files = Dir.glob("{bin,lib,test}/**/*").delete_if { |item| item.include?('__workdir') }
59
59
  s.files += %w(LICENSE README CHANGES Rakefile)
@@ -143,7 +143,14 @@ task :publish_news do
143
143
  end
144
144
  end
145
145
 
146
- task :publish_site do
147
- system('cd doc/site && webgen')
146
+ require 'webgen/rake/webgentask'
147
+
148
+ Webgen::Rake::WebgenTask.new do |t|
149
+ t.directory = File.join(Dir.pwd, "doc/site")
150
+ end
151
+
152
+ task :publish_site => :webgen do
148
153
  sh %{scp -r -q doc/site/output/* #{RUBYFORGE_USER}@rubyforge.org:/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/}
149
154
  end
155
+
156
+ task :release => [:release_files, :publish_news, :webgen]
@@ -25,4 +25,8 @@ class Cerberus::Builder::Bjam
25
25
  $?.exitstatus == 0 and not @output =~ /failed|error:|skipped/
26
26
  #/\*\*\* \d+ failure(s)? detected in test suite/ and not @output.include?("syntax error")
27
27
  end
28
+
29
+ def brokeness
30
+ return nil
31
+ end
28
32
  end
@@ -1,7 +1,7 @@
1
1
  require 'cerberus/builder/base'
2
2
 
3
3
  class Cerberus::Builder::Maven2
4
- attr_reader :output
4
+ attr_reader :output, :brokeness
5
5
 
6
6
  def initialize(config)
7
7
  @config = config
@@ -23,7 +23,9 @@ class Cerberus::Builder::Maven2
23
23
  def add_error_information
24
24
  str = @output
25
25
  @output = ''
26
+ @brokeness = 0
26
27
  while str =~ / <<< FAILURE!$/
28
+ @brokeness += 1
27
29
  s = $'
28
30
 
29
31
  $` =~ /^(.|\n)*Running (.*)$/
@@ -19,6 +19,12 @@ class Cerberus::Builder::RubyBase
19
19
  $?.exitstatus == 0 and not @output.include?("#{@cmd} aborted!")
20
20
  end
21
21
 
22
+ def brokeness
23
+ if @output =~ /\d+ tests, \d+ assertions, (\d+) failures, (\d+) errors/
24
+ $1.to_i + $2.to_i
25
+ end
26
+ end
27
+
22
28
  private
23
29
  def choose_exec
24
30
  ext = ['']
@@ -56,7 +56,7 @@ module Cerberus
56
56
  end
57
57
 
58
58
  HELP = %{
59
- Cerberus is a simple Continuous Integration tool for Ruby projects that run from command-line interface.
59
+ Cerberus is a lightweight command-line Continuous Integration tool for Ruby.
60
60
 
61
61
  Usage:
62
62
  cerberus add <URL> --- add project from svn repository to list watched of applications
@@ -0,0 +1,63 @@
1
+ module Cerberus
2
+ module SCM
3
+ TYPES = {
4
+ :svn => 'SVN', #Cerberus::SCM
5
+ :darcs => 'Darcs',
6
+ :perforce => 'Perforce'
7
+ }
8
+
9
+ def self.get(type)
10
+ class_name = TYPES[type.to_sym]
11
+ say "SCM #{type} not supported" unless class_name
12
+ require "cerberus/scm/#{type}"
13
+ const_get(class_name)
14
+ end
15
+
16
+
17
+ def self.guess_type(path)
18
+ return nil unless test(?d, path)
19
+
20
+ case
21
+ when test(?d, path+'/.svn')
22
+ 'svn'
23
+ when test(?d, path+'/_darcs')
24
+ 'darcs'
25
+ when test(?d, path+'/.cvs')
26
+ 'cvs'
27
+ end
28
+ end
29
+ end
30
+
31
+ module Publisher
32
+ TYPES = {
33
+ :mail => 'Mail', #Cerberus::Publisher
34
+ :jabber => 'Jabber',
35
+ :irc => 'IRC',
36
+ :rss => 'RSS',
37
+ :campfire => 'Campfire'
38
+ }
39
+
40
+ def self.get(type)
41
+ class_name = TYPES[type.to_sym]
42
+ say "Publisher #{type} not supported" unless class_name
43
+ require "cerberus/publisher/#{type}"
44
+ const_get(class_name)
45
+ end
46
+ end
47
+
48
+ module Builder
49
+ TYPES = {
50
+ :maven2 => 'Maven2', #Cerberus::Builder
51
+ :rake => 'Rake',
52
+ :rant => 'Rant',
53
+ :bjam => 'Bjam'
54
+ }
55
+
56
+ def self.get(type)
57
+ class_name = TYPES[type.to_sym]
58
+ say "Builder #{type} not supported" unless class_name
59
+ require "cerberus/builder/#{type}"
60
+ const_get(class_name)
61
+ end
62
+ end
63
+ end
@@ -8,10 +8,8 @@ publisher:
8
8
  user_name: someuser
9
9
  password: somepassword
10
10
  # jabber:
11
- # jid: cerberus@gtalk.google.com
12
- # port: 5222
13
- # password: mypass
14
- # digest: false
11
+ # jid: somemailbox@gmail.com/cerberus
12
+ # password: somepassword
15
13
  # irc:
16
14
  # nick: cerb
17
15
  # server: irc.freenode.net
@@ -4,5 +4,5 @@ module Cerberus
4
4
 
5
5
  LOCK_WAIT = 30 * 60 #30 minutes
6
6
 
7
- VERSION = '0.3.2'
7
+ VERSION = '0.3.3'
8
8
  end
@@ -8,7 +8,7 @@ module Cerberus
8
8
  modif_time = File::Stat.new(lock_file).mtime
9
9
  ttl = options[:lock_ttl]
10
10
 
11
- if ttl and modif_time < ttl.ago
11
+ if ttl and modif_time + ttl < Time.now
12
12
  File.delete(lock_file)
13
13
  else
14
14
  return
@@ -4,6 +4,7 @@ require 'cerberus/utils'
4
4
  require 'cerberus/constants'
5
5
  require 'cerberus/config'
6
6
  require 'cerberus/latch'
7
+ require 'cerberus/component_lazy_loader'
7
8
 
8
9
  module Cerberus
9
10
  class AddCommand
@@ -15,7 +16,7 @@ module Cerberus
15
16
  end
16
17
 
17
18
  def run
18
- scm_type = @cli_options[:scm] || 'svn'
19
+ scm_type = @cli_options[:scm] || Cerberus::SCM.guess_type(@path) || 'svn'
19
20
  scm = Cerberus::SCM.get(scm_type).new(@path, Config.new(nil, @cli_options))
20
21
  say "Can't find any #{scm_type} application under #{@path}" unless scm.url
21
22
 
@@ -67,7 +68,7 @@ module Cerberus
67
68
  @config = Config.new(application_name, cli_options.merge(def_options))
68
69
  @config.merge!(DEFAULT_CONFIG, false)
69
70
 
70
- @status = Status.new("#{app_root}/status.log")
71
+ @status = Status.read("#{app_root}/status.log")
71
72
 
72
73
  scm_type = @config[:scm, :type]
73
74
  @scm = SCM.get(scm_type).new(@config[:application_root], @config)
@@ -80,48 +81,47 @@ module Cerberus
80
81
  def run
81
82
  begin
82
83
  Latch.lock("#{HOME}/work/#{@config[:application_name]}/.lock", :lock_ttl => 2 * LOCK_WAIT) do
83
- previous_status = @status.recall
84
84
  @scm.update!
85
85
 
86
- state =
87
- if @scm.has_changes? or @config[:force] or not previous_status
88
- if status = @builder.run
89
- @status.keep(:succesful)
90
- case previous_status
91
- when :failed
92
- :revival
93
- when :succesful
94
- :succesful
95
- when false
96
- :setup
97
- end
98
- else
99
- @status.keep(:failed)
100
- previous_status == :failed ? :broken : :failure
101
- end
102
- else
103
- :unchanged
104
- end
86
+ if @scm.has_changes? or @config[:force] or @status.previous_build_successful.nil?
87
+ build_successful = @builder.run
88
+ @status.keep(build_successful, @scm.current_revision, @builder.brokeness)
105
89
 
106
- #Save logs to directory
107
- if @config[:log, :enable] and state != :unchanged
108
- log_dir = "#{HOME}/work/#{@config[:application_name]}/logs/"
109
- FileUtils.mkpath(log_dir)
90
+ #Save logs to directory
91
+ if @config[:log, :enable]
92
+ log_dir = "#{HOME}/work/#{@config[:application_name]}/logs/"
93
+ FileUtils.mkpath(log_dir)
110
94
 
111
- time = Time.now.strftime("%Y%m%d%H%M%S")
112
- file_name = "#{log_dir}/#{time}-#{state.to_s}.log"
113
- body = [ scm.last_commit_message, builder.output ].join("\n\n")
114
- IO.write(file_name, body)
115
- end
95
+ time = Time.now.strftime("%Y%m%d%H%M%S")
96
+ file_name = "#{log_dir}/#{time}-#{@status.current_state.to_s}.log"
97
+ body = [ scm.last_commit_message, builder.output ].join("\n\n")
98
+ IO.write(file_name, body)
99
+ end
116
100
 
117
- #send notifications
118
- if [:failure, :broken, :revival, :setup].include?(state)
101
+ #send notifications
119
102
  active_publishers = get_configuration_option(@config[:publisher], :active, 'mail')
120
103
  active_publishers.split(/\W+/).each do |pub|
121
- raise "Publisher have no configuration: #{pub}" unless @config[:publisher, pub]
122
- Publisher.get(pub).publish(state, self, @config)
104
+
105
+ publisher_config = @config[:publisher, pub]
106
+ raise "Publisher have no configuration: #{pub}" unless publisher_config
107
+
108
+ on_event = publisher_config[:on_event] || @config[:publisher, :on_event] || 'default'
109
+ events =
110
+ case on_event
111
+ when 'all'
112
+ [:setup, :successful, :revival, :broken, :failed]
113
+ when 'none'
114
+ []
115
+ when 'default'
116
+ [:setup, :revival, :broken, :failed] #the same as 'all' except successful
117
+ else
118
+ on_event.scan(/\w+/).map{|s| s.to_sym}
119
+ end
120
+
121
+ Publisher.get(pub).publish(@status, self, @config) if events.include?(@status.current_state)
123
122
  end
124
123
  end
124
+
125
125
  end #lock
126
126
  rescue Exception => e
127
127
  if ENV['CERBERUS_ENV'] == 'TEST'
@@ -129,7 +129,7 @@ module Cerberus
129
129
  else
130
130
  File.open("#{HOME}/error.log", File::WRONLY|File::APPEND|File::CREAT) do |f|
131
131
  f.puts Time.now.strftime("%a, %d %b %Y %H:%M:%S [#{@config[:application_name]}] -- #{e.class}")
132
- f.puts e.message unless e.message.blank?
132
+ f.puts e.message unless e.message.empty?
133
133
  f.puts e.backtrace.collect{|line| ' '*5 + line}
134
134
  f.puts "\n"
135
135
  end
@@ -173,7 +173,7 @@ module Cerberus
173
173
  end
174
174
 
175
175
  class ListCommand
176
- def initialize(cli_options = {})
176
+ def initialize(cli_options = {})
177
177
  end
178
178
 
179
179
  def run
@@ -194,69 +194,84 @@ module Cerberus
194
194
  end
195
195
  end
196
196
 
197
+ #Fields that are contained in status file
198
+ # successful (true mean previous build was successful, otherwise - false)
199
+ # timestamp
200
+ # revision
201
+ # brokeness
202
+ # successful_build_timestamp
203
+ # successful_build_revision
197
204
  class Status
198
- def initialize(path)
199
- @path = path
200
- end
201
-
202
- def keep(status)
203
- File.open(@path, "w+", 0777) { |file| file.write(status.to_s) }
204
- end
205
-
206
- def recall
207
- return false unless File.exists?(@path)
208
- value = File.read(@path)
209
- value.empty? ? false : value.to_sym
205
+ attr_reader :previous_build_successful, :previous_brokeness, :current_build_successful, :current_brokeness
206
+
207
+ def initialize(param)
208
+ if param.is_a? Hash
209
+ @hash = param
210
+ @current_build_successful = @hash['state']
211
+ @already_kept = true
212
+ else
213
+ @path = param
214
+ value = File.exists?(@path) ? YAML.load(IO.read(@path)) : nil
215
+
216
+ @hash =
217
+ case value
218
+ when String
219
+ value = %w(succesful successful setup).include?(value) #fix typo in status values
220
+ {'successful' => value}
221
+ when nil
222
+ {}
223
+ else
224
+ #TODO remove it before 0.3.3 release
225
+ if state = value['state']
226
+ value['successful'] = %w(succesful successful setup).include?(state)
227
+ end
228
+
229
+ value
230
+ end
231
+
232
+ @already_kept = false
233
+ end
234
+
235
+ @previous_build_successful = @hash['successful']
236
+ @previous_brokeness = @hash['brokeness']
210
237
  end
211
- end
212
- end
213
238
 
214
- module Cerberus
215
- module SCM
216
- TYPES = {
217
- :svn => 'SVN', #Cerberus::SCM
218
- :darcs => 'Darcs',
219
- :perforce => 'Perforce'
220
- }
221
-
222
- def self.get(type)
223
- class_name = TYPES[type.to_sym]
224
- say "SCM #{type} not supported" unless class_name
225
- require "cerberus/scm/#{type}"
226
- const_get(class_name)
239
+ def self.read(file_name)
240
+ Status.new(file_name)
227
241
  end
228
- end
229
242
 
230
- module Publisher
231
- TYPES = {
232
- :mail => 'Mail', #Cerberus::Publisher
233
- :jabber => 'Jabber',
234
- :irc => 'IRC',
235
- :rss => 'RSS',
236
- :campfire => 'Campfire'
237
- }
238
-
239
- def self.get(type)
240
- class_name = TYPES[type.to_sym]
241
- say "Publisher #{type} not supported" unless class_name
242
- require "cerberus/publisher/#{type}"
243
- const_get(class_name)
243
+ def keep(build_successful, revision, brokeness)
244
+ raise 'Status could be kept only once. Please try to reread status file.' if @already_kept
245
+
246
+ @current_brokeness = brokeness
247
+ @current_build_successful = build_successful
248
+
249
+ hash = {'successful' => @current_build_successful, 'timestamp' => Time.now, 'revision' => revision, 'brokeness' => brokeness}
250
+ if build_successful
251
+ hash['successful_build_timestamp'] = Time.now
252
+ hash['successful_build_revision'] = revision
253
+ else
254
+ hash['successful_build_timestamp'] = @hash['successful_build_timestamp']
255
+ hash['successful_build_revision'] = @hash['successful_build_revision']
256
+ end
257
+
258
+ File.open(@path, "w+", 0777) { |file| file.write(YAML.dump(hash)) }
259
+
260
+ @already_kept = true
244
261
  end
245
- end
246
262
 
247
- module Builder
248
- TYPES = {
249
- :maven2 => 'Maven2', #Cerberus::Builder
250
- :rake => 'Rake',
251
- :rant => 'Rant',
252
- :bjam => 'Bjam'
253
- }
254
-
255
- def self.get(type)
256
- class_name = TYPES[type.to_sym]
257
- say "Builder #{type} not supported" unless class_name
258
- require "cerberus/builder/#{type}"
259
- const_get(class_name)
263
+ def current_state
264
+ raise "Invalid project state. Before calculating status please do keeping of it." unless @already_kept
265
+
266
+ if @current_build_successful
267
+ if @previous_build_successful.nil?
268
+ :setup
269
+ else
270
+ @previous_build_successful ? :successful : :revival
271
+ end
272
+ else
273
+ @previous_build_successful ? :failed : :broken
274
+ end
260
275
  end
261
276
  end
262
- end
277
+ end
@@ -5,17 +5,31 @@ module Cerberus
5
5
  class Base
6
6
  def self.formatted_message(state, manager, options)
7
7
  subject =
8
- case state
8
+ case state.current_state
9
9
  when :setup
10
10
  "Cerberus set up for project (##{manager.scm.current_revision})"
11
11
  when :broken
12
- "Build still broken (##{manager.scm.current_revision})"
13
- when :failure
12
+ additional_message = nil
13
+ if state.previous_brokeness and state.current_brokeness
14
+ additional_message =
15
+ case
16
+ when state.previous_brokeness > state.current_brokeness
17
+ ' but getting better'
18
+ when state.previous_brokeness < state.current_brokeness
19
+ ' and getting worse'
20
+ end
21
+ end
22
+ "Build still broken#{additional_message} (##{manager.scm.current_revision})"
23
+
24
+ #FIXME instead of using last author as person that broken build try to guess it. I.e. only if one author since last commit did commit - then he broken it.
25
+ when :failed
14
26
  "Build broken by #{manager.scm.last_author} (##{manager.scm.current_revision})"
15
27
  when :revival
16
28
  "Build fixed by #{manager.scm.last_author} (##{manager.scm.current_revision})"
17
- else
18
- raise "Unknown build state #{state}"
29
+ when :revival
30
+ "Build was successfully built (##{manager.scm.current_revision})"
31
+ else
32
+ raise "Unknown build state '#{state.current_state.to_s}'"
19
33
  end
20
34
 
21
35
  subject = "[#{options[:application_name]}] #{subject}"
@@ -3,6 +3,8 @@ require 'IRC'
3
3
  require 'cerberus/publisher/base'
4
4
 
5
5
  class Cerberus::Publisher::IRC < Cerberus::Publisher::Base
6
+ class << self; include Cerberus::Utils end
7
+
6
8
  def self.publish(state, manager, options)
7
9
  irc_options = options[:publisher, :irc]
8
10
  raise "There is no channel provided for IRC publisher" unless irc_options[:channel]
@@ -21,11 +23,7 @@ class Cerberus::Publisher::IRC < Cerberus::Publisher::Base
21
23
  }
22
24
  bot.send_quit
23
25
  }
24
- begin
25
- bot.connect #Why it always fails?
26
- rescue Exception => e
27
- puts e.message
28
- end
26
+ bot.connect
29
27
  }
30
28
  end
31
29
  end
@@ -1,5 +1,5 @@
1
1
  require 'rubygems'
2
- require 'jabber4r/jabber4r'
2
+ require 'xmpp4r'
3
3
  require 'cerberus/publisher/base'
4
4
 
5
5
  class Cerberus::Publisher::Jabber < Cerberus::Publisher::Base
@@ -10,26 +10,16 @@ class Cerberus::Publisher::Jabber < Cerberus::Publisher::Base
10
10
 
11
11
  subject,body = Cerberus::Publisher::Base.formatted_message(state, manager, options)
12
12
 
13
- session = login(jabber_options[:jid], jabber_options[:password])
13
+ client = Jabber::Client::new(Jabber::JID.new(jabber_options[:jid]))
14
+ client.connect
15
+ client.auth(jabber_options[:password])
16
+
14
17
  jabber_options[:recipients].split(',').each do |address|
15
- session.new_message(address.strip).set_subject(subject).set_body(body).send
18
+ message = Jabber::Message::new(address.strip, body).set_subject(subject)
19
+ client.send(message)
16
20
  end
17
21
  ensure
18
- session.release if session
19
- end
20
- end
21
-
22
- def self.login(id_resource, password, register_if_login_fails=true)
23
- begin
24
- session = ::Jabber::Session.bind(id_resource, password)
25
- rescue
26
- if(register_if_login_fails)
27
- if(::Jabber::Session.register(id_resource, password))
28
- Cerberus::Publisher::Jabber.login(id_resource, password, false)
29
- else
30
- raise "Failed to register #{id_resource}"
31
- end
32
- end
22
+ client.close if client
33
23
  end
34
24
  end
35
25
  end
@@ -62,40 +62,49 @@ class FunctionalTest < Test::Unit::TestCase
62
62
 
63
63
  status_file = HOME + '/work/myapp/status.log'
64
64
  assert File.exists?(status_file)
65
- assert_equal 'succesful', IO.read(status_file)
66
- assert 1, Dir[HOME + "/work/rake_cust/logs/*-succesful.log"].size
65
+ assert build_successful?(status_file)
66
+ assert 1, Dir[HOME + "/work/rake_cust/logs/*-setup.log"].size
67
67
 
68
68
  FileUtils.rm status_file
69
69
  build = Cerberus::BuildCommand.new('myapp')
70
70
  build.run
71
71
  assert File.exists?(status_file)
72
+ assert build_successful?(status_file)
73
+ assert_equal :setup, build.status.current_state
72
74
  assert_equal 2, ActionMailer::Base.deliveries.size #first email that project was setup
73
75
  assert 2, Dir[HOME + "/work/rake_cust/logs/*.log"].size
74
76
 
75
- build = Cerberus::BuildCommand.new('myapp')
77
+ build = Cerberus::BuildCommand.new('myapp', :force => true)
76
78
  build.run
79
+ assert_equal :successful, build.status.current_state
77
80
  assert_equal 2, ActionMailer::Base.deliveries.size #Number of mails not changed
78
81
  assert 2, Dir[HOME + "/work/rake_cust/logs/*.log"].size #even if sources unchanged
79
82
 
80
83
  #remove status file to run project again
81
84
  FileUtils.rm status_file
82
- add_test_case_to_project('myapp', 'assert false') { #if assertion failed
83
- build = Cerberus::BuildCommand.new('myapp')
84
- build.run
85
-
86
- assert_equal 'failed', IO.read(status_file)
87
- }
85
+ add_test_case_to_project('myapp', 'assert false') #if assertion failed
86
+ build = Cerberus::BuildCommand.new('myapp')
87
+ build.run
88
+ assert !build_successful?(status_file)
89
+ assert_equal :broken, build.status.current_state
88
90
  assert_equal 3, ActionMailer::Base.deliveries.size #We should receive mail if project fails
89
91
 
90
92
 
93
+ add_test_case_to_project('myapp', 'raise "Some exception here"') #if we have exception
94
+ build = Cerberus::BuildCommand.new('myapp', :force => true)
95
+ build.run
96
+ assert !build_successful?(status_file)
97
+ assert_equal :broken, build.status.current_state
98
+
99
+ subject = ActionMailer::Base.deliveries.last.subject
100
+ assert_match /and getting worse/, subject
101
+
91
102
  #remove status file to run project again
92
103
  FileUtils.rm status_file
93
- add_test_case_to_project('myapp', 'raise "Some exception here"') { #if we have exception
94
- build = Cerberus::BuildCommand.new('myapp')
95
- build.run
96
-
97
- assert_equal 'failed', IO.read(status_file)
98
- }
104
+ build = Cerberus::BuildCommand.new('myapp')
105
+ build.run
106
+ assert !build_successful?(status_file)
107
+ assert_equal :broken, build.status.current_state
99
108
  end
100
109
 
101
110
  def test_have_no_awkward_header
@@ -108,6 +117,19 @@ class FunctionalTest < Test::Unit::TestCase
108
117
  assert_equal 0, build.scm.last_commit_message.index('-' * 72)
109
118
  end
110
119
 
120
+ def test_send_on_different_events
121
+ add_application('myapp', SVN_URL, 'publisher' => {'mail' => {'on_event' => 'none'}, 'on_event' => 'all'})
122
+ build = Cerberus::BuildCommand.new('myapp')
123
+ build.run
124
+ assert_equal 0, ActionMailer::Base.deliveries.size
125
+
126
+
127
+ add_application('myapp', SVN_URL, 'publisher' => {'mail' => {'on_event' => 'all'}, 'on_event' => 'none'})
128
+ build = Cerberus::BuildCommand.new('myapp')
129
+ build.run
130
+ assert_equal 1, ActionMailer::Base.deliveries.size
131
+ end
132
+
111
133
  def test_multiply_publishers_without_configuration
112
134
  add_application('myapp', SVN_URL, 'publisher' => {'active' => 'mail , jabber , irc, dddd'})
113
135
 
@@ -148,7 +170,7 @@ class FunctionalTest < Test::Unit::TestCase
148
170
  for i in 1..4 do
149
171
  status_file = HOME + "/work/myapp#{i}/status.log"
150
172
  assert File.exists?(status_file)
151
- assert_equal 'succesful', IO.read(status_file)
173
+ assert build_successful?(status_file)
152
174
  end
153
175
  end
154
176
 
@@ -187,7 +209,7 @@ class FunctionalTest < Test::Unit::TestCase
187
209
 
188
210
  status_file = HOME + '/work/darcsapp/status.log'
189
211
  assert File.exists?(status_file)
190
- assert_equal 'succesful', IO.read(status_file)
212
+ assert build_successful?(status_file)
191
213
  assert 1, Dir[HOME + "/work/darcsapp/logs/*.log"].size
192
214
 
193
215
  #There were no changes - no reaction should be
@@ -244,4 +266,22 @@ class FunctionalTest < Test::Unit::TestCase
244
266
 
245
267
  assert_equal 2, Marshmallow.counter
246
268
  end
269
+
270
+ def test_correct_migration_from_previous_status
271
+ status_fn = TEMP_DIR + '/test_status_file.log'
272
+
273
+ status = Cerberus::Status.new(status_fn)
274
+ assert_equal nil, status.previous_build_successful
275
+ assert_equal nil, status.current_build_successful
276
+
277
+ IO.write(status_fn, 'failed')
278
+ status = Cerberus::Status.new(status_fn)
279
+ assert_equal nil, status.current_build_successful
280
+ assert_equal false, status.previous_build_successful
281
+
282
+ status.keep(true, 1232, 0)
283
+ assert_equal true, status.current_build_successful
284
+ assert_equal false, status.previous_build_successful
285
+ assert_equal :revival, status.current_state
286
+ end
247
287
  end
@@ -48,7 +48,7 @@ class IntegrationTest < Test::Unit::TestCase
48
48
 
49
49
  run_cerb("build svn_repo")
50
50
  assert File.exists?(HOME + '/work/svn_repo/status.log')
51
- assert_equal 'succesful', IO.read(HOME + '/work/svn_repo/status.log')
51
+ assert build_successful?(HOME + '/work/svn_repo/status.log')
52
52
  end
53
53
 
54
54
  def test_add_darcs_scm
@@ -10,8 +10,9 @@ class IRCPublisherTest < Test::Unit::TestCase
10
10
  options = Cerberus::Config.new(nil, :publisher => {:irc => {:channel => 'hello'}}, :application_name => 'IrcApp')
11
11
  build = DummyManager.new('last message', 'this is output', 1232, 'anatol')
12
12
 
13
- Cerberus::Publisher::IRC.publish(:setup, build, options)
13
+ Cerberus::Publisher::IRC.publish(build_status(true), build, options)
14
14
 
15
15
  assert IRCConnection.connected
16
+ # assert_equal 1, IRCConnection.messages.size
16
17
  end
17
18
  end
@@ -1,20 +1,21 @@
1
1
  require File.dirname(__FILE__) + '/test_helper'
2
2
 
3
3
  require 'cerberus/publisher/jabber'
4
- require 'mock/jabber4r'
4
+ require 'mock/xmpp4r'
5
5
  require 'mock/manager'
6
6
 
7
7
  class JabberPublisherTest < Test::Unit::TestCase
8
8
  def test_publisher
9
- options = Cerberus::Config.new(nil, :publisher => {:jabber => {:recipients => ' jit1@google.com, another@google.com '}}, :application_name => 'MegaApp')
9
+ options = Cerberus::Config.new(nil, :publisher => {:jabber => {:jid=>'from.cerberus@gmail.com', :recipients => ' jit1@google.com, another@google.com '}}, :application_name => 'MegaApp')
10
10
  build = DummyManager.new('last message', 'this is output', 1232, 'anatol')
11
11
 
12
- Cerberus::Publisher::Jabber.publish(:setup, build, options)
12
+ Cerberus::Publisher::Jabber.publish(build_status(false), build, options)
13
13
 
14
- messages = Jabber::Protocol::Message.messages
15
- assert_equal 2, messages.size
16
- assert_equal 'google.com', messages[0].to.host
14
+ messages = Jabber::Client.messages
15
+ assert messages.size > 2
16
+ assert_equal 'google.com', messages[0].to.domain
17
17
  assert_equal 'jit1', messages[0].to.node
18
- assert_equal '[MegaApp] Cerberus set up for project (#1232)', messages[0].subject
18
+ assert_equal '[MegaApp] Build still broken (#1232)', messages[0].subject
19
+ assert !messages[0].body.nil?
19
20
  end
20
21
  end
@@ -14,7 +14,7 @@ class MailPublisherTest < Test::Unit::TestCase
14
14
  :application_name => 'MyApp')
15
15
  build = DummyManager.new('last message', 'this is output', 1232, 'anatol')
16
16
 
17
- Cerberus::Publisher::Mail.publish(:setup, build, options)
17
+ Cerberus::Publisher::Mail.publish(build_status(true), build, options)
18
18
 
19
19
  mails = ActionMailer::Base.deliveries
20
20
  assert_equal 1, mails.size
@@ -14,7 +14,7 @@ class IRCConnection
14
14
  @@messages << msg
15
15
  end
16
16
 
17
- def self.handle_connection(server, port)
17
+ def self.handle_connection(server, port, nick, realname)
18
18
  @@connected = true
19
19
  end
20
20
  end
@@ -0,0 +1,19 @@
1
+ require 'xmpp4r'
2
+
3
+ class Jabber::Client
4
+ @@messages = []
5
+
6
+ def connect
7
+ end
8
+
9
+ def send(message)
10
+ @@messages << message
11
+ end
12
+
13
+ def self.messages
14
+ @@messages
15
+ end
16
+
17
+ def auth(pwd)
18
+ end
19
+ end
@@ -10,11 +10,11 @@ class RSSPublisherTest < Test::Unit::TestCase
10
10
  options = Cerberus::Config.new(nil, :publisher => {:rss => {:file => rss_file.path}}, :application_name => 'RSS<App')
11
11
  build = DummyManager.new('last message', 'this is output', 1235, 'anatol')
12
12
 
13
- Cerberus::Publisher::RSS.publish(:setup, build, options)
13
+ Cerberus::Publisher::RSS.publish(build_status(false), build, options)
14
14
 
15
15
  xml = REXML::Document.new(IO.read(rss_file.path))
16
16
 
17
- assert_equal '[RSS<App] Cerberus set up for project (#1235)', xml.elements["rss/channel/item/title/"].get_text.value
17
+ assert_equal '[RSS<App] Build still broken (#1235)', xml.elements["rss/channel/item/title/"].get_text.value
18
18
  assert_match %r{<pre>last message\nthis is output\n--\nCerberus 0.\d.\d, http://cerberus.rubyforge.org/</pre>},
19
19
  xml.elements["rss/channel/item/description/"].get_text.value
20
20
  end
@@ -1,4 +1,5 @@
1
1
  $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+ $:.unshift File.expand_path(File.dirname(__FILE__))
2
3
 
3
4
  require 'test/unit'
4
5
  require 'fileutils'
@@ -57,9 +58,10 @@ class A#{rand(10000)}Test < Test::Unit::TestCase
57
58
  end"
58
59
  }
59
60
 
60
- yield
61
-
62
- FileUtils.rm test_case_name
61
+ if block_given?
62
+ yield
63
+ FileUtils.rm test_case_name
64
+ end
63
65
  end
64
66
 
65
67
  def add_application(app_name, url, options = {})
@@ -71,6 +73,8 @@ end"
71
73
  opt.deep_merge!(options)
72
74
 
73
75
  dump_yml(HOME + "/config/#{app_name}.yml", opt)
76
+
77
+ FileUtils.rm_rf HOME + "/work/#{app_name}"
74
78
  end
75
79
 
76
80
  def add_config(options)
@@ -88,6 +92,16 @@ end"
88
92
  # Create the new method
89
93
  klass.send(:define_method, method_name, block)
90
94
  end
95
+
96
+ def build_successful?(file_name)
97
+ data = YAML.load(IO.read(file_name))
98
+ assert_kind_of Hash, data
99
+ data['successful']
100
+ end
101
+
102
+ def build_status(successful)
103
+ Cerberus::Status.new('state' => successful)
104
+ end
91
105
  end
92
106
 
93
107
  require 'cerberus/config'
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0.4
2
+ rubygems_version: 0.9.0.8
3
3
  specification_version: 1
4
4
  name: cerberus
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.3.2
7
- date: 2006-12-04 00:00:00 +03:00
6
+ version: 0.3.3
7
+ date: 2007-01-25 00:00:00 +03:00
8
8
  summary: Cerberus is a Continuous Integration tool that could be easily run from Cron.
9
9
  require_paths:
10
10
  - lib
@@ -33,6 +33,7 @@ files:
33
33
  - lib/cerberus
34
34
  - lib/cerberus/builder
35
35
  - lib/cerberus/cli.rb
36
+ - lib/cerberus/component_lazy_loader.rb
36
37
  - lib/cerberus/config.example.yml
37
38
  - lib/cerberus/config.rb
38
39
  - lib/cerberus/config_migration.rb
@@ -77,9 +78,9 @@ files:
77
78
  - test/data/darcs.zip
78
79
  - test/data/subversion.dump
79
80
  - test/mock/irc.rb
80
- - test/mock/jabber4r.rb
81
81
  - test/mock/manager.rb
82
82
  - test/mock/marshmallow.rb
83
+ - test/mock/xmpp4r.rb
83
84
  - LICENSE
84
85
  - README
85
86
  - CHANGES
@@ -117,13 +118,13 @@ dependencies:
117
118
  version: 0.7.1
118
119
  version:
119
120
  - !ruby/object:Gem::Dependency
120
- name: jabber4r
121
+ name: xmpp4r
121
122
  version_requirement:
122
123
  version_requirements: !ruby/object:Gem::Version::Requirement
123
124
  requirements:
124
125
  - - ">="
125
126
  - !ruby/object:Gem::Version
126
- version: 0.8.0
127
+ version: "0.3"
127
128
  version:
128
129
  - !ruby/object:Gem::Dependency
129
130
  name: Ruby-IRC
@@ -132,5 +133,5 @@ dependencies:
132
133
  requirements:
133
134
  - - ">="
134
135
  - !ruby/object:Gem::Version
135
- version: 1.0.3
136
+ version: 1.0.7
136
137
  version:
@@ -1,24 +0,0 @@
1
- class Jabber::Session
2
- def self.bind(jid, password)
3
- Jabber::Session.new
4
- end
5
-
6
- def initialize
7
- end
8
- end
9
-
10
- class Jabber::Protocol::Message
11
- @@messages = []
12
-
13
- def self.messages
14
- @@messages
15
- end
16
-
17
- def self.clear
18
- @@messages = []
19
- end
20
-
21
- def send
22
- @@messages << self
23
- end
24
- end