cerberus 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +19 -0
- data/README +24 -10
- data/Rakefile +28 -8
- data/doc/OPTIONS +45 -0
- data/lib/cerberus/builder/maven2.rb +2 -0
- data/lib/cerberus/builder/rake.rb +2 -0
- data/lib/cerberus/cli.rb +3 -3
- data/lib/cerberus/config.example.yml +23 -0
- data/lib/cerberus/config.rb +7 -2
- data/lib/cerberus/config_migration.rb +0 -0
- data/lib/cerberus/constants.rb +1 -1
- data/lib/cerberus/manager.rb +60 -93
- data/lib/cerberus/publisher/base.rb +29 -0
- data/lib/cerberus/publisher/irc.rb +26 -0
- data/lib/cerberus/publisher/jabber.rb +32 -0
- data/lib/cerberus/publisher/mail.rb +28 -0
- data/lib/cerberus/publisher/rss.rb +26 -0
- data/lib/cerberus/scm/cvs.rb +2 -0
- data/lib/cerberus/scm/darcs.rb +2 -0
- data/lib/cerberus/scm/svn.rb +53 -0
- data/lib/cerberus/utils.rb +9 -0
- data/lib/cerberus/version.rb +2 -2
- data/test/config_test.rb +2 -1
- data/test/functional_test.rb +20 -15
- data/test/integration_test.rb +5 -5
- data/test/irc_publisher_test.rb +17 -0
- data/test/jabber_publisher_test.rb +20 -0
- data/test/mail_publisher_test.rb +25 -0
- data/test/mock/build.rb +10 -0
- data/test/mock/irc.rb +20 -0
- data/test/mock/jabber4r.rb +24 -0
- data/test/rss_publisher_test.rb +19 -0
- data/test/test_helper.rb +13 -5
- metadata +47 -6
- data/lib/cerberus/notifier/email.rb +0 -47
data/CHANGES
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
= Cerberus Changelog
|
2
2
|
|
3
|
+
== Version 0.2.0
|
4
|
+
Config file was changed since 0.1.1 and you need regenerate config files.
|
5
|
+
Or change it by hands: see doc/OPTIONS file to list of all avalable options.
|
6
|
+
|
7
|
+
Changing required by advanced publishing mechanism. Now it is possible to add several published to one project.
|
8
|
+
|
9
|
+
Also added 3 new publishers.
|
10
|
+
Jabber Publisher - all notification sended via Jabber server
|
11
|
+
IRC publisher - messages sent to IRC channel
|
12
|
+
RSS Publisher - result of build Cerberus writes to file in RSS format.
|
13
|
+
This feature would be useful for big open project when many users would like to see results of test-run.
|
14
|
+
If you publish results as RSS - then any user could subscribe to channel.
|
15
|
+
|
16
|
+
|
17
|
+
* Added automatic subversion cleanup to avoid repository locking after Cedrberus process termination
|
18
|
+
* Added Jabber publisher
|
19
|
+
* Added IRC publisher
|
20
|
+
* Added RSS publisher
|
21
|
+
|
3
22
|
== Version 0.1.1
|
4
23
|
Minor improvements
|
5
24
|
|
data/README
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Cerberus is a Continuous
|
1
|
+
Cerberus is a Continuous Builder software. Cerberus could be periodically run from scheduler and check if application tests are broken. If it happens then Cerberus will send notification to developers. Cerberus perfectly works both on Windows and *nix platforms.
|
2
2
|
|
3
3
|
For more CI theory read this document from Martin Fowler
|
4
4
|
http://www.martinfowler.com/articles/continuousIntegration.html.
|
@@ -17,6 +17,16 @@ He guarded the gate to Hades (the Greek underworld) and ensured that the dead co
|
|
17
17
|
|
18
18
|
So Cerberus will guard your tests and not allow your project to go to the world of dead.
|
19
19
|
|
20
|
+
There is several solutions already present, why do you need to use Cerberus?
|
21
|
+
Main advantages of Cerberus over other solutions:
|
22
|
+
= Cerberus could be installed on any machine not only where SVN repository located.
|
23
|
+
= Cerberus works not only for Rails projects, but for any other Ruby (or better to say for projects that use Rake)
|
24
|
+
= Cerberus multiplatform solution: it runs excellent both on *nix and Windows.
|
25
|
+
= Cerberus distributed via RubyGems, so it is very easy to install and very easy to update to the latest available versin
|
26
|
+
= Cerberus very easy start to use. Just type 'cerberus add PROJECT_URL|PROJECT_DIR'
|
27
|
+
= Cerberus is lightweigt solution: mots of the time ruby process even not run - Rake runs only in case if changes in project found
|
28
|
+
|
29
|
+
|
20
30
|
To use Cerberus it is very easy. First install it. Easiest way to do it through RubyGems package manager.
|
21
31
|
|
22
32
|
'gem install cerberus'
|
@@ -31,12 +41,13 @@ as second parameter you could pass URL to subversion repository or directory wit
|
|
31
41
|
|
32
42
|
Go to ~./cerberus and edit config.yml file (only once after installing Cerberus). Enter your configuration options here like email server, password, user_name and other options. See ActiveMailer description - Cerberus uses it as notification layer. My config file looks like this
|
33
43
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
44
|
+
publisher:
|
45
|
+
mail:
|
46
|
+
address: mail.somesever.com
|
47
|
+
user_name: anatol
|
48
|
+
password: anatol
|
49
|
+
domain: somesever.com
|
50
|
+
authentication: login
|
40
51
|
|
41
52
|
Also check ~/.cerberus/config/<APPLICATION_NAME>.yml and make sure that you have right options.
|
42
53
|
|
@@ -44,8 +55,11 @@ And then run Cerberus
|
|
44
55
|
|
45
56
|
cerberus build APPLICATION_NAME #Run project
|
46
57
|
|
47
|
-
|
58
|
+
or
|
59
|
+
|
60
|
+
cerberus buildall #Run all available projects
|
48
61
|
|
49
|
-
But of course better run Cerberus automatically from Cron. Run Cerberus for project each 10 minutes would be ok.
|
50
62
|
|
51
|
-
|
63
|
+
It will check out latest sources and run tests for your application. If tests are broken - recipients will receive notifications.
|
64
|
+
|
65
|
+
But of course better run Cerberus automatically from Cron. Run Cerberus for project each 10 minutes would be ok.
|
data/Rakefile
CHANGED
@@ -28,7 +28,9 @@ end
|
|
28
28
|
|
29
29
|
desc "Clean all generated files"
|
30
30
|
task :clean => :clobber_package do
|
31
|
-
rm_rf
|
31
|
+
rm_rf "#{File.dirname(__FILE__)}/test/__workdir"
|
32
|
+
rm_rf "#{File.dirname(__FILE__)}/coverage"
|
33
|
+
rm_rf "#{File.dirname(__FILE__)}/doc/site/output"
|
32
34
|
end
|
33
35
|
|
34
36
|
|
@@ -49,11 +51,14 @@ GEM_SPEC = Gem::Specification.new do |s|
|
|
49
51
|
Cerberus could be easily invoked from Cron (for Unix) or nnCron (for Windows) utilities.
|
50
52
|
DESC
|
51
53
|
|
52
|
-
s.add_dependency 'actionmailer', '>= 1.2.
|
54
|
+
s.add_dependency 'actionmailer', '>= 1.2.3'
|
53
55
|
s.add_dependency 'rake', '>= 0.7.1'
|
56
|
+
s.add_dependency 'jabber4r', '>= 0.8.0'
|
57
|
+
s.add_dependency 'Ruby-IRC', '>= 1.0.3'
|
54
58
|
|
55
|
-
s.files = Dir.glob("{bin,
|
59
|
+
s.files = Dir.glob("{bin,lib,test}/**/*").delete_if { |item| item.include?('__workdir') }
|
56
60
|
s.files += %w(LICENSE README CHANGES Rakefile)
|
61
|
+
s.files += Dir.glob("doc/*").delete_if { |item| item.include?('__workdir') }
|
57
62
|
|
58
63
|
s.bindir = "bin"
|
59
64
|
s.executables = ["cerberus"]
|
@@ -90,12 +95,27 @@ end
|
|
90
95
|
|
91
96
|
desc "Look for TODO and FIXME tags in the code"
|
92
97
|
task :todo do
|
93
|
-
|
94
|
-
|
98
|
+
FileList.new(File.dirname(__FILE__)+'/**/*.rb').egrep(/#.*(FIXME|TODO|TBD|DEPRECATED)/i)
|
99
|
+
end
|
100
|
+
|
101
|
+
task :reinstall => [:uninstall, :install]
|
102
|
+
|
103
|
+
task :site_webgen do
|
104
|
+
sh %{pushd doc/site; webgen; scp -r output/* #{RUBY_FORGE_USER}@rubyforge.org:/var/www/gforge-projects/#{RUBY_FORGE_PROJECT}/; popd }
|
105
|
+
end
|
106
|
+
|
107
|
+
begin
|
108
|
+
require 'rcov/rcovtask'
|
109
|
+
Rcov::RcovTask.new do |t|
|
110
|
+
t.test_files = FileList['test/*_test.rb']
|
111
|
+
t.output_dir = File.dirname(__FILE__) + "/coverage"
|
112
|
+
t.verbose = true
|
95
113
|
end
|
114
|
+
rescue Object
|
96
115
|
end
|
97
116
|
|
98
|
-
task :
|
117
|
+
task :site_coverage => [:rcov] do
|
118
|
+
sh %{ scp -r test/coverage/* #{RUBY_FORGE_USER}@rubyforge.org:/var/www/gforge-projects/#{RUBY_FORGE_PROJECT}/coverage/ }
|
99
119
|
end
|
100
120
|
|
101
121
|
task :release_files => [:clean, :package] do
|
@@ -125,7 +145,7 @@ task :publish_news do
|
|
125
145
|
Rake::XForge::NewsPublisher.new(project) do |publisher|
|
126
146
|
publisher.user_name = RUBY_FORGE_USER
|
127
147
|
publisher.password = ENV['RUBYFORGE_PASSWORD']
|
128
|
-
publisher.subject = "Cerberus #{PKG_VERSION} Released"
|
129
|
-
publisher.details =
|
148
|
+
publisher.subject = "[ANN] Cerberus #{PKG_VERSION} Released"
|
149
|
+
publisher.details = IO.read(File.dirname(__FILE__) + '/README')
|
130
150
|
end
|
131
151
|
end
|
data/doc/OPTIONS
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
bin_path:
|
2
|
+
publisher:
|
3
|
+
active:
|
4
|
+
mail:
|
5
|
+
delivery_method: smtp C
|
6
|
+
address: mail.tut.by C
|
7
|
+
port: 2525 C
|
8
|
+
domain: C
|
9
|
+
user_name: anatol C
|
10
|
+
password: somepass C
|
11
|
+
authentication: login C
|
12
|
+
sender: "'Cerberus' <anatol2003@tut.by>" C
|
13
|
+
recipients: anatol.pomozov@gmail.com A
|
14
|
+
jabber:
|
15
|
+
jid: C
|
16
|
+
port: C
|
17
|
+
password: C
|
18
|
+
digest: C
|
19
|
+
recipients: A
|
20
|
+
irc:
|
21
|
+
nick: A
|
22
|
+
server: A
|
23
|
+
port: A
|
24
|
+
channel: A
|
25
|
+
rss:
|
26
|
+
file:
|
27
|
+
scm:
|
28
|
+
type: svn A
|
29
|
+
url: A
|
30
|
+
builder
|
31
|
+
type: rake #supported: maven2 A
|
32
|
+
rake: C
|
33
|
+
task: test CA
|
34
|
+
maven2:
|
35
|
+
|
36
|
+
|
37
|
+
L - Only for command line interface
|
38
|
+
C - Cerberus config
|
39
|
+
A - application level config
|
40
|
+
|
41
|
+
L
|
42
|
+
recipients (add)
|
43
|
+
verbose or quite ??(add, build)
|
44
|
+
application_name (add)
|
45
|
+
scm (add, default svn)
|
data/lib/cerberus/cli.rb
CHANGED
@@ -19,17 +19,17 @@ module Cerberus
|
|
19
19
|
when 'add'
|
20
20
|
path = args.shift || Dir.pwd
|
21
21
|
|
22
|
-
command = Cerberus::
|
22
|
+
command = Cerberus::AddCommand.new(path, cli_options)
|
23
23
|
command.run
|
24
24
|
when 'build'
|
25
25
|
say HELP if args.empty?
|
26
26
|
|
27
27
|
application_name = args.shift
|
28
28
|
|
29
|
-
command = Cerberus::
|
29
|
+
command = Cerberus::BuildCommand.new(application_name, cli_options)
|
30
30
|
command.run
|
31
31
|
when 'buildall'
|
32
|
-
command = Cerberus::
|
32
|
+
command = Cerberus::BuildAllCommand.new(cli_options)
|
33
33
|
command.run
|
34
34
|
end
|
35
35
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#Copy this file to config.yml and configure notification services
|
2
|
+
publisher:
|
3
|
+
active: mail jabber rss
|
4
|
+
mail:
|
5
|
+
delivery_method: smtp
|
6
|
+
address: smtp.mymail.com
|
7
|
+
port: 2525
|
8
|
+
domain: mymail.com
|
9
|
+
user_name: cerberus
|
10
|
+
password: somepass
|
11
|
+
authentication: plain
|
12
|
+
sender: "'Cerberus Builder' <cerberus@mymail.com>"
|
13
|
+
jabber:
|
14
|
+
jid: cerberus@gtalk.google.com
|
15
|
+
port: 5222
|
16
|
+
password: mypass
|
17
|
+
digest: false
|
18
|
+
irc:
|
19
|
+
nick: cerb
|
20
|
+
server: irc.freenode.net
|
21
|
+
channel: cerberus
|
22
|
+
rss:
|
23
|
+
file: /usr/www/rss.xml
|
data/lib/cerberus/config.rb
CHANGED
File without changes
|
data/lib/cerberus/constants.rb
CHANGED
data/lib/cerberus/manager.rb
CHANGED
@@ -5,10 +5,26 @@ require 'cerberus/utils'
|
|
5
5
|
require 'cerberus/constants'
|
6
6
|
require 'cerberus/config'
|
7
7
|
|
8
|
-
require 'cerberus/
|
8
|
+
require 'cerberus/publisher/mail'
|
9
|
+
require 'cerberus/publisher/jabber'
|
10
|
+
require 'cerberus/publisher/irc'
|
11
|
+
require 'cerberus/publisher/rss'
|
12
|
+
require 'cerberus/scm/svn'
|
9
13
|
|
10
14
|
module Cerberus
|
11
|
-
|
15
|
+
SCM_TYPES = {
|
16
|
+
'svn' => Cerberus::SCM::SVN
|
17
|
+
}
|
18
|
+
|
19
|
+
PUBLISHER_TYPES = {
|
20
|
+
:mail => Cerberus::Publisher::Mail,
|
21
|
+
:jabber => Cerberus::Publisher::Jabber,
|
22
|
+
:irc => Cerberus::Publisher::IRC,
|
23
|
+
:rss => Cerberus::Publisher::RSS
|
24
|
+
}
|
25
|
+
|
26
|
+
class AddCommand
|
27
|
+
EXAMPLE_CONFIG = File.expand_path(File.dirname(__FILE__) + '/config.example.yml')
|
12
28
|
include Cerberus::Utils
|
13
29
|
|
14
30
|
def initialize(path, cli_options = {})
|
@@ -16,19 +32,23 @@ module Cerberus
|
|
16
32
|
end
|
17
33
|
|
18
34
|
def run
|
19
|
-
|
20
|
-
say "
|
35
|
+
scm_type = @config[:scm] || 'svn'
|
36
|
+
say "SCM #{scm_type} not supported" unless SCM_TYPES[scm_type]
|
37
|
+
|
38
|
+
scm = SCM_TYPES[scm_type].new(@path, @config)
|
39
|
+
say "Can't find any #{scm_type} application under #{@path}" unless scm.url
|
21
40
|
|
22
41
|
application_name = @config[:application_name] || extract_project_name(@path)
|
23
42
|
|
24
|
-
|
43
|
+
create_example_config
|
25
44
|
|
26
45
|
config_name = "#{HOME}/config/#{application_name}.yml"
|
27
46
|
say "Application #{application_name} already present in Cerberus" if File.exists?(config_name)
|
28
47
|
|
29
|
-
app_config = {
|
30
|
-
|
31
|
-
|
48
|
+
app_config = { 'scm' => {
|
49
|
+
'url' => scm.url,
|
50
|
+
'type' => scm_type },
|
51
|
+
'publisher' => {'mail' => {'recipients' => @config[:recipients]}}
|
32
52
|
}
|
33
53
|
dump_yml(config_name, app_config)
|
34
54
|
puts "Application '#{application_name}' was successfully added to Cerberus" unless @config[:quiet]
|
@@ -39,26 +59,16 @@ module Cerberus
|
|
39
59
|
path = File.expand_path(path) if test(?d, path)
|
40
60
|
File.basename(path).strip
|
41
61
|
end
|
42
|
-
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
{ 'delivery_method'=>'smtp',
|
47
|
-
'address'=>'somserver.com',
|
48
|
-
'port' => 25,
|
49
|
-
'domain'=>'somserver.com',
|
50
|
-
'user_name'=>'secret_user',
|
51
|
-
'password'=>'secret_password',
|
52
|
-
'authentication' => 'plain'
|
53
|
-
},
|
54
|
-
'sender' => "'Cerberus' <cerberus@example.com>"}
|
55
|
-
dump_yml(CONFIG_FILE, default_mail_config, false)
|
62
|
+
|
63
|
+
def create_example_config
|
64
|
+
FileUtils.mkpath(HOME) unless test(?d, HOME)
|
65
|
+
FileUtils.cp(EXAMPLE_CONFIG, CONFIG_FILE) unless test(?f, CONFIG_FILE)
|
56
66
|
end
|
57
67
|
end
|
58
68
|
|
59
|
-
class
|
69
|
+
class BuildCommand
|
60
70
|
include Cerberus::Utils
|
61
|
-
attr_reader :output, :success, :
|
71
|
+
attr_reader :output, :success, :scm, :status
|
62
72
|
|
63
73
|
def initialize(application_name, cli_options = {})
|
64
74
|
unless File.exists?("#{HOME}/config/#{application_name}.yml")
|
@@ -72,16 +82,16 @@ module Cerberus
|
|
72
82
|
|
73
83
|
@status = Status.new("#{app_root}/status.log")
|
74
84
|
|
75
|
-
@
|
85
|
+
@scm = SCM_TYPES[@config[:scm, :type] || 'svn'].new(@config[:application_root], @config)
|
76
86
|
end
|
77
87
|
|
78
88
|
def run
|
79
89
|
begin
|
80
90
|
previous_status = @status.recall
|
81
|
-
@
|
91
|
+
@scm.update!
|
82
92
|
|
83
93
|
state =
|
84
|
-
if @
|
94
|
+
if @scm.has_changes? or not previous_status
|
85
95
|
if status = make
|
86
96
|
@status.keep(:succesful)
|
87
97
|
case previous_status
|
@@ -101,14 +111,27 @@ module Cerberus
|
|
101
111
|
end
|
102
112
|
|
103
113
|
if [:failure, :broken, :revival, :setup].include?(state)
|
104
|
-
|
114
|
+
@config[:publisher, :active].split.each do |pub|
|
115
|
+
silence_stream(STDOUT) { #some of publishers like IRC very noisy
|
116
|
+
clazz = PUBLISHER_TYPES[pub.to_sym]
|
117
|
+
if clazz
|
118
|
+
clazz.publish(state, self, @config)
|
119
|
+
else
|
120
|
+
raise "There is no such publisher: #{pub}"
|
121
|
+
end
|
122
|
+
}
|
123
|
+
end
|
105
124
|
end
|
106
125
|
rescue Exception => e
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
126
|
+
if ENV['CERBERUS_ENV'] == 'TEST'
|
127
|
+
raise e
|
128
|
+
else
|
129
|
+
File.open("#{HOME}/work/#{@config[:application_name]}/error.log", File::WRONLY|File::APPEND|File::CREAT) do |f|
|
130
|
+
f.puts Time.now.strftime("%a, %d %b %Y %H:%M:%S -- #{e.class}")
|
131
|
+
f.puts e.message unless e.message.blank?
|
132
|
+
f.puts e.backtrace.collect{|line| ' '*5 + line}
|
133
|
+
f.puts "\n"
|
134
|
+
end
|
112
135
|
end
|
113
136
|
end
|
114
137
|
end
|
@@ -116,9 +139,7 @@ module Cerberus
|
|
116
139
|
private
|
117
140
|
def make
|
118
141
|
Dir.chdir @config[:application_root]
|
119
|
-
|
120
|
-
@output = `#{@config[:bin_path]}#{choose_rake_exec()} #{@config[:rake_task]} 2>&1`
|
121
|
-
|
142
|
+
@output = `#{@config[:bin_path]}#{choose_rake_exec()} #{@config[:builder, :rake, :task]} 2>&1`
|
122
143
|
make_successful?
|
123
144
|
end
|
124
145
|
|
@@ -135,7 +156,7 @@ module Cerberus
|
|
135
156
|
|
136
157
|
ext.each{|e|
|
137
158
|
begin
|
138
|
-
out =
|
159
|
+
out = `#{@config[:bin_path]}rake#{e} --version`
|
139
160
|
return "rake#{e}" if out =~ /rake/
|
140
161
|
rescue
|
141
162
|
end
|
@@ -143,7 +164,7 @@ module Cerberus
|
|
143
164
|
end
|
144
165
|
end
|
145
166
|
|
146
|
-
class
|
167
|
+
class BuildAllCommand
|
147
168
|
def initialize(cli_options = {})
|
148
169
|
@cli_options = cli_options
|
149
170
|
end
|
@@ -153,66 +174,12 @@ module Cerberus
|
|
153
174
|
fn =~ %r{#{HOME}/config/(.*).yml}
|
154
175
|
application_name = $1
|
155
176
|
|
156
|
-
command = Cerberus::
|
177
|
+
command = Cerberus::BuildCommand.new(application_name, @cli_options)
|
157
178
|
command.run
|
158
179
|
end
|
159
180
|
end
|
160
181
|
end
|
161
182
|
|
162
|
-
|
163
|
-
class Checkout
|
164
|
-
def initialize(path, options = {})
|
165
|
-
raise "Path can't be nil" unless path
|
166
|
-
|
167
|
-
@path, @options = path.strip, options
|
168
|
-
@encoded_path = (@path.include?(' ') ? "\"#{@path}\"" : @path)
|
169
|
-
end
|
170
|
-
|
171
|
-
def update!
|
172
|
-
if test(?d, @path + '/.svn')
|
173
|
-
@status = execute("svn update")
|
174
|
-
else
|
175
|
-
FileUtils.mkpath(@path) unless test(?d,@path)
|
176
|
-
@status = execute("svn checkout", nil, @options[:url])
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
def has_changes?
|
181
|
-
@status =~ /[A-Z]\s+[\w\/]+/
|
182
|
-
end
|
183
|
-
|
184
|
-
def current_revision
|
185
|
-
info['Revision'].to_i
|
186
|
-
end
|
187
|
-
|
188
|
-
def url
|
189
|
-
info['URL']
|
190
|
-
end
|
191
|
-
|
192
|
-
def last_commit_message
|
193
|
-
message = execute("svn log", "--limit 1 -v")
|
194
|
-
#strip first line that contains command line itself (svn log --limit ...)
|
195
|
-
if ((idx = message.index('-'*72)) != 0 )
|
196
|
-
message[idx..-1]
|
197
|
-
else
|
198
|
-
message
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
def last_author
|
203
|
-
info['Last Changed Author']
|
204
|
-
end
|
205
|
-
|
206
|
-
private
|
207
|
-
def info
|
208
|
-
@info ||= YAML.load(execute("svn info"))
|
209
|
-
end
|
210
|
-
|
211
|
-
def execute(command, parameters = nil, pre_parameters = nil)
|
212
|
-
`#{@options[:bin_path]}#{command} #{pre_parameters} #{@encoded_path} #{parameters}`
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
183
|
class Status
|
217
184
|
def initialize(path)
|
218
185
|
@path = path
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'cerberus/version'
|
2
|
+
|
3
|
+
module Cerberus
|
4
|
+
module Publisher
|
5
|
+
class Base
|
6
|
+
def self.formatted_message(state, build, options)
|
7
|
+
subject =
|
8
|
+
case state
|
9
|
+
when :setup
|
10
|
+
"Cerberus set up for project (##{build.scm.current_revision})"
|
11
|
+
when :broken
|
12
|
+
"Build still broken (##{build.scm.current_revision})"
|
13
|
+
when :failure
|
14
|
+
"Build broken by #{build.scm.last_author} (##{build.scm.current_revision})"
|
15
|
+
when :revival
|
16
|
+
"Build fixed by #{build.scm.last_author} (##{build.scm.current_revision})"
|
17
|
+
else
|
18
|
+
raise "Unknown build state #{state}"
|
19
|
+
end
|
20
|
+
|
21
|
+
subject = "[#{options[:application_name]}] #{subject}"
|
22
|
+
generated_by = "--\nCerberus #{Cerberus::VERSION::STRING}, http://rubyforge.org/projects/cerberus"
|
23
|
+
body = [ build.scm.last_commit_message, build.output, generated_by ].join("\n\n")
|
24
|
+
|
25
|
+
return subject, body
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'IRC'
|
2
|
+
require 'cerberus/publisher/base'
|
3
|
+
|
4
|
+
class Cerberus::Publisher::IRC < Cerberus::Publisher::Base
|
5
|
+
def self.publish(state, build, options)
|
6
|
+
irc_options = options[:publisher, :irc]
|
7
|
+
subject,body = Cerberus::Publisher::Base.formatted_message(state, build, options)
|
8
|
+
message = subject + "\n" + '*' * subject.length + "\n" + body
|
9
|
+
|
10
|
+
|
11
|
+
channel = '#' + irc_options[:channel]
|
12
|
+
bot = IRC.new(irc_options[:nick] || 'cerberus', irc_options[:server], irc_options[:port] || 6667)
|
13
|
+
IRCEvent.add_callback('endofmotd') { |event|
|
14
|
+
bot.add_channel(channel)
|
15
|
+
message.split("\n").each{|line|
|
16
|
+
bot.send_message(channel, line)
|
17
|
+
}
|
18
|
+
bot.send_quit
|
19
|
+
}
|
20
|
+
begin
|
21
|
+
bot.connect #Why it always fails?
|
22
|
+
rescue Exception => e
|
23
|
+
puts e.message
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'jabber4r/jabber4r'
|
2
|
+
require 'cerberus/publisher/base'
|
3
|
+
|
4
|
+
class Cerberus::Publisher::Jabber < Cerberus::Publisher::Base
|
5
|
+
def self.publish(state, build, options)
|
6
|
+
begin
|
7
|
+
jabber_options = options[:publisher, :jabber]
|
8
|
+
subject,body = Cerberus::Publisher::Base.formatted_message(state, build, options)
|
9
|
+
|
10
|
+
session = login(jabber_options[:jid], jabber_options[:password])
|
11
|
+
jabber_options[:recipients].split(',').each do |address|
|
12
|
+
session.new_message(address.strip).set_subject(subject).set_body(body).send
|
13
|
+
end
|
14
|
+
ensure
|
15
|
+
session.release if session
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.login(id_resource, password, register_if_login_fails=true)
|
20
|
+
begin
|
21
|
+
session = ::Jabber::Session.bind(id_resource, password)
|
22
|
+
rescue
|
23
|
+
if(register_if_login_fails)
|
24
|
+
if(::Jabber::Session.register(id_resource, password))
|
25
|
+
Cerberus::Publisher::Jabber.login(id_resource, password, false)
|
26
|
+
else
|
27
|
+
raise "Failed to register #{id_resource}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'action_mailer'
|
2
|
+
require 'cerberus/publisher/base'
|
3
|
+
|
4
|
+
class Cerberus::Publisher::Mail < Cerberus::Publisher::Base
|
5
|
+
def self.publish(state, build, options)
|
6
|
+
configure(options[:publisher, :mail].dup)
|
7
|
+
ActionMailerPublisher.deliver_message(state, build, options)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
def self.configure(config)
|
12
|
+
[:authentication, :delivery_method].each do |k|
|
13
|
+
config[k] = config[k].to_sym if config[k]
|
14
|
+
end
|
15
|
+
|
16
|
+
ActionMailer::Base.delivery_method = config[:delivery_method] if config[:delivery_method]
|
17
|
+
ActionMailer::Base.server_settings = config
|
18
|
+
end
|
19
|
+
|
20
|
+
class ActionMailerPublisher < ActionMailer::Base
|
21
|
+
def message(state, build, options)
|
22
|
+
@subject, @body = Cerberus::Publisher::Base.formatted_message(state, build, options)
|
23
|
+
@recipients, @sent_on = options[:publisher, :mail, :recipients], Time.now
|
24
|
+
@from = options[:publisher, :mail, :sender] || "'Cerberus' <cerberus@example.com>"
|
25
|
+
# raise "Please specify recipient addresses for application '#{options[:application_name]}'" unless options[:recipients]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'cerberus/publisher/base'
|
2
|
+
|
3
|
+
class Cerberus::Publisher::RSS < Cerberus::Publisher::Base
|
4
|
+
def self.publish(state, build, options)
|
5
|
+
config = options[:publisher, :rss]
|
6
|
+
subject,body = Cerberus::Publisher::Base.formatted_message(state, build, options)
|
7
|
+
|
8
|
+
pub_date = Time.now.iso8601
|
9
|
+
result = <<-END
|
10
|
+
<rss version="2.0">
|
11
|
+
<channel>
|
12
|
+
<title>Cerberus build feed for #{options[:application_name]}</title>
|
13
|
+
<pubDate>#{pub_date}</pubDate>
|
14
|
+
<generator>http://rubyforge.org/projects/cerberus</generator>
|
15
|
+
<item>
|
16
|
+
<title>#{subject}</title>
|
17
|
+
<pubDate>#{pub_date}</pubDate>
|
18
|
+
<description><pre>#{body}</pre></description>
|
19
|
+
</item>
|
20
|
+
</channel>
|
21
|
+
</rss>
|
22
|
+
END
|
23
|
+
|
24
|
+
File.open(config[:file], 'w'){|f| f.write(result)}
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class Cerberus::SCM::SVN
|
2
|
+
def initialize(path, options = {})
|
3
|
+
raise "Path can't be nil" unless path
|
4
|
+
|
5
|
+
@path, @options = path.strip, options
|
6
|
+
@encoded_path = (@path.include?(' ') ? "\"#{@path}\"" : @path)
|
7
|
+
end
|
8
|
+
|
9
|
+
def update!
|
10
|
+
if test(?d, @path + '/.svn')
|
11
|
+
execute("svn cleanup") #TODO check first that it was locked
|
12
|
+
@status = execute("svn update")
|
13
|
+
else
|
14
|
+
FileUtils.mkpath(@path) unless test(?d,@path)
|
15
|
+
@status = execute("svn checkout", nil, @options[:scm, :url])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def has_changes?
|
20
|
+
@status =~ /[A-Z]\s+[\w\/]+/
|
21
|
+
end
|
22
|
+
|
23
|
+
def current_revision
|
24
|
+
info['Revision'].to_i
|
25
|
+
end
|
26
|
+
|
27
|
+
def url
|
28
|
+
info['URL']
|
29
|
+
end
|
30
|
+
|
31
|
+
def last_commit_message
|
32
|
+
message = execute("svn log", "--limit 1 -v")
|
33
|
+
#strip first line that contains command line itself (svn log --limit ...)
|
34
|
+
if ((idx = message.index('-'*72)) != 0 )
|
35
|
+
message[idx..-1]
|
36
|
+
else
|
37
|
+
message
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def last_author
|
42
|
+
info['Last Changed Author']
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
def info
|
47
|
+
@info ||= YAML.load(execute("svn info"))
|
48
|
+
end
|
49
|
+
|
50
|
+
def execute(command, parameters = nil, pre_parameters = nil)
|
51
|
+
`#{@options[:bin_path]}#{command} #{pre_parameters} #{@encoded_path} #{parameters}`
|
52
|
+
end
|
53
|
+
end
|
data/lib/cerberus/utils.rb
CHANGED
data/lib/cerberus/version.rb
CHANGED
data/test/config_test.rb
CHANGED
data/test/functional_test.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
require 'test_helper'
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
2
|
|
3
3
|
require 'cerberus/cli'
|
4
4
|
|
5
5
|
class FunctionalTest < Test::Unit::TestCase
|
6
6
|
def setup
|
7
7
|
FileUtils.rm_rf HOME
|
8
|
+
ActionMailer::Base.deliveries.clear
|
8
9
|
end
|
9
10
|
|
10
11
|
def teardown
|
@@ -15,11 +16,13 @@ class FunctionalTest < Test::Unit::TestCase
|
|
15
16
|
def test_add_by_url
|
16
17
|
assert !File.exists?(HOME + '/config/svn_repo.yml')
|
17
18
|
|
18
|
-
command = Cerberus::
|
19
|
+
command = Cerberus::AddCommand.new(" #{SVN_URL} ", :quiet => true)
|
19
20
|
command.run
|
20
21
|
|
21
22
|
assert File.exists?(HOME + '/config/svn_repo.yml')
|
22
|
-
|
23
|
+
scm_conf = load_yml(HOME + '/config/svn_repo.yml')['scm']
|
24
|
+
assert_equal 'svn', scm_conf['type']
|
25
|
+
assert_equal SVN_URL, scm_conf['url']
|
23
26
|
|
24
27
|
assert File.exists?(HOME + '/config.yml')
|
25
28
|
end
|
@@ -27,13 +30,15 @@ class FunctionalTest < Test::Unit::TestCase
|
|
27
30
|
def test_add_by_dir
|
28
31
|
sources_dir = File.dirname(__FILE__) + '/..'
|
29
32
|
|
30
|
-
command = Cerberus::
|
33
|
+
command = Cerberus::AddCommand.new(sources_dir, :quiet => true)
|
31
34
|
command.run
|
32
35
|
|
33
36
|
project_config = HOME + "/config/#{File.basename(File.expand_path(sources_dir))}.yml" #name of added application should be calculated from File System path
|
34
37
|
|
35
38
|
assert File.exists?(project_config)
|
36
|
-
|
39
|
+
scm_conf = load_yml(project_config)['scm']
|
40
|
+
assert_equal 'svn', scm_conf['type']
|
41
|
+
assert_match %r{svn(\+ssh)?://(\w+@)?rubyforge.org/var/svn/cerberus}, scm_conf['url']
|
37
42
|
|
38
43
|
assert File.exists?(HOME + '/config.yml')
|
39
44
|
end
|
@@ -41,7 +46,7 @@ class FunctionalTest < Test::Unit::TestCase
|
|
41
46
|
def test_build
|
42
47
|
add_application('myapp', SVN_URL)
|
43
48
|
|
44
|
-
build = Cerberus::
|
49
|
+
build = Cerberus::BuildCommand.new('myapp')
|
45
50
|
build.run
|
46
51
|
assert_equal 1, ActionMailer::Base.deliveries.size #first email that project was setup
|
47
52
|
|
@@ -50,13 +55,13 @@ class FunctionalTest < Test::Unit::TestCase
|
|
50
55
|
assert_equal 'succesful', IO.read(status_file)
|
51
56
|
|
52
57
|
FileUtils.rm status_file
|
53
|
-
build = Cerberus::
|
58
|
+
build = Cerberus::BuildCommand.new('myapp')
|
54
59
|
build.run
|
55
60
|
assert File.exists?(status_file)
|
56
61
|
|
57
62
|
assert_equal 2, ActionMailer::Base.deliveries.size #first email that project was setup
|
58
63
|
|
59
|
-
build = Cerberus::
|
64
|
+
build = Cerberus::BuildCommand.new('myapp')
|
60
65
|
build.run
|
61
66
|
assert_equal 2, ActionMailer::Base.deliveries.size #Number of mails not changed
|
62
67
|
|
@@ -64,7 +69,7 @@ class FunctionalTest < Test::Unit::TestCase
|
|
64
69
|
#remove status file to run project again
|
65
70
|
FileUtils.rm status_file
|
66
71
|
add_test_case_to_project('myapp', 'assert false') { #if assertion failed
|
67
|
-
build = Cerberus::
|
72
|
+
build = Cerberus::BuildCommand.new('myapp')
|
68
73
|
build.run
|
69
74
|
|
70
75
|
assert_equal 'failed', IO.read(status_file)
|
@@ -75,7 +80,7 @@ class FunctionalTest < Test::Unit::TestCase
|
|
75
80
|
#remove status file to run project again
|
76
81
|
FileUtils.rm status_file
|
77
82
|
add_test_case_to_project('myapp', 'raise "Some exception here"') { #if we have exception
|
78
|
-
build = Cerberus::
|
83
|
+
build = Cerberus::BuildCommand.new('myapp')
|
79
84
|
build.run
|
80
85
|
|
81
86
|
assert_equal 'failed', IO.read(status_file)
|
@@ -85,20 +90,20 @@ class FunctionalTest < Test::Unit::TestCase
|
|
85
90
|
def test_have_no_awkward_header
|
86
91
|
add_application('myapp', SVN_URL)
|
87
92
|
|
88
|
-
build = Cerberus::
|
93
|
+
build = Cerberus::BuildCommand.new('myapp')
|
89
94
|
build.run
|
90
95
|
|
91
|
-
assert build.
|
92
|
-
assert_equal 0, build.
|
96
|
+
assert build.scm.last_commit_message !~ /-rHEAD -v/
|
97
|
+
assert_equal 0, build.scm.last_commit_message.index('-' * 72)
|
93
98
|
end
|
94
99
|
|
95
|
-
def
|
100
|
+
def test_batch_running
|
96
101
|
add_application('myapp1', SVN_URL)
|
97
102
|
add_application('myapp2', SVN_URL)
|
98
103
|
add_application('myapp3', SVN_URL)
|
99
104
|
add_application('myapp4', SVN_URL)
|
100
105
|
|
101
|
-
build = Cerberus::
|
106
|
+
build = Cerberus::BuildAllCommand.new
|
102
107
|
build.run
|
103
108
|
|
104
109
|
for i in 1..4 do
|
data/test/integration_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'test_helper'
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
2
|
|
3
3
|
require 'yaml'
|
4
4
|
|
@@ -15,13 +15,13 @@ class IntegrationTest < Test::Unit::TestCase
|
|
15
15
|
output = run_cerb(" add #{SVN_URL} ")
|
16
16
|
assert_match /was successfully added/, output
|
17
17
|
assert File.exists?(HOME + '/config/svn_repo.yml')
|
18
|
-
assert_equal SVN_URL, load_yml(HOME + '/config/svn_repo.yml')['url']
|
18
|
+
assert_equal SVN_URL, load_yml(HOME + '/config/svn_repo.yml')['scm']['url']
|
19
19
|
|
20
20
|
#try to add second time
|
21
21
|
output = run_cerb("add #{SVN_URL}")
|
22
22
|
assert_match /already present/, output
|
23
23
|
assert File.exists?(HOME + '/config/svn_repo.yml')
|
24
|
-
assert_equal SVN_URL, load_yml(HOME + '/config/svn_repo.yml')['url']
|
24
|
+
assert_equal SVN_URL, load_yml(HOME + '/config/svn_repo.yml')['scm']['url']
|
25
25
|
end
|
26
26
|
|
27
27
|
def test_add_project_with_parameters
|
@@ -31,8 +31,8 @@ class IntegrationTest < Test::Unit::TestCase
|
|
31
31
|
assert File.exists?(HOME + '/config/hello_world.yml')
|
32
32
|
cfg = load_yml(HOME + '/config/hello_world.yml')
|
33
33
|
|
34
|
-
assert_equal SVN_URL, cfg['url']
|
35
|
-
assert_equal 'aa@gmail.com', cfg['recipients']
|
34
|
+
assert_equal SVN_URL, cfg['scm']['url']
|
35
|
+
assert_equal 'aa@gmail.com', cfg['publisher']['mail']['recipients']
|
36
36
|
end
|
37
37
|
|
38
38
|
def test_run_project
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
require 'cerberus/publisher/irc'
|
4
|
+
require 'cerberus/config'
|
5
|
+
require 'mock/irc'
|
6
|
+
require 'mock/build'
|
7
|
+
|
8
|
+
class IRCPublisherTest < Test::Unit::TestCase
|
9
|
+
def test_publisher
|
10
|
+
options = Cerberus::Config.new(nil, :publisher => {:irc => {:channel => 'hello'}}, :application_name => 'IrcApp')
|
11
|
+
build = DummyBuild.new('last message', 'this is output', 1232, 'anatol')
|
12
|
+
|
13
|
+
Cerberus::Publisher::IRC.publish(:setup, build, options)
|
14
|
+
|
15
|
+
assert IRCConnection.connected
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
require 'cerberus/publisher/jabber'
|
4
|
+
require 'mock/jabber4r'
|
5
|
+
require 'mock/build'
|
6
|
+
|
7
|
+
class JabberPublisherTest < Test::Unit::TestCase
|
8
|
+
def test_publisher
|
9
|
+
options = Cerberus::Config.new(nil, :publisher => {:jabber => {:recipients => ' jit1@google.com, another@google.com '}}, :application_name => 'MegaApp')
|
10
|
+
build = DummyBuild.new('last message', 'this is output', 1232, 'anatol')
|
11
|
+
|
12
|
+
Cerberus::Publisher::Jabber.publish(:setup, build, options)
|
13
|
+
|
14
|
+
messages = Jabber::Protocol::Message.messages
|
15
|
+
assert_equal 2, messages.size
|
16
|
+
assert_equal 'google.com', messages[0].to.host
|
17
|
+
assert_equal 'jit1', messages[0].to.node
|
18
|
+
assert_equal '[MegaApp] Cerberus set up for project (#1232)', messages[0].subject
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
require 'cerberus/publisher/mail'
|
4
|
+
require 'mock/build'
|
5
|
+
|
6
|
+
class MailPublisherTest < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
ActionMailer::Base.deliveries.clear
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_publisher
|
12
|
+
options = Cerberus::Config.new(nil, :publisher => {
|
13
|
+
:mail => {:recipients => 'anatol.pomozov@hello.com', :sender => 'haha', :delivery_method => 'test'}},
|
14
|
+
:application_name => 'MyApp')
|
15
|
+
build = DummyBuild.new('last message', 'this is output', 1232, 'anatol')
|
16
|
+
|
17
|
+
Cerberus::Publisher::Mail.publish(:setup, build, options)
|
18
|
+
|
19
|
+
mails = ActionMailer::Base.deliveries
|
20
|
+
assert_equal 1, mails.size
|
21
|
+
mail = mails[0]
|
22
|
+
assert_equal 'haha', mail.from_addrs[0].address
|
23
|
+
assert_equal '[MyApp] Cerberus set up for project (#1232)', mail.subject
|
24
|
+
end
|
25
|
+
end
|
data/test/mock/build.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
class DummyBuild
|
2
|
+
attr_reader :output, :scm
|
3
|
+
SCM = Struct.new(:last_commit_message, :current_revision, :last_author)
|
4
|
+
|
5
|
+
def initialize(last_commit_message, output, current_revision, last_author)
|
6
|
+
@output = output
|
7
|
+
|
8
|
+
@scm = SCM.new(last_commit_message, current_revision, last_author)
|
9
|
+
end
|
10
|
+
end
|
data/test/mock/irc.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
class IRCConnection
|
2
|
+
@@messages = []
|
3
|
+
@@connected = false
|
4
|
+
|
5
|
+
def self.messages
|
6
|
+
@@messages
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.connected
|
10
|
+
@@connected
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.send_to_server(msg)
|
14
|
+
@@messages << msg
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.handle_connection(server, port)
|
18
|
+
@@connected = true
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
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
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
require 'cerberus/publisher/rss'
|
4
|
+
require 'mock/build'
|
5
|
+
require 'tempfile'
|
6
|
+
|
7
|
+
class RSSPublisherTest < Test::Unit::TestCase
|
8
|
+
def test_publisher
|
9
|
+
rss_file = tf = Tempfile.new('cerberus-rss')
|
10
|
+
options = Cerberus::Config.new(nil, :publisher => {:rss => {:file => rss_file.path}}, :application_name => 'RSSApp')
|
11
|
+
build = DummyBuild.new('last message', 'this is output', 1235, 'anatol')
|
12
|
+
|
13
|
+
Cerberus::Publisher::RSS.publish(:setup, build, options)
|
14
|
+
|
15
|
+
xml = REXML::Document.new(IO.read(rss_file.path))
|
16
|
+
|
17
|
+
assert_equal '[RSSApp] Cerberus set up for project (#1235)', xml.elements["rss/channel/item/title/"].get_text.value
|
18
|
+
end
|
19
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
$:.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
|
3
|
+
require 'rubygems'
|
2
4
|
require 'test/unit'
|
3
5
|
require 'fileutils'
|
4
6
|
|
@@ -14,6 +16,7 @@ class Test::Unit::TestCase
|
|
14
16
|
|
15
17
|
HOME = TEMP_DIR + '/home'
|
16
18
|
ENV['CERBERUS_HOME'] = HOME
|
19
|
+
ENV['CERBERUS_ENV'] = 'TEST'
|
17
20
|
|
18
21
|
def self.refresh_subversion
|
19
22
|
FileUtils.rm_rf TEMP_DIR
|
@@ -47,10 +50,15 @@ end"
|
|
47
50
|
end
|
48
51
|
|
49
52
|
def add_application(app_name, url, options = {})
|
50
|
-
opt = options.
|
51
|
-
|
52
|
-
|
53
|
-
|
53
|
+
opt = options.merge(
|
54
|
+
'scm'=>{'url'=>url},
|
55
|
+
'publisher'=>{
|
56
|
+
'active' => 'mail',
|
57
|
+
'mail'=>{'recipients'=>'somebody@com.com', 'delivery_method' => 'test'}
|
58
|
+
})
|
59
|
+
|
54
60
|
dump_yml(HOME + "/config/#{app_name}.yml", opt)
|
55
61
|
end
|
56
|
-
end
|
62
|
+
end
|
63
|
+
|
64
|
+
require 'cerberus/config'
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: cerberus
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2006-
|
6
|
+
version: 0.2.0
|
7
|
+
date: 2006-08-11 00:00:00 +04:00
|
8
8
|
summary: Cerberus is a Continuous Integration tool that could be easily run from Cron.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -30,27 +30,50 @@ authors:
|
|
30
30
|
- Anatol Pomozov
|
31
31
|
files:
|
32
32
|
- bin/cerberus
|
33
|
-
- doc/FAQ
|
34
33
|
- lib/cerberus
|
34
|
+
- lib/cerberus/builder
|
35
35
|
- lib/cerberus/cli.rb
|
36
|
+
- lib/cerberus/config.example.yml
|
36
37
|
- lib/cerberus/config.rb
|
38
|
+
- lib/cerberus/config_migration.rb
|
37
39
|
- lib/cerberus/constants.rb
|
38
40
|
- lib/cerberus/latch.rb
|
39
41
|
- lib/cerberus/manager.rb
|
40
|
-
- lib/cerberus/
|
42
|
+
- lib/cerberus/publisher
|
43
|
+
- lib/cerberus/scm
|
41
44
|
- lib/cerberus/utils.rb
|
42
45
|
- lib/cerberus/version.rb
|
43
|
-
- lib/cerberus/
|
46
|
+
- lib/cerberus/builder/maven2.rb
|
47
|
+
- lib/cerberus/builder/rake.rb
|
48
|
+
- lib/cerberus/publisher/base.rb
|
49
|
+
- lib/cerberus/publisher/irc.rb
|
50
|
+
- lib/cerberus/publisher/jabber.rb
|
51
|
+
- lib/cerberus/publisher/mail.rb
|
52
|
+
- lib/cerberus/publisher/rss.rb
|
53
|
+
- lib/cerberus/scm/cvs.rb
|
54
|
+
- lib/cerberus/scm/darcs.rb
|
55
|
+
- lib/cerberus/scm/svn.rb
|
44
56
|
- test/config_test.rb
|
45
57
|
- test/data
|
46
58
|
- test/functional_test.rb
|
47
59
|
- test/integration_test.rb
|
60
|
+
- test/irc_publisher_test.rb
|
61
|
+
- test/jabber_publisher_test.rb
|
62
|
+
- test/mail_publisher_test.rb
|
63
|
+
- test/mock
|
64
|
+
- test/rss_publisher_test.rb
|
48
65
|
- test/test_helper.rb
|
49
66
|
- test/data/application.dump
|
67
|
+
- test/mock/build.rb
|
68
|
+
- test/mock/irc.rb
|
69
|
+
- test/mock/jabber4r.rb
|
50
70
|
- LICENSE
|
51
71
|
- README
|
52
72
|
- CHANGES
|
53
73
|
- Rakefile
|
74
|
+
- doc/FAQ
|
75
|
+
- doc/OPTIONS
|
76
|
+
- doc/site
|
54
77
|
test_files:
|
55
78
|
- test/integration_test.rb
|
56
79
|
rdoc_options:
|
@@ -72,7 +95,7 @@ dependencies:
|
|
72
95
|
requirements:
|
73
96
|
- - ">="
|
74
97
|
- !ruby/object:Gem::Version
|
75
|
-
version: 1.2.
|
98
|
+
version: 1.2.3
|
76
99
|
version:
|
77
100
|
- !ruby/object:Gem::Dependency
|
78
101
|
name: rake
|
@@ -83,3 +106,21 @@ dependencies:
|
|
83
106
|
- !ruby/object:Gem::Version
|
84
107
|
version: 0.7.1
|
85
108
|
version:
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
name: jabber4r
|
111
|
+
version_requirement:
|
112
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 0.8.0
|
117
|
+
version:
|
118
|
+
- !ruby/object:Gem::Dependency
|
119
|
+
name: Ruby-IRC
|
120
|
+
version_requirement:
|
121
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 1.0.3
|
126
|
+
version:
|
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'action_mailer'
|
2
|
-
|
3
|
-
module Cerberus
|
4
|
-
module Notifier
|
5
|
-
class Email
|
6
|
-
def self.notify(state, build, options)
|
7
|
-
Email.configure(options)
|
8
|
-
ActionMailerNotifier.deliver_message(state, build, options)
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
def self.configure(options)
|
13
|
-
mail_config = options[:mail] || {}
|
14
|
-
[:authentication, :delivery_method].each do |k|
|
15
|
-
mail_config[k] = mail_config[k].to_sym if mail_config[k]
|
16
|
-
end
|
17
|
-
|
18
|
-
ActionMailer::Base.delivery_method = mail_config[:delivery_method] if mail_config[:delivery_method]
|
19
|
-
ActionMailer::Base.server_settings = mail_config
|
20
|
-
end
|
21
|
-
|
22
|
-
class ActionMailerNotifier < ActionMailer::Base
|
23
|
-
def message(state, build, options)
|
24
|
-
subject =
|
25
|
-
case state
|
26
|
-
when :setup
|
27
|
-
"Cerberus set up for project (##{build.checkout.current_revision})"
|
28
|
-
when :broken
|
29
|
-
"Build still broken (##{build.checkout.current_revision})"
|
30
|
-
when :failure
|
31
|
-
"Build broken by #{build.checkout.last_author} (##{build.checkout.current_revision})"
|
32
|
-
when :revival
|
33
|
-
"Build fixed by #{build.checkout.last_author} (##{build.checkout.current_revision})"
|
34
|
-
end
|
35
|
-
|
36
|
-
@subject = "[#{options[:application_name]}] #{subject}"
|
37
|
-
@body = [ build.checkout.last_commit_message, build.output ].join("\n\n")
|
38
|
-
|
39
|
-
@recipients, @sent_on = options[:recipients], Time.now
|
40
|
-
|
41
|
-
@from = options[:sender] || "'Cerberus' <cerberus@example.com>"
|
42
|
-
raise "Please specify recipient addresses for application '#{options[:application_name]}'" unless options[:recipients]
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|