cerberus 0.7 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
data/Changelog.txt CHANGED
@@ -1,5 +1,20 @@
1
1
  = Cerberus Changelog
2
2
 
3
+ == Version 0.7.2
4
+ Bugfixes and updates to RSS publisher
5
+
6
+ * Fix mercurial builder to properly read revision number of merged commits
7
+ * Updated RSS publisher to output a properly formatted RSS feed with the
8
+ ability to keep a certain number of previous builds in the feed. For more
9
+ info on the changes please see the commit message on the following commit:
10
+ http://github.com/cpjolicoeur/cerberus/commit/1f7176a6a611f30a0d70e0f75ec90724f6302043
11
+
12
+ == Version 0.7.1
13
+ New configuration options for publisher
14
+
15
+ * added "extra_subject" publisher option
16
+ * added Mercurial SCM support
17
+
3
18
  == Version 0.7
4
19
  New config options, Bazaar SCM support, removed GMailer bugfixes
5
20
 
@@ -8,8 +23,7 @@ New config options, Bazaar SCM support, removed GMailer bugfixes
8
23
  * removed GMailer library. Use default Mail publisher instead
9
24
  * added 'build_dir' option for setting custom build directory
10
25
  * added 'setup_script' option for a custom script to be run before build command
11
- * Projects using the Git SCM were not getting the full diff output in their
12
- Publishers
26
+ * Projects using the Git SCM were not getting the full diff output in their Publishers
13
27
 
14
28
  == Version 0.6
15
29
  New Ruby builder, bugfixes, and refactoring
data/Copyright.txt CHANGED
@@ -13,4 +13,5 @@ Niklas Koponen
13
13
  Mike Gunderloy
14
14
  Joe Van Dyk
15
15
  Andrew Timberlake
16
- Paul Hinze
16
+ Paul Hinze
17
+ McClain Looney
data/Rakefile CHANGED
@@ -3,6 +3,7 @@ require 'rake'
3
3
  require 'rake/testtask'
4
4
  require 'rake/packagetask'
5
5
  require 'rake/gempackagetask'
6
+ require 'rake/clean'
6
7
 
7
8
  require './lib/cerberus/constants'
8
9
 
@@ -25,6 +26,7 @@ Rake::TestTask.new(:test) do |t|
25
26
  t.verbose = true
26
27
  end
27
28
 
29
+ CLEAN.include %w(**/*~)
28
30
  desc "Clean all generated files"
29
31
  task :clean => :clobber_package do
30
32
  root = File.dirname(__FILE__)
data/Readme.markdown CHANGED
@@ -87,6 +87,7 @@ Cerberus currently supports the following SCM tools:
87
87
  * Perforce
88
88
  * CVS
89
89
  * Bazaar
90
+ * Mercurial
90
91
 
91
92
  Cerberus currently supports the following notification systems:
92
93
 
@@ -126,7 +127,7 @@ is included in the License.txt file.
126
127
 
127
128
 
128
129
  [1]:http://www.martinfowler.com/articles/continuousIntegration.html
129
- [2]:http://wiki.github.com/cpjolicoeur/cerberusci
130
+ [2]:http://wiki.github.com/cpjolicoeur/cerberus
130
131
  [3]:http://groups.google.com/group/cerberusci
131
132
  [4]:http://cpjolicoeur.lighthouseapp.com/projects/22299-cerberus
132
133
  [5]:http://rubyforge.org/frs/?group_id=1794
@@ -6,7 +6,8 @@ module Cerberus
6
6
  :perforce => 'Perforce',
7
7
  :cvs => 'CVS',
8
8
  :bzr => 'Bazaar',
9
- :git => 'Git'
9
+ :git => 'Git',
10
+ :hg => 'Mercurial'
10
11
  }
11
12
 
12
13
  def self.get(type)
@@ -30,6 +31,8 @@ module Cerberus
30
31
  'bzr'
31
32
  when test(?d, path+'/.git')
32
33
  'git'
34
+ when test(?d, path+'/.hg')
35
+ 'hg'
33
36
  end
34
37
  else
35
38
  #guess SCM type by its url
@@ -23,6 +23,9 @@ publisher:
23
23
  # url: http://someemail:password@cerberustool.campfirenow.com/room/51660
24
24
  # rss:
25
25
  # file: /usr/www/rss.xml
26
+ # channel_link: http://example.com/rss.xml
27
+ # keep: 1
28
+ # extra_subject: "#deployment #tags"
26
29
  #builder:
27
30
  # rake:
28
31
  # task: migrate test
@@ -4,5 +4,5 @@ module Cerberus
4
4
 
5
5
  LOCK_WAIT = 30 * 60 # 30 minutes
6
6
 
7
- VERSION = '0.7'
7
+ VERSION = '0.7.2'
8
8
  end
@@ -55,7 +55,7 @@ module Cerberus
55
55
 
56
56
  def initialize(application_name, cli_options = {})
57
57
  unless File.exists?("#{HOME}/config/#{application_name}.yml")
58
- say "Project '#{application_name}' does not present in Cerberus. Type 'cerberus list' to see the list of all active projects."
58
+ say "Project '#{application_name}' does not exist in Cerberus. Type 'cerberus list' to see the list of all active projects."
59
59
  end
60
60
  @app_root = "#{HOME}/work/#{application_name}"
61
61
 
@@ -88,7 +88,7 @@ module Cerberus
88
88
 
89
89
  def initialize(application_name, cli_options = {})
90
90
  unless File.exists?("#{HOME}/config/#{application_name}.yml")
91
- say "Project '#{application_name}' does not present in Cerberus. Type 'cerberus list' to see the list of all active projects."
91
+ say "Project '#{application_name}' does not exist in Cerberus. Type 'cerberus list' to see the list of all active projects."
92
92
  end
93
93
 
94
94
  app_root = "#{HOME}/work/#{application_name}"
@@ -141,7 +141,6 @@ module Cerberus
141
141
  Publisher.get(pub, publisher_config).publish(@status, self, @config) if events.include?(@status.current_state)
142
142
  end
143
143
 
144
-
145
144
  #Process hooks
146
145
  hooks = @config[:hook]
147
146
  hooks.each_pair{|name, hook|
@@ -32,7 +32,7 @@ module Cerberus
32
32
  raise "Unknown build state '#{state.current_state.to_s}'"
33
33
  end
34
34
 
35
- subject = "[#{options[:application_name]}] #{subject}"
35
+ subject = "[#{options[:application_name]}]#{options[:publisher, :extra_subject]} #{subject}"
36
36
  generated_by = "--\nThis email generated by Cerberus tool ver. #{Cerberus::VERSION}, http://cerberus.rubyforge.org/"
37
37
  body = [ manager.scm.last_commit_message ]
38
38
  if options[:changeset_url]
@@ -1,29 +1,41 @@
1
1
  require 'cerberus/publisher/base'
2
2
  require 'time'
3
3
  require 'builder'
4
+ require 'rss'
4
5
 
5
6
  class Cerberus::Publisher::RSS < Cerberus::Publisher::Base
6
7
  def self.publish(state, manager, options)
7
8
  config = options[:publisher, :rss]
8
9
  subject,body = Cerberus::Publisher::Base.formatted_message(state, manager, options)
9
10
 
10
- pub_date = Time.now.iso8601
11
- description = "<pre>#{body}</pre>".to_xs
12
- result = <<-END
13
- <rss version="2.0">
14
- <channel>
15
- <title>Cerberus build feed for #{options[:application_name].to_xs}</title>
16
- <pubDate>#{pub_date}</pubDate>
17
- <generator>http://rubyforge.org/projects/cerberus</generator>
18
- <item>
19
- <title>#{subject.to_xs}</title>
20
- <pubDate>#{pub_date}</pubDate>
21
- <description>#{description}</description>
22
- </item>
23
- </channel>
24
- </rss>
25
- END
11
+ pub_date = Time.now
26
12
 
27
- IO.write(config[:file], result)
13
+ begin
14
+ feed = RSS::Parser.parse(File.read(config[:file]), false)
15
+ raise RSS::Error unless feed
16
+ keep = config[:keep] || 1
17
+ feed.items.slice!(keep -1 ..-1) # one less than keep value, to make room for the new build
18
+ rescue RSS::Error, Errno::ENOENT
19
+ # if there's no existing file or we can't parse it, start a new one from scratch
20
+ feed = RSS::Maker.make("2.0") do |new_rss|
21
+ new_rss.channel.title = "#{options[:application_name].to_xs} build status"
22
+ new_rss.channel.description = "Cerberus build feed for #{options[:application_name].to_xs}"
23
+ new_rss.channel.generator = "http://rubyforge.org/projects/cerberus"
24
+ new_rss.channel.link = config[:channel_link] || "file://#{config[:file]}"
25
+ end
26
+ end
27
+
28
+ # update channel link if we have it explicitly set, otherwise retain existing value
29
+ feed.channel.link = config[:channel_link] unless config[:channel_link].nil?
30
+ feed.channel.pubDate = pub_date
31
+
32
+ new_item = RSS::Rss::Channel::Item.new()
33
+ new_item.title = subject
34
+ new_item.pubDate = pub_date
35
+ new_item.description = "<pre>#{body}</pre>"
36
+
37
+ feed.items.unshift new_item
38
+
39
+ IO.write(config[:file], feed)
28
40
  end
29
41
  end
@@ -54,7 +54,7 @@ class Cerberus::SCM::Bazaar < Cerberus::SCM::Base
54
54
  # message:
55
55
  # sidfugsdiufgsdifusdg
56
56
 
57
- @revision = lastlog.match(/^revno: (\d+)$/)[1].to_i
57
+ @revision = lastlog.match(/^revno: (\d+).*$/)[1].to_i
58
58
  @author = lastlog.match(/^committer: (.+)$/)[1]
59
59
  @date = Time.parse(lastlog.match(/^timestamp: (.+)$/)[1])
60
60
  @message = lastlog.match(/message:\n (.*)/m)[1]
@@ -0,0 +1,87 @@
1
+ require 'cerberus/utils'
2
+ require 'cerberus/scm/base'
3
+
4
+ class Cerberus::SCM::Mercurial < Cerberus::SCM::Base
5
+
6
+ def installed?
7
+ exec_successful? "#{@config[:bin_path]}hg --version"
8
+ end
9
+
10
+ def update!
11
+ @new =false
12
+ if test( ?d, File.join( @path,'.hg' ) )
13
+ r = get_localrev
14
+ get_updates
15
+ r_new = get_localrev
16
+ @has_changes = r_new !=r
17
+ else
18
+ FileUtils.rm_rf(@path) if test(?d, @path)
19
+ encoded_url = (@config[:scm, :url].include?(' ') ? "\"#{@config[:scm, :url]}\"" : @config[:scm, :url])
20
+ @new = true
21
+ @has_changes = true
22
+ @status = execute("clone", "#{encoded_url} #{@path}", false)
23
+ if branch = @config[:scm, :branch]
24
+ execute('update', "-C #{branch}")
25
+ end
26
+ end
27
+ extract_commit_info if @has_changes
28
+ end
29
+
30
+ def has_changes?
31
+ @has_changes
32
+ end
33
+
34
+
35
+ def new?
36
+ @new
37
+ end
38
+
39
+ def current_revision
40
+ @revision
41
+ end
42
+
43
+ def last_commit_message
44
+ @message
45
+ end
46
+
47
+ def last_author
48
+ @author
49
+ end
50
+
51
+ def output
52
+ @status
53
+ end
54
+
55
+ private
56
+ def get_localrev
57
+ execute("id", '-i').strip
58
+ end
59
+
60
+ def get_updates
61
+ execute("pull", '-u')
62
+ end
63
+
64
+ def remote_head
65
+ branch = @config[:scm, :branch] || 'default'
66
+ end
67
+
68
+ def execute(command, parameters = nil, with_path = true)
69
+ if with_path
70
+ cmd = "cd #{@config[:application_root]} && #{@config[:bin_path]}hg #{command} #{parameters}"
71
+ else
72
+ cmd = "#{@config[:bin_path]}hg #{command} #{parameters}"
73
+ end
74
+ `#{cmd}`
75
+ end
76
+
77
+ def extract_commit_info( branch='default' )
78
+ message = execute("log", "-b #{ branch } -r tip --template '{author}|{date|shortdate}|{node}|{desc}'").split("|")
79
+ m= { :author => message.shift, :date => message.shift, :revision => message.shift, :message => message.shift }
80
+ @message = m[:message]
81
+ @author = m[:author]
82
+ @date = m[:date]
83
+ @revision = m[:revision]
84
+ m
85
+ end
86
+
87
+ end
Binary file
@@ -330,6 +330,70 @@ class FunctionalTest < Test::Unit::TestCase
330
330
  build.run
331
331
  assert_equal false, build.scm.has_changes?
332
332
  end
333
+
334
+ def test_mercurial
335
+ add_application('hgapp', HG_URL, :scm => {:type => 'hg'})
336
+
337
+ build = Cerberus::BuildCommand.new('hgapp')
338
+ build.run
339
+ assert build.scm.has_changes?
340
+ assert_equal 1, ActionMailer::Base.deliveries.size #first email that project was setup
341
+ mail = ActionMailer::Base.deliveries[0]
342
+ output = mail.body
343
+
344
+ #Check output that run needed tasks
345
+ assert_match /1 tests, 1 assertions, 0 failures, 0 errors/, output
346
+ assert output !~ /Task 'custom1' has been invoked/
347
+ assert_match /\[hgapp\] Cerberus set up for project/, mail.subject
348
+
349
+ status_file = HOME + '/work/hgapp/status.log'
350
+ assert File.exists?(status_file)
351
+ assert build_successful?(status_file)
352
+ assert 1, Dir[HOME + "/work/hgapp/logs/*.log"].size
353
+
354
+ #There were no changes - no reaction should be
355
+ build = Cerberus::BuildCommand.new('hgapp')
356
+ build.run
357
+ assert_equal false, build.scm.has_changes?
358
+ assert_equal 1, ActionMailer::Base.deliveries.size #first email that project was setup
359
+ assert 1, Dir[HOME + "/work/hgapp/logs/*.log"].size
360
+
361
+ #now we add new broken test
362
+ rand_val = rand(10000)
363
+ test_case_name = "test/#{rand_val}_test.rb"
364
+ File.open(HG_REPO + '/' + test_case_name, 'w') { |f|
365
+ f << %Q( require 'test/unit'
366
+ class A#{rand_val}Test < Test::Unit::TestCase
367
+ def test_ok
368
+ assert false
369
+ end
370
+ end )
371
+ }
372
+
373
+ curr_dir = Dir.pwd
374
+ Dir.chdir HG_REPO
375
+ `hg add #{test_case_name}`
376
+ `hg commit -m 'somepatch'`
377
+ Dir.chdir curr_dir
378
+
379
+ build = Cerberus::BuildCommand.new('hgapp')
380
+ build.run
381
+ assert build.scm.has_changes?
382
+ assert_equal 2, ActionMailer::Base.deliveries.size #first email that project was setup plus new alert email
383
+ assert 2, Dir[HOME + "/work/hgapp/logs/*.log"].size
384
+
385
+ build = Cerberus::BuildCommand.new('hgapp')
386
+ build.run
387
+ assert_equal false, build.scm.has_changes?
388
+ assert_equal 2, ActionMailer::Base.deliveries.size #first email that project was setup
389
+ assert 2, Dir[HOME + "/work/hgapp/logs/*.log"].size
390
+
391
+ #Now we broke remote repository (imitate that network unaccessable)
392
+ FileUtils.rm_rf HG_REPO
393
+ build = Cerberus::BuildCommand.new('hgapp')
394
+ build.run
395
+ assert_equal false, build.scm.has_changes?
396
+ end
333
397
 
334
398
  def test_campfire_publisher
335
399
  # there were not any messages causing login/password is incorrect. We just check that there was no any exceptions
@@ -11,7 +11,7 @@ class IntegrationTest < Test::Unit::TestCase
11
11
  FileUtils.rm_rf HOME
12
12
  end
13
13
 
14
- def test_add_project_as_url
14
+ def test_add_project_as_url_subversion
15
15
  output = run_cerb(" add #{SVN_URL} ")
16
16
  assert_match /has been added to Cerberus successfully/, output
17
17
  assert File.exists?(HOME + '/config/svn_repo.yml')
@@ -31,8 +31,13 @@ class IntegrationTest < Test::Unit::TestCase
31
31
  end
32
32
 
33
33
  def test_status_command
34
- # FIXME: add real tests
35
- assert true
34
+ run_cerb(" add #{SVN_URL} APPLICATION_NAME=mamba ")
35
+ output = run_cerb(" status ")
36
+ assert_match /Project Name/, output
37
+ assert_match /Revision/, output
38
+ assert_match /Status/, output
39
+ assert_match /mamba/, output
40
+ assert_match /(Pass|Fail)/, output
36
41
  end
37
42
 
38
43
  def test_add_project_with_parameters
@@ -80,7 +85,7 @@ class IntegrationTest < Test::Unit::TestCase
80
85
 
81
86
  def test_run_unexist_project
82
87
  output = run_cerb("build some_project")
83
- assert_match /Project 'some_project' does not present in Cerberus/, output
88
+ assert_match /Project 'some_project' does not exist in Cerberus/, output
84
89
  assert !test(?d, HOME + '/work/some_project')
85
90
  end
86
91
 
@@ -104,7 +109,7 @@ class IntegrationTest < Test::Unit::TestCase
104
109
 
105
110
  def test_hook
106
111
  some_number = rand(100000)
107
- tmp_file = File.join(TEMP_DIR, 'some_number')
112
+ tmp_file = File.join(TEMP_DIR, '/some_number')
108
113
  config_file = HOME + '/config/hooks.yml'
109
114
 
110
115
  add_application('hooks', SVN_URL, 'quiet' => true)
@@ -113,7 +118,7 @@ class IntegrationTest < Test::Unit::TestCase
113
118
  cfg['hook'] = {'echo' => {'action' => "echo #{some_number} > #{tmp_file}"}}
114
119
  dump_yml(config_file, cfg)
115
120
 
116
- File.rm_f tmp_file
121
+ # File.rm_f tmp_file
117
122
  run_cerb("build hooks")
118
123
  assert_equal some_number.to_s, IO.read(tmp_file).strip
119
124
  File.rm_f tmp_file
@@ -11,7 +11,8 @@ class MailPublisherTest < Test::Unit::TestCase
11
11
 
12
12
  def test_publisher
13
13
  options = Cerberus::Config.new(nil, :publisher => {
14
- :mail => {:recipients => 'anatol.pomozov@hello.com', :sender => "cerberus@example.com", :delivery_method => 'test'}},
14
+ :mail => {:recipients => 'anatol.pomozov@hello.com', :sender => "cerberus@example.com", :delivery_method => 'test'},
15
+ :extra_subject => "[#deployment]"},
15
16
  :application_name => 'MyApp')
16
17
  build = DummyManager.new('last message', 'this is output', 1232, 'anatol')
17
18
 
@@ -21,6 +22,6 @@ class MailPublisherTest < Test::Unit::TestCase
21
22
  assert_equal 1, mails.size
22
23
  mail = mails[0]
23
24
  assert_equal 'cerberus@example.com', mail.from_addrs[0].address
24
- assert_equal '[MyApp] Cerberus set up for project (1232)', mail.subject
25
+ assert_equal '[MyApp][#deployment] Cerberus set up for project (1232)', mail.subject
25
26
  end
26
27
  end
data/test/test_helper.rb CHANGED
@@ -21,6 +21,9 @@ class Test::Unit::TestCase
21
21
 
22
22
  GIT_REPO = TEMP_DIR + '/git_repo'
23
23
  GIT_URL = 'file:///' + GIT_REPO.gsub(/\\/,'/').gsub(/^\//,'').gsub(' ', '%20')
24
+
25
+ HG_REPO = TEMP_DIR + '/hg_repo'
26
+ HG_URL = 'file:///' + HG_REPO.gsub(/\\/, '/').gsub(/^\//, '').gsub(' ', '%20')
24
27
 
25
28
  def self.refresh_repos
26
29
  # setup base subversion repos
@@ -50,6 +53,16 @@ class Test::Unit::TestCase
50
53
  zf.extract(e, fpath)
51
54
  }
52
55
  }
56
+
57
+ # setup base hg repos
58
+ FileUtils.mkpath HG_REPO
59
+ Zip::ZipFile::open("#{File.dirname(__FILE__)}/data/mercurial.zip") { |zf|
60
+ zf.each { |e|
61
+ fpath = File.join(HG_REPO, e.name)
62
+ FileUtils.mkdir_p(File.dirname(fpath))
63
+ zf.extract(e, fpath)
64
+ }
65
+ }
53
66
  end
54
67
 
55
68
  refresh_repos
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cerberus
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.7"
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Craig P Jolicoeur
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-05 00:00:00 -04:00
12
+ date: 2010-03-20 00:00:00 -04:00
13
13
  default_executable: cerberus
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -81,6 +81,7 @@ files:
81
81
  - lib/cerberus/scm/cvs.rb
82
82
  - lib/cerberus/scm/darcs.rb
83
83
  - lib/cerberus/scm/git.rb
84
+ - lib/cerberus/scm/hg.rb
84
85
  - lib/cerberus/scm/perforce.rb
85
86
  - lib/cerberus/scm/svn.rb
86
87
  - lib/cerberus/utils.rb
@@ -346,6 +347,7 @@ files:
346
347
  - test/cron_string_test.rb
347
348
  - test/data/darcs.zip
348
349
  - test/data/git.zip
350
+ - test/data/mercurial.zip
349
351
  - test/data/subversion.dump
350
352
  - test/functional_test.rb
351
353
  - test/integration_test.rb
@@ -394,7 +396,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
394
396
  requirements: []
395
397
 
396
398
  rubyforge_project: cerberus
397
- rubygems_version: 1.3.4
399
+ rubygems_version: 1.3.5
398
400
  signing_key:
399
401
  specification_version: 3
400
402
  summary: Cerberus is a Continuous Integration tool that could be easily run from Cron.