cerberus 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/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