dynport_tools 0.2.8 → 0.2.9

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.8
1
+ 0.2.9
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{dynport_tools}
8
- s.version = "0.2.8"
8
+ s.version = "0.2.9"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tobias Schwab"]
12
- s.date = %q{2011-08-23}
12
+ s.date = %q{2011-08-24}
13
13
  s.description = %q{Collection of various tools}
14
14
  s.email = %q{tobias.schwab@dynport.de}
15
15
  s.executables = ["xmldiff", "redis_dumper"]
data/lib/dynport_tools.rb CHANGED
@@ -1,4 +1,9 @@
1
1
  module DynportTools
2
2
  end
3
3
 
4
+ require "time"
5
+ require "typhoeus"
6
+ require "nokogiri"
7
+ require "cgi"
8
+
4
9
  %w(deep_merger differ jenkins redis_dumper xml_file have_attributes redis_q eta).map { |m| require "dynport_tools/#{m}" }
@@ -38,7 +38,7 @@ class DynportTools::ETA
38
38
  end
39
39
 
40
40
  def to_s
41
- "%.1f%%, %.1f/second, ETA: %s" % [percs * 100, per_second, eta.iso8601]
41
+ "%.2f%%, %.2f/second, ETA: %s" % [percs * 100, per_second, eta.iso8601]
42
42
  end
43
43
 
44
44
  def raise_error_when_current_or_total_not_set
@@ -1,6 +1,3 @@
1
- require "typhoeus"
2
- require "nokogiri"
3
-
4
1
  class DynportTools::Jenkins
5
2
  attr_accessor :url
6
3
 
@@ -12,8 +9,49 @@ class DynportTools::Jenkins
12
9
  @hydra ||= Typhoeus::Hydra.new
13
10
  end
14
11
 
15
- def jobs_hash
16
- Nokogiri::XML(Typhoeus::Request.get("#{url}/api/xml").body).search("job").inject({}) do |hash, node|
12
+ def create_project(name, xml)
13
+ post_request "createItem?name=#{escape_job_name(name)}", :headers => { "Content-Type" => "application/xml" }, :body => xml
14
+ end
15
+
16
+ def update_project(name, xml)
17
+ post_request "job/#{escape_job_name(name)}/config.xml", :headers => { "Content-Type" => "application/xml" }, :body => xml
18
+ end
19
+
20
+ def delete_project(name)
21
+ send_to_project(name, "doDelete")
22
+ end
23
+
24
+ def build_project(name)
25
+ send_to_project(name, "build")
26
+ end
27
+
28
+ def disable_project(name)
29
+ send_to_project(name, "disable")
30
+ end
31
+
32
+ def enable_project(name)
33
+ send_to_project(name, "enable")
34
+ end
35
+
36
+ def send_to_project(name, action)
37
+ post_request "job/#{escape_job_name(name)}/#{action}"
38
+ end
39
+
40
+ def post_request(path, options = nil)
41
+ @cache = {}
42
+ Typhoeus::Request.post(*["#{url}/#{path}", options].compact)
43
+ end
44
+
45
+ def cache
46
+ @cache ||= {}
47
+ end
48
+
49
+ def escape_job_name(name)
50
+ URI.escape(name)
51
+ end
52
+
53
+ def projects_hash
54
+ cache[:projects_hash] ||= Nokogiri::XML(Typhoeus::Request.get("#{url}/api/xml").body).search("job").inject({}) do |hash, node|
17
55
  url = node.at("url").inner_text.strip if node.at("url")
18
56
  name = node.at("name").inner_text.strip if node.at("name")
19
57
  hash[url] = { :url => url, :name => name }
@@ -21,9 +59,10 @@ class DynportTools::Jenkins
21
59
  end
22
60
  end
23
61
 
24
- def job_details
62
+ def project_details
63
+ return cache[:projects_details] if cache[:projects_details]
25
64
  jobs = {}
26
- jobs_hash.each do |url, job|
65
+ projects_hash.each do |url, job|
27
66
  request = Typhoeus::Request.new("#{url}config.xml")
28
67
  request.on_complete do |response|
29
68
  xml = Nokogiri::XML(response.body).to_s
@@ -32,24 +71,100 @@ class DynportTools::Jenkins
32
71
  hydra.queue(request)
33
72
  end
34
73
  hydra.run
35
- jobs
74
+ cache[:projects_details] = jobs
75
+ end
76
+
77
+ def remote_projects
78
+ project_details.inject({}) do |hash, (url, project_hash)|
79
+ hash.merge!(project_hash[:name] => RemoteProject.new(:url => project_hash[:url], :name => project_hash[:name], :xml => project_hash[:body]))
80
+ end
81
+ end
82
+
83
+ class RemoteProject
84
+ attr_accessor :url, :name, :xml
85
+
86
+ def initialize(options = {})
87
+ options.each do |key, value|
88
+ self.send(:"#{key}=", value) if self.respond_to?(:"#{key}=")
89
+ end
90
+ end
91
+
92
+ def doc
93
+ @doc ||= Nokogiri::XML(xml) if xml
94
+ end
95
+
96
+ def md5
97
+ Digest::MD5.hexdigest(xml) if xml
98
+ end
99
+
100
+ def days_to_keep
101
+ logrotate_value_when_set("daysToKeep")
102
+ end
103
+
104
+ def num_to_keep
105
+ logrotate_value_when_set("numToKeep")
106
+ end
107
+
108
+ def logrotate_value_when_set(key)
109
+ if node = doc.at("/project/logRotator/#{key}")
110
+ node.inner_text.to_i if node.inner_text.to_i != -1
111
+ end
112
+ end
113
+
114
+ def commands
115
+ doc.xpath("/project/builders/hudson.tasks.Shell/command").map(&:inner_text)
116
+ end
117
+
118
+ def crontab_patterns
119
+ doc.xpath("/project/triggers/hudson.triggers.TimerTrigger/spec").map(&:inner_text)
120
+ end
121
+
122
+ def disabled?
123
+ doc.at("/project/disabled/text()").to_s == "true"
124
+ end
125
+
126
+ def child_projects
127
+ if projects = doc.xpath("/project/publishers/hudson.tasks.BuildTrigger/childProjects").first
128
+ projects.inner_text.split(/\s*,\s*/)
129
+ else
130
+ []
131
+ end
132
+ end
133
+
134
+ def email_addresses
135
+ doc.xpath("/project/publishers/hudson.tasks.Mailer/recipients").map { |rec| rec.inner_text.split(",") }.flatten
136
+ end
137
+
138
+ def node
139
+ doc.xpath("/project/assignedNode").map { |n| n.inner_text }.first
140
+ end
141
+
142
+ def locks
143
+ doc.xpath("/project/buildWrappers/hudson.plugins.locksandlatches.LockWrapper/locks/hudson.plugins.locksandlatches.LockWrapper_-LockWaitConfig/name").map(&:inner_text)
144
+ end
36
145
  end
37
146
 
38
147
  class Project
39
- attr_accessor :name, :commands, :crontab_pattern, :days_to_keep, :num_to_keep, :node, :child_projects
148
+ attr_accessor :name, :commands, :crontab_pattern, :days_to_keep, :num_to_keep, :node, :child_projects, :locks, :disabled, :description, :email_addresses
40
149
  DEFAUL_SCM = "hudson.scm.NullSCM"
41
150
 
42
- def initialize(name)
151
+ def initialize(name = nil)
43
152
  self.name = name
44
153
  self.commands = []
45
154
  self.child_projects = []
155
+ self.email_addresses = []
156
+ self.locks = []
157
+ end
158
+
159
+ def md5
160
+ Digest::MD5.hexdigest(to_xml)
46
161
  end
47
162
 
48
163
  def to_xml
49
164
  Nokogiri::XML::Builder.new(:encoding => "UTF-8") do |xml|
50
165
  xml.project do
51
166
  xml.actions
52
- xml.description
167
+ xml.description *[description].compact
53
168
  if days_to_keep || num_to_keep
54
169
  xml.logRotator do
55
170
  xml.daysToKeep days_to_keep || -1
@@ -58,14 +173,18 @@ class DynportTools::Jenkins
58
173
  xml.artifactNumToKeep -1
59
174
  end
60
175
  end
61
- xml.keepDependencies "false"
176
+ xml.keepDependencies false
62
177
  xml.properties
63
178
  xml.scm(:class => DEFAUL_SCM)
64
- xml.assignedNode node if node
65
- xml.canRoam "true"
66
- xml.disabled "false"
67
- xml.blockBuildWhenDownstreamBuilding "false"
68
- xml.blockBuildWhenUpstreamBuilding "false"
179
+ if node
180
+ xml.assignedNode node
181
+ xml.canRoam false
182
+ else
183
+ xml.canRoam true
184
+ end
185
+ xml.disabled disabled ? true : false
186
+ xml.blockBuildWhenDownstreamBuilding false
187
+ xml.blockBuildWhenUpstreamBuilding false
69
188
  xml.triggers(:class => "vector") do
70
189
  if crontab_pattern
71
190
  xml.send("hudson.triggers.TimerTrigger") do
@@ -73,11 +192,11 @@ class DynportTools::Jenkins
73
192
  end
74
193
  end
75
194
  end
76
- xml.concurrentBuild "false"
195
+ xml.concurrentBuild false
77
196
  xml.builders do
78
197
  commands.each do |command|
79
198
  xml.send("hudson.tasks.Shell") do
80
- xml.command ["#!/bin/sh", command].join("\n")
199
+ xml.command command
81
200
  end
82
201
  end
83
202
  end
@@ -92,8 +211,24 @@ class DynportTools::Jenkins
92
211
  end
93
212
  end
94
213
  end
214
+ if email_addresses.any?
215
+ xml.send("hudson.tasks.Mailer") do
216
+ xml.recipients email_addresses.join(",")
217
+ xml.dontNotifyEveryUnstableBuild true
218
+ xml.sendToIndividuals false
219
+ end
220
+ end
95
221
  end
96
222
  xml.buildWrappers do
223
+ if locks.any?
224
+ xml.send("hudson.plugins.locksandlatches.LockWrapper") do
225
+ xml.locks do
226
+ locks.each do |lock|
227
+ xml.send("hudson.plugins.locksandlatches.LockWrapper_-LockWaitConfig") { xml.name lock }
228
+ end
229
+ end
230
+ end
231
+ end
97
232
  end
98
233
  end
99
234
  end.to_xml
@@ -1,10 +1,15 @@
1
1
  require "nokogiri"
2
2
 
3
3
  class DynportTools::XmlFile
4
- attr_accessor :path
4
+ attr_accessor :path, :content
5
5
 
6
- def initialize(path)
7
- self.path = path.to_s
6
+ def initialize(path_or_options = nil)
7
+ if path_or_options.is_a?(Hash)
8
+ self.path = path_or_options[:path].to_s if path_or_options[:path].to_s
9
+ self.content = path_or_options[:content]
10
+ elsif !path_or_options.nil?
11
+ self.path = path_or_options.to_s
12
+ end
8
13
  end
9
14
 
10
15
  def nodes_hash
@@ -12,7 +17,7 @@ class DynportTools::XmlFile
12
17
  end
13
18
 
14
19
  def doc
15
- @doc ||= Nokogiri::XML(File.open(path))
20
+ @doc ||= Nokogiri::XML(content || File.open(path))
16
21
  end
17
22
 
18
23
  def parse_node(node)
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require "time"
3
2
 
4
3
  describe "DynportTools::ETA" do
5
4
  let(:eta) { DynportTools::ETA.new(:current => 17, :total => 100) }
@@ -101,7 +100,7 @@ describe "DynportTools::ETA" do
101
100
  end
102
101
 
103
102
  it "returns the correct string" do
104
- DynportTools::ETA.new(:current => 10, :total => 100, :started => time - 1).to_s.should == "10.0%, 10.0/second, ETA: 2011-02-03T04:50:09+01:00"
103
+ DynportTools::ETA.new(:current => 10, :total => 100, :started => time - 1).to_s.should == "10.00%, 10.00/second, ETA: 2011-02-03T04:50:09+01:00"
105
104
  end
106
105
 
107
106
  describe "#from_time_string" do
@@ -5,6 +5,91 @@ require "dynport_tools/jenkins"
5
5
  describe "DynportTools::Jenkins" do
6
6
  let(:url) { "http://some.url.com:8098" }
7
7
  let(:jenkins) { DynportTools::Jenkins.new(url) }
8
+ before(:each) do
9
+ Typhoeus::Request.stub!(:post).and_return nil
10
+ end
11
+
12
+ describe "RemoteProject" do
13
+ let(:remote_project) do
14
+ xml = File.read(root.join("spec/fixtures/jenkins_job.xml"))
15
+ remote_project = DynportTools::Jenkins::RemoteProject.new(:xml => xml)
16
+ remote_project
17
+ end
18
+
19
+ it "can be initialized" do
20
+ DynportTools::Jenkins::RemoteProject.new(:url => "some/url", :name => "Some Name", :rgne => "true").should return_values(:url => "some/url",
21
+ :name => "Some Name"
22
+ )
23
+ end
24
+
25
+ it "returns the correct " do
26
+ remote_project.commands.should == [%(ssh some.host \"touch /some/path/running.pid\")]
27
+ end
28
+
29
+ it "returns an empty array when no commands found" do
30
+ DynportTools::Jenkins::RemoteProject.new(:url => "some/url", :name => "Some Name", :xml => "<project/>").commands.should be_empty
31
+ end
32
+
33
+ it "returns the correct crontab_patterns" do
34
+ remote_project.crontab_patterns.should == ["0 4 * * *"]
35
+ end
36
+
37
+ it "returns the correct childProjects" do
38
+ remote_project.child_projects.should == ["Project 2", "Project 6", "Prohect 9"]
39
+ end
40
+
41
+ it "returns the correct locks" do
42
+ remote_project.locks.should == %w(Import)
43
+ end
44
+
45
+ it "returns the correct md5" do
46
+ remote_project.stub!(:xml).and_return "some xml"
47
+ remote_project.md5.should == "53bdfcda073f189a71901011123abf9a"
48
+ end
49
+
50
+ describe "logrotate" do
51
+ it "returns the correct amount of days_to_keep" do
52
+ remote_project.days_to_keep.should == 7
53
+ end
54
+
55
+ it "returns nil when days_to_keep == -1" do
56
+ DynportTools::Jenkins::RemoteProject.new(:xml => "<project><logRotator><daysToKeep>-1</daysToKeep></logRotator></project>").days_to_keep.should be_nil
57
+ end
58
+
59
+ it "returns nil for num_to_keep when -1" do
60
+ remote_project.num_to_keep.should be_nil
61
+ end
62
+
63
+ it "returns the correct value for num_to_keep when set" do
64
+ DynportTools::Jenkins::RemoteProject.new(:xml => "<project><logRotator><numToKeep>20</numToKeep></logRotator></project>").num_to_keep.should == 20
65
+ end
66
+ end
67
+
68
+ it "returns the correct disabled status" do
69
+ remote_project.should be_disabled
70
+ end
71
+
72
+ it "returns the correct email_addresses" do
73
+ remote_project.email_addresses.should == %w(test@test.xx)
74
+ end
75
+
76
+ it "returns false when not disabled" do
77
+ DynportTools::Jenkins::RemoteProject.new(:xml => "<project><disabled>false</disabled></project>").should_not be_disabled
78
+ end
79
+
80
+ it "extracts the correct node" do
81
+ remote_project.node.should == "Import"
82
+ end
83
+
84
+ describe "#with nothing found" do
85
+ let(:empty_remote_project) { DynportTools::Jenkins::RemoteProject.new(:xml => "<project/>") }
86
+ [:child_projects, :commands, :crontab_patterns, :locks].each do |method|
87
+ it "returns an empty array for #{method}" do
88
+ empty_remote_project.send(method).should == []
89
+ end
90
+ end
91
+ end
92
+ end
8
93
 
9
94
  describe "Project" do
10
95
  let(:job) { DynportTools::Jenkins::Project.new("Some Name") }
@@ -19,6 +104,14 @@ describe "DynportTools::Jenkins" do
19
104
  job.child_projects.should == []
20
105
  end
21
106
 
107
+ it "sets the commands to an empty array" do
108
+ job.locks.should == []
109
+ end
110
+
111
+ it "sets the email addresses to an empty array" do
112
+ job.email_addresses.should == []
113
+ end
114
+
22
115
  it "sets the name" do
23
116
  job.name.should == "Some Name"
24
117
  end
@@ -38,12 +131,19 @@ describe "DynportTools::Jenkins" do
38
131
  job.to_xml.should include("</project>")
39
132
  end
40
133
 
41
- %w(actions description properties builders publishers buildWrappers).each do |key|
134
+ %w(actions description properties publishers buildWrappers).each do |key|
42
135
  it "includes an empty node #{key}" do
43
136
  doc.at("/project/#{key}").children.should be_empty
44
137
  end
45
138
  end
46
139
 
140
+ it "sets the correct email_addresses when present" do
141
+ job.email_addresses = %w(test@test.xx test2@test.xx)
142
+ doc.xpath("/project/publishers/hudson.tasks.Mailer/recipients").map(&:inner_text).should == ["test@test.xx,test2@test.xx"]
143
+ doc.at("/project/publishers/hudson.tasks.Mailer/dontNotifyEveryUnstableBuild").inner_text.should == "true"
144
+ doc.at("/project/publishers/hudson.tasks.Mailer/sendToIndividuals").inner_text.should == "false"
145
+ end
146
+
47
147
  {
48
148
  "keepDependencies" => "false",
49
149
  "canRoam" => "true",
@@ -57,6 +157,11 @@ describe "DynportTools::Jenkins" do
57
157
  end
58
158
  end
59
159
 
160
+ it "sets disabled to true when set" do
161
+ job.disabled = true
162
+ doc.at("/project/disabled").inner_text.should == "true"
163
+ end
164
+
60
165
  { "scm" => "hudson.scm.NullSCM", "triggers" => "vector" }.each do |key, clazz|
61
166
  it "sets the class of #{key} to #{clazz}" do
62
167
  doc.at("/project/#{key}")["class"].should == clazz
@@ -68,7 +173,7 @@ describe "DynportTools::Jenkins" do
68
173
  job.commands << "date"
69
174
  shell_tasks = doc.search("project/builders/*")
70
175
  shell_tasks.map(&:name).should == ["hudson.tasks.Shell", "hudson.tasks.Shell"]
71
- shell_tasks.map { |node| node.at("command").inner_text }.should == ["#!/bin/sh\nhostname", "#!/bin/sh\ndate"]
176
+ shell_tasks.map { |node| node.at("command").inner_text }.should == ["hostname", "date"]
72
177
  end
73
178
 
74
179
  it "includes crontab like triggers" do
@@ -88,6 +193,17 @@ describe "DynportTools::Jenkins" do
88
193
  it "sets assignedNode when node is set" do
89
194
  job.node = "processor"
90
195
  doc.at("/project/assignedNode").inner_text.should == "processor"
196
+ doc.at("/project/canRoam").inner_text.should == "false"
197
+ end
198
+
199
+ it "allows setting a description" do
200
+ job.description = "some description"
201
+ doc.at("/project/description").inner_text.should == "some description"
202
+ end
203
+
204
+ it "returns the correct md5" do
205
+ job.stub(:to_xml).and_return "some test"
206
+ job.md5.should == "f1b75ac7689ff88e1ecc40c84b115785"
91
207
  end
92
208
 
93
209
  describe "with days_to_keep set" do
@@ -150,6 +266,22 @@ describe "DynportTools::Jenkins" do
150
266
  end
151
267
  end
152
268
  end
269
+
270
+ describe "#with locks" do
271
+ let(:locks) { doc.xpath("/project/buildWrappers/hudson.plugins.locksandlatches.LockWrapper/locks/hudson.plugins.locksandlatches.LockWrapper_-LockWaitConfig") }
272
+ before(:each) do
273
+ job.locks << "exclusive3"
274
+ job.locks << "exclusive2"
275
+ end
276
+
277
+ it "sets the correct amount of locks" do
278
+ locks.count.should == 2
279
+ end
280
+
281
+ it "sets the correct locks" do
282
+ locks.map { |l| l.at("name").inner_text }.should == %w(exclusive3 exclusive2)
283
+ end
284
+ end
153
285
  end
154
286
  end
155
287
 
@@ -159,7 +291,15 @@ describe "DynportTools::Jenkins" do
159
291
  end
160
292
  end
161
293
 
162
- describe "#jobs_hash" do
294
+ describe "#post_request" do
295
+ it "clears the local cache" do
296
+ jenkins.instance_variable_set("@cache", { :a => 1 })
297
+ jenkins.post_request("some/path")
298
+ jenkins.instance_variable_get("@cache").should == {}
299
+ end
300
+ end
301
+
302
+ describe "#projects_hash" do
163
303
  let(:body) do
164
304
  html =<<-HTML
165
305
  <hudson>
@@ -194,19 +334,45 @@ describe "DynportTools::Jenkins" do
194
334
 
195
335
  it "fetches the correct url" do
196
336
  Typhoeus::Request.should_receive(:get).with("http://some.url.com:8098/api/xml")
197
- jenkins.jobs_hash
337
+ jenkins.projects_hash
198
338
  end
199
339
 
200
- it "returns the correct jobs_hash" do
201
- jobs = jenkins.jobs_hash
340
+ it "returns the correct projects_hash" do
341
+ jobs = jenkins.projects_hash
202
342
  jobs["http://hudson.host:8080/job/Job1/"].should == { :url => "http://hudson.host:8080/job/Job1/", :name => "Job 1"}
203
343
  jobs["http://hudson.host:8080/job/Job2/"].should == { :url => "http://hudson.host:8080/job/Job2/", :name => "Job 2"}
204
344
  end
205
345
  end
346
+
347
+ it "sends the correct Typhoeus request when creating a project" do
348
+ xml = "some_xml"
349
+ Typhoeus::Request.should_receive(:post).with("http://some.url.com:8098/createItem?name=Test%20Job",
350
+ :headers => { "Content-Type" => "application/xml" }, :body => "some_xml"
351
+ )
352
+ jenkins.create_project("Test Job", xml)
353
+ end
354
+
355
+ it "sends the correct request when updating a project" do
356
+ xml = "some_update"
357
+ Typhoeus::Request.should_receive(:post).with("http://some.url.com:8098/job/Test%20Job/config.xml",
358
+ :headers => { "Content-Type" => "application/xml" }, :body => "some_update"
359
+ )
360
+ jenkins.update_project("Test Job", xml)
361
+ end
362
+
363
+ {
364
+ :delete_project => "doDelete", :build_project => "build", :disable_project => "disable",
365
+ :enable_project => "enable"
366
+ }.each do |method, action|
367
+ it "posts to the correct url when calling #{action}" do
368
+ Typhoeus::Request.should_receive(:post).with("http://some.url.com:8098/job/Test%20Job/#{action}")
369
+ jenkins.send(method, "Test Job")
370
+ end
371
+ end
206
372
 
207
- describe "#job_details" do
373
+ describe "#project_details" do
208
374
  before(:each) do
209
- jenkins.stub!(:jobs_hash).and_return(
375
+ jenkins.stub!(:projects_hash).and_return(
210
376
  "http://hudson.host:8080/job/Job1/" => { :url => "http://hudson.host:8080/job/Job1/", :name => "Job 1"},
211
377
  "http://hudson.host:8080/job/Job2/" => { :url => "http://hudson.host:8080/job/Job2/", :name => "Job 2"}
212
378
  )
@@ -217,7 +383,7 @@ describe "DynportTools::Jenkins" do
217
383
  response2 = Typhoeus::Response.new(:code => 200, :headers => "", :body => "<root><a>test2</a><b></b></root>")
218
384
  jenkins.hydra.stub(:get, "http://hudson.host:8080/job/Job1/config.xml").and_return(response1)
219
385
  jenkins.hydra.stub(:get, "http://hudson.host:8080/job/Job2/config.xml").and_return(response2)
220
- details = jenkins.job_details
386
+ details = jenkins.project_details
221
387
  details.should be_an_instance_of(Hash)
222
388
  details["http://hudson.host:8080/job/Job2/"].should == {
223
389
  :body=>"<?xml version=\"1.0\"?>\n<root>\n <a>test2</a>\n <b/>\n</root>\n",
@@ -228,39 +394,29 @@ describe "DynportTools::Jenkins" do
228
394
  :md5=>"14fa3890bea86820f7e45ce7f5a3ada4", :name=>"Job 1", :url=>"http://hudson.host:8080/job/Job1/"
229
395
  }
230
396
  end
397
+ end
398
+
399
+ describe "#remote_projects" do
400
+ before(:each) do
401
+ jenkins.stub(:project_details).and_return({})
402
+ end
403
+ it "calls project_details" do
404
+ jenkins.should_receive(:project_details).and_return({})
405
+ jenkins.remote_projects
406
+ end
231
407
 
232
- it "has a builder" do
233
- builder = Nokogiri::XML::Builder.new(:encoding => "UTF-8") do |xml|
234
- xml.project {
235
- xml.actions
236
- xml.description
237
- xml.keepDependencies false
238
- xml.properties
239
- xml.scm(:class => "hudson.scm.NullSCM")
240
- xml.canRoam true
241
- xml.disabled false
242
- xml.blockBuildWhenDownstreamBuilding false
243
- xml.blockBuildWhenUpstreamBuilding false
244
- xml.triggers(:class => "vector")
245
- xml.concurrentBuild false
246
- xml.builders do
247
- xml.send("hudson.tasks.Shell") do
248
- xml.command %(#!/bin/sh\nssh some.host "cd /some/path && ./script/runner -e production 'Some.command'")
249
- end
250
- end
251
- xml.publishers
252
- xml.buildWrappers do
253
- xml.send("hudson.plugins.locksandlatches.LockWrapper") do
254
- xml.locks do
255
- xml.send("hudson.plugins.locksandlatches.LockWrapper_-LockWaitConfig") do
256
- xml.name "Popularities"
257
- end
258
- end
259
- end
260
- end
261
- }
262
- end
263
- builder.to_xml.should == Nokogiri::XML(File.read(root.join("spec/fixtures/jenkins_job.xml"))).to_s
408
+ it "returns a hash" do
409
+ jenkins.remote_projects.should be_kind_of(Hash)
410
+ end
411
+
412
+ it "sets RemoteProject as values for hash" do
413
+ jenkins.should_receive(:project_details).and_return(
414
+ "url1" => { :name => "Project 1", :body => "some xml", :url => "url1" },
415
+ "url2" => { :name => "Project 2", :body => "some other xml", :url => "url2" }
416
+ )
417
+ remote_projects = jenkins.remote_projects
418
+ remote_projects.values.map(&:class).should == [DynportTools::Jenkins::RemoteProject, DynportTools::Jenkins::RemoteProject]
419
+ remote_projects["Project 1"].should return_values(:url => "url1", :name => "Project 1", :xml => "some xml")
264
420
  end
265
421
  end
266
422
  end
@@ -11,6 +11,30 @@ describe "DynportTools::XmlFile" do
11
11
  it "sets the correct path" do
12
12
  DynportTools::XmlFile.new(FILE1).path.should == FILE1.to_s
13
13
  end
14
+
15
+ it "also sets the pathwhen given as hash" do
16
+ DynportTools::XmlFile.new(:path => FILE1).path.should == FILE1.to_s
17
+ end
18
+
19
+ it "sets content when given" do
20
+ DynportTools::XmlFile.new(:content => "some content").content.should == "some content"
21
+ end
22
+ end
23
+
24
+ describe "#doc" do
25
+ it "opens a file when set" do
26
+ f = double("f")
27
+ File.should_receive(:open).with("/some/path").and_return f
28
+ Nokogiri.should_receive(:XML).with(f).and_return nil
29
+ DynportTools::XmlFile.new("/some/path").doc
30
+ end
31
+
32
+ it "parses the direct content when present" do
33
+ file = DynportTools::XmlFile.new
34
+ file.content = "some content"
35
+ Nokogiri.should_receive(:XML).with("some content").and_return nil
36
+ file.doc
37
+ end
14
38
  end
15
39
 
16
40
  describe "#nodes_hash" do
@@ -2,27 +2,51 @@
2
2
  <project>
3
3
  <actions/>
4
4
  <description></description>
5
+ <logRotator>
6
+ <daysToKeep>7</daysToKeep>
7
+ <numToKeep>-1</numToKeep>
8
+ <artifactDaysToKeep>-1</artifactDaysToKeep>
9
+ <artifactNumToKeep>-1</artifactNumToKeep>
10
+ </logRotator>
5
11
  <keepDependencies>false</keepDependencies>
6
12
  <properties/>
7
13
  <scm class="hudson.scm.NullSCM"/>
14
+ <assignedNode>Import</assignedNode>
8
15
  <canRoam>true</canRoam>
9
- <disabled>false</disabled>
16
+ <disabled>true</disabled>
10
17
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
11
18
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
12
- <triggers class="vector"/>
19
+ <triggers class="vector">
20
+ <hudson.triggers.TimerTrigger>
21
+ <spec>0 4 * * *</spec>
22
+ </hudson.triggers.TimerTrigger>
23
+ </triggers>
13
24
  <concurrentBuild>false</concurrentBuild>
14
25
  <builders>
15
26
  <hudson.tasks.Shell>
16
- <command>#!/bin/sh
17
- ssh some.host &quot;cd /some/path &amp;&amp; ./script/runner -e production &apos;Some.command&apos;&quot;</command>
27
+ <command>ssh some.host &quot;touch /some/path/running.pid&quot;</command>
18
28
  </hudson.tasks.Shell>
19
29
  </builders>
20
- <publishers/>
30
+ <publishers>
31
+ <hudson.tasks.BuildTrigger>
32
+ <childProjects>Project 2,Project 6, Prohect 9</childProjects>
33
+ <threshold>
34
+ <name>SUCCESS</name>
35
+ <ordinal>0</ordinal>
36
+ <color>BLUE</color>
37
+ </threshold>
38
+ </hudson.tasks.BuildTrigger>
39
+ <hudson.tasks.Mailer>
40
+ <recipients>test@test.xx</recipients>
41
+ <dontNotifyEveryUnstableBuild>true</dontNotifyEveryUnstableBuild>
42
+ <sendToIndividuals>false</sendToIndividuals>
43
+ </hudson.tasks.Mailer>
44
+ </publishers>
21
45
  <buildWrappers>
22
46
  <hudson.plugins.locksandlatches.LockWrapper>
23
47
  <locks>
24
48
  <hudson.plugins.locksandlatches.LockWrapper_-LockWaitConfig>
25
- <name>Popularities</name>
49
+ <name>Import</name>
26
50
  </hudson.plugins.locksandlatches.LockWrapper_-LockWaitConfig>
27
51
  </locks>
28
52
  </hudson.plugins.locksandlatches.LockWrapper>
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynport_tools
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 8
10
- version: 0.2.8
9
+ - 9
10
+ version: 0.2.9
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tobias Schwab
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-08-23 00:00:00 +02:00
18
+ date: 2011-08-24 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency