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 +26 -0
- data/Rakefile +11 -4
- data/lib/cerberus/builder/bjam.rb +4 -0
- data/lib/cerberus/builder/maven2.rb +3 -1
- data/lib/cerberus/builder/ruby_base.rb +6 -0
- data/lib/cerberus/cli.rb +1 -1
- data/lib/cerberus/component_lazy_loader.rb +63 -0
- data/lib/cerberus/config.example.yml +2 -4
- data/lib/cerberus/constants.rb +1 -1
- data/lib/cerberus/latch.rb +1 -1
- data/lib/cerberus/manager.rb +109 -94
- data/lib/cerberus/publisher/base.rb +19 -5
- data/lib/cerberus/publisher/irc.rb +3 -5
- data/lib/cerberus/publisher/jabber.rb +8 -18
- data/test/functional_test.rb +57 -17
- data/test/integration_test.rb +1 -1
- data/test/irc_publisher_test.rb +2 -1
- data/test/jabber_publisher_test.rb +8 -7
- data/test/mail_publisher_test.rb +1 -1
- data/test/mock/irc.rb +1 -1
- data/test/mock/xmpp4r.rb +19 -0
- data/test/rss_publisher_test.rb +2 -2
- data/test/test_helper.rb +17 -3
- metadata +8 -7
- data/test/mock/jabber4r.rb +0 -24
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 '
|
56
|
-
s.add_dependency 'Ruby-IRC', '>= 1.0.
|
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
|
-
|
147
|
-
|
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]
|
@@ -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 = ['']
|
data/lib/cerberus/cli.rb
CHANGED
@@ -56,7 +56,7 @@ module Cerberus
|
|
56
56
|
end
|
57
57
|
|
58
58
|
HELP = %{
|
59
|
-
Cerberus is a
|
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:
|
12
|
-
#
|
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
|
data/lib/cerberus/constants.rb
CHANGED
data/lib/cerberus/latch.rb
CHANGED
data/lib/cerberus/manager.rb
CHANGED
@@ -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.
|
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
|
-
|
87
|
-
|
88
|
-
|
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
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
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
|
-
|
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
|
-
|
122
|
-
|
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.
|
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
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
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
|
-
|
215
|
-
|
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
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
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
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
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
|
-
|
13
|
-
|
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
|
-
|
18
|
-
|
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
|
-
|
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 '
|
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
|
-
|
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
|
-
|
18
|
+
message = Jabber::Message::new(address.strip, body).set_subject(subject)
|
19
|
+
client.send(message)
|
16
20
|
end
|
17
21
|
ensure
|
18
|
-
|
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
|
data/test/functional_test.rb
CHANGED
@@ -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
|
-
|
66
|
-
assert 1, Dir[HOME + "/work/rake_cust/logs/*-
|
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')
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
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
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
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
|
-
|
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
|
data/test/integration_test.rb
CHANGED
@@ -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
|
-
|
51
|
+
assert build_successful?(HOME + '/work/svn_repo/status.log')
|
52
52
|
end
|
53
53
|
|
54
54
|
def test_add_darcs_scm
|
data/test/irc_publisher_test.rb
CHANGED
@@ -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(
|
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/
|
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(
|
12
|
+
Cerberus::Publisher::Jabber.publish(build_status(false), build, options)
|
13
13
|
|
14
|
-
messages = Jabber::
|
15
|
-
|
16
|
-
assert_equal 'google.com', messages[0].to.
|
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]
|
18
|
+
assert_equal '[MegaApp] Build still broken (#1232)', messages[0].subject
|
19
|
+
assert !messages[0].body.nil?
|
19
20
|
end
|
20
21
|
end
|
data/test/mail_publisher_test.rb
CHANGED
@@ -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(
|
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
|
data/test/mock/irc.rb
CHANGED
data/test/mock/xmpp4r.rb
ADDED
data/test/rss_publisher_test.rb
CHANGED
@@ -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(
|
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]
|
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
|
data/test/test_helper.rb
CHANGED
@@ -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
|
-
|
61
|
-
|
62
|
-
|
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.
|
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.
|
7
|
-
date:
|
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:
|
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.
|
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.
|
136
|
+
version: 1.0.7
|
136
137
|
version:
|
data/test/mock/jabber4r.rb
DELETED
@@ -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
|