public
Description: CruiseControl.rb is a continuous integration tool, written in Ruby. It is quick to install, simple to use and easy to hack.
Homepage: http://cruisecontrolrb.thoughtworks.com/
Clone URL: git://github.com/benburkert/cruisecontrolrb.git
Multiple triggers per project

git-svn-id: http://cruisecontrolrb.rubyforge.org/svn/trunk@525 
c04ce798-636b-4ca8-9149-0f9336831111
alexeyv (author)
Wed Aug 15 18:06:21 -0700 2007
commit  549139b5a5accc8aed5ca28b0320be7f19f813ff
tree    915a150f950e3ad568271d6449fa1e1d070f2ca8
parent  d0391fba09eed8d9be3b2e71f480f46bf22a4795
...
39
40
41
42
 
43
44
45
...
199
200
201
202
203
 
204
205
206
...
220
221
222
 
 
 
 
223
224
225
...
395
396
397
398
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
399
400
401
...
39
40
41
 
42
43
44
45
...
199
200
201
 
 
202
203
204
205
...
219
220
221
222
223
224
225
226
227
228
...
398
399
400
 
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
0
@@ -39,7 +39,7 @@ class Project
0
     @settings = ''
0
     @config_file_content = ''
0
     @error_message = ''
0
- @trigger = ChangeInSourceControlTrigger.new
0
+ @triggers = [ChangeInSourceControlTrigger.new(self)]
0
     instantiate_plugins
0
   end
0
   
0
@@ -199,8 +199,7 @@ class Project
0
 
0
   def build_if_necessary
0
     begin
0
- revisions = @trigger.get_revisions_to_build(self)
0
-
0
+ revisions = revisions_to_build
0
       if revisions.empty?
0
         notify :no_new_revisions_detected
0
         return nil
0
@@ -220,6 +219,10 @@ class Project
0
     end
0
   end
0
 
0
+ def revisions_to_build
0
+ @triggers.collect(&:revisions_to_build).flatten.sort.uniq
0
+ end
0
+
0
   def new_revisions
0
     if builds.empty?
0
       [@source_control.latest_revision(self)].compact
0
@@ -395,7 +398,25 @@ class Project
0
   def load_timestamp(file)
0
     Time.parse(File.read(file))
0
   end
0
-
0
+
0
+ def triggered_by(*new_triggers)
0
+ @triggers += new_triggers
0
+
0
+ @triggers.map! do |trigger|
0
+ if trigger.is_a?(String) || trigger.is_a?(Symbol)
0
+ SuccessfulBuildTrigger.new(self, trigger)
0
+ else
0
+ trigger
0
+ end
0
+ end
0
+ @triggers
0
+ end
0
+
0
+ def triggered_by=(triggers)
0
+ @triggers = [triggers].flatten
0
+ end
0
+
0
+
0
   private
0
   
0
   # sorts a array of builds in order of revision number and rebuild number
...
1
2
3
 
 
 
4
5
6
...
9
10
11
12
13
 
 
 
14
15
 
16
17
18
...
1
2
 
3
4
5
6
7
8
...
11
12
13
 
 
14
15
16
17
 
18
19
20
21
0
@@ -1,6 +1,8 @@
0
 Revision = Struct.new :number, :committed_by, :time, :message, :changeset
0
 
0
-class Revision
0
+class Revision
0
+ include Comparable
0
+
0
   def to_s
0
     <<-EOL
0
 Revision #{number} committed by #{committed_by} on #{time.strftime('%Y-%m-%d %H:%M:%S') if time}
0
@@ -9,10 +11,11 @@ Revision #{number} committed by #{committed_by} on #{time.strftime('%Y-%m-%d %H:
0
     EOL
0
   end
0
 
0
- def ==(other)
0
- number == other.number
0
+ def <=>(other)
0
+ raise("Comparing a revision to #{other.class} is not supported") unless other.is_a? Revision
0
+ self.number <=> other.number
0
   end
0
-
0
+
0
   def to_i
0
     number
0
   end
...
1
2
3
4
 
 
 
 
 
 
 
5
6
7
8
9
 
10
11
 
 
12
13
14
15
 
16
17
18
19
 
20
21
22
...
24
25
26
27
 
 
 
28
29
30
...
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
1
 
 
 
2
3
4
5
6
7
8
9
10
11
12
 
13
14
 
15
16
17
18
19
 
20
21
22
23
 
24
25
26
27
...
29
30
31
 
32
33
34
35
36
37
...
41
42
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0
@@ -1,22 +1,27 @@
0
 class ChangeInSourceControlTrigger
0
- def get_revisions_to_build(project)
0
- project.notify :polling_source_control
0
- project.new_revisions
0
+ def initialize(triggered_project)
0
+ @triggered_project = triggered_project
0
+ end
0
+
0
+ def revisions_to_build
0
+ @triggered_project.notify :polling_source_control
0
+ @triggered_project.new_revisions
0
   end
0
 end
0
 
0
 class SuccessfulBuildTrigger
0
- attr_accessor :triggering_project_name
0
+ attr_accessor :triggering_project_name, :triggered_project
0
   
0
- def initialize(triggering_project_name)
0
+ def initialize(triggered_project, triggering_project_name)
0
+ @triggered_project = triggered_project
0
     @triggering_project_name = triggering_project_name.to_s
0
   end
0
   
0
- def get_revisions_to_build(project)
0
+ def revisions_to_build
0
     triggering_project = Project.new(@triggering_project_name)
0
     last_successful_build = last_successful(triggering_project.builds)
0
     
0
- if !last_successful_build || project.find_build(last_successful_build.label)
0
+ if last_successful_build.nil? || @triggered_project.find_build(last_successful_build.label)
0
       []
0
     else
0
       [Revision.new(last_successful_build.label)]
0
@@ -24,7 +29,9 @@ class SuccessfulBuildTrigger
0
   end
0
   
0
   def ==(other)
0
- other.is_a?(SuccessfulBuildTrigger) && triggering_project_name == other.triggering_project_name
0
+ other.is_a?(SuccessfulBuildTrigger) &&
0
+ triggered_project == other.triggered_project &&
0
+ triggering_project_name == other.triggering_project_name
0
   end
0
   
0
   private
0
@@ -34,18 +41,3 @@ class SuccessfulBuildTrigger
0
   end
0
 end
0
 
0
-class SvnExternalTrigger < ChangeInSourceControlTrigger
0
- def get_revisions_to_build
0
- if svn_external_changed
0
- super
0
- end
0
- end
0
-end
0
-
0
-class Project
0
- def triggered_by(trigger)
0
- trigger = SuccessfulBuildTrigger.new(trigger) if trigger.is_a?(String) || trigger.is_a?(Symbol)
0
- @trigger = trigger
0
- end
0
-end
0
-
...
8
9
10
11
 
12
13
14
...
8
9
10
 
11
12
13
14
0
@@ -8,7 +8,7 @@ module CruiseControl
0
   # This hack is needed because db:test:purge implementation for MySQL drops the test database, invalidating
0
   # the existing connection. A solution is to reconnect again.
0
   def self.reconnect
0
- require 'active_record'
0
+ require 'active_record' unless defined? ActiveRecord
0
     configurations = ActiveRecord::Base.configurations
0
     if configurations and configurations.has_key?("test") and configurations["test"]["adapter"] == 'mysql'
0
       ActiveRecord::Base.establish_connection(:test)
...
1
 
...
 
1
0
@@ -1 +1 @@
0
-20 3f 3
0
+25 3f 3
...
137
138
139
140
 
141
142
143
...
137
138
139
 
140
141
142
143
0
@@ -137,7 +137,7 @@ class BuilderIntegrationTest < Test::Unit::TestCase
0
       build = project.build
0
       build_log = File.read("#{build.artifacts_directory}/build.log")
0
 
0
- expected_output = "RAILS_ENV=test\ndb:migrate invoked\n[CruiseControl] Invoking Rake task \"default\"\ndefault invoked\n"
0
+ expected_output = "[CruiseControl] Invoking Rake task \"db:migrate\"\nRAILS_ENV=test\n[CruiseControl] Invoking Rake task \"default\"\n"
0
       assert build_log.include?(expected_output), "#{expected_output.inspect} not found in build log:\n#{build_log}"
0
     end
0
     
...
568
569
570
571
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
572
573
574
...
568
569
570
 
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
0
@@ -568,7 +568,48 @@ class ProjectTest < Test::Unit::TestCase
0
       assert @project.do_clean_checkout?
0
     end
0
   end
0
-
0
+
0
+
0
+ def test_new_project_should_have_source_control_triggers
0
+ project = Project.new('foo')
0
+ trigger_classes = project.triggered_by.map(&:class)
0
+ assert_equal [ChangeInSourceControlTrigger], trigger_classes
0
+ end
0
+
0
+
0
+ def test_project_triggered_by
0
+ project = Project.new('foo')
0
+
0
+ project.triggered_by = []
0
+ assert_equal [], project.triggered_by
0
+
0
+ project.triggered_by 1
0
+ assert_equal [1], project.triggered_by
0
+
0
+ project.triggered_by 2, 3
0
+ assert_equal [1, 2, 3], project.triggered_by
0
+ end
0
+
0
+ def test_project_triggered_by_should_convert_strings_and_symbols_to_successful_build_triggers
0
+ project = Project.new('foo')
0
+
0
+ project.triggered_by = ['foo', 123]
0
+ project.triggered_by :bar
0
+ project.triggered_by << :baz
0
+ assert_equal [SuccessfulBuildTrigger.new(project, 'foo'), 123, SuccessfulBuildTrigger.new(project, 'bar'),
0
+ SuccessfulBuildTrigger.new(project, 'baz')],
0
+ project.triggered_by
0
+ end
0
+
0
+ def test_revisions_to_build_should_merge_revisions_from_triggers
0
+ project = Project.new('foo')
0
+ stub_trigger_1 = Object.new
0
+ stub_trigger_2 = Object.new
0
+ project.triggered_by = [stub_trigger_1, stub_trigger_2]
0
+ stub_trigger_1.stubs(:revisions_to_build).returns([Revision.new(2)])
0
+ stub_trigger_2.stubs(:revisions_to_build).returns([Revision.new(1), Revision.new(3)])
0
+ assert_equal [Revision.new(1), Revision.new(2), Revision.new(3)], project.revisions_to_build
0
+ end
0
   private
0
   
0
   def stub_build(label)
...
19
20
21
22
 
23
24
25
26
 
27
28
29
 
30
31
 
32
33
34
 
35
36
37
38
39
 
40
41
42
43
44
45
 
46
47
 
48
49
 
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
 
71
72
 
73
74
75
 
76
...
19
20
21
 
22
23
24
25
 
26
27
28
 
29
30
 
31
32
33
 
34
35
36
37
38
 
39
40
41
42
43
44
 
45
46
 
47
48
 
49
50
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
53
 
54
55
56
57
58
59
0
@@ -19,58 +19,41 @@ class TriggerTest < Test::Unit::TestCase
0
     in_total_sandbox do |sandbox|
0
       Configuration.stubs(:projects_directory).returns(sandbox.root)
0
       one, two = sandbox.new_project('one'), sandbox.new_project('two')
0
- trigger = SuccessfulBuildTrigger.new(:two)
0
+ trigger = SuccessfulBuildTrigger.new(one, :two)
0
 
0
       create_build one, 1
0
       create_build two, 1
0
- assert_equal [], trigger.get_revisions_to_build(one)
0
+ assert_equal [], trigger.revisions_to_build
0
 
0
       create_build two, 2, :fail!
0
- assert_equal [], trigger.get_revisions_to_build(one)
0
+ assert_equal [], trigger.revisions_to_build
0
       create_build two, 3
0
- assert_equal [Revision.new('3')], trigger.get_revisions_to_build(one)
0
+ assert_equal [Revision.new('3')], trigger.revisions_to_build
0
       
0
       create_build one, 3, :fail!
0
- assert_equal [], trigger.get_revisions_to_build(one)
0
+ assert_equal [], trigger.revisions_to_build
0
 
0
       create_build two, 4
0
       create_build two, 5
0
       create_build two, 6, :fail!
0
- assert_equal [Revision.new('5')], trigger.get_revisions_to_build(one)
0
+ assert_equal [Revision.new('5')], trigger.revisions_to_build
0
     end
0
   end
0
   
0
   def test_triggered_by__change_in_source_control
0
     with_sandbox_project do |sandbox, project|
0
- project.expects(:new_revisions).returns(5)
0
+ project.expects(:new_revisions).returns([Revision.new('5')])
0
 
0
- trigger = ChangeInSourceControlTrigger.new
0
+ trigger = ChangeInSourceControlTrigger.new(project)
0
 
0
- assert_equal 5, trigger.get_revisions_to_build(project)
0
+ assert_equal [Revision.new('5')], trigger.revisions_to_build
0
     end
0
   end
0
-
0
- def test_triggered_by__change_in_svn_external
0
- end
0
-
0
- def test_project_triggered_by
0
- p = Project.new('foo')
0
- def p.trigger
0
- @trigger
0
- end
0
-
0
- assert_equal ChangeInSourceControlTrigger, p.trigger.class
0
-
0
- p.triggered_by 'CruiseControl-Fast'
0
- assert_equal SuccessfulBuildTrigger.new('CruiseControl-Fast'), p.trigger
0
-
0
- p.triggered_by :ccrb
0
- assert_equal SuccessfulBuildTrigger.new(:ccrb), p.trigger
0
- end
0
-
0
+
0
   private
0
-
0
+
0
   def create_build(project, label, state = :succeed!)
0
     project.create_build(label).build_status.send(state, 0)
0
   end
0
+
0
 end

Comments

    No one has commented yet.