jenkins_api_client 0.12.1 → 0.13.0
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/.travis.yml +2 -0
- data/CHANGELOG.md +30 -1
- data/CONTRIBUTORS.md +13 -0
- data/README.md +126 -66
- data/Vagrantfile +85 -0
- data/config/login.yml.example +4 -0
- data/jenkins_api_client.gemspec +12 -12
- data/lib/jenkins_api_client/build_queue.rb +34 -0
- data/lib/jenkins_api_client/cli/job.rb +4 -11
- data/lib/jenkins_api_client/client.rb +241 -79
- data/lib/jenkins_api_client/exceptions.rb +109 -21
- data/lib/jenkins_api_client/job.rb +143 -28
- data/lib/jenkins_api_client/node.rb +16 -8
- data/lib/jenkins_api_client/system.rb +21 -2
- data/lib/jenkins_api_client/version.rb +2 -2
- data/lib/jenkins_api_client/view.rb +18 -1
- data/spec/func_tests/client_spec.rb +9 -15
- data/spec/func_tests/job_spec.rb +190 -51
- data/spec/func_tests/node_spec.rb +29 -12
- data/spec/func_tests/spec_helper.rb +1 -7
- data/spec/func_tests/system_spec.rb +25 -6
- data/spec/func_tests/view_spec.rb +101 -34
- data/spec/unit_tests/build_queue_spec.rb +4 -0
- data/spec/unit_tests/client_spec.rb +2 -36
- data/spec/unit_tests/job_spec.rb +48 -5
- data/spec/unit_tests/node_spec.rb +4 -7
- data/spec/unit_tests/spec_helper.rb +1 -0
- data/spec/unit_tests/system_spec.rb +15 -2
- data/spec/unit_tests/view_spec.rb +11 -7
- data/travis/jenkins_config_with_crumb.xml +67 -0
- data/travis/setup_crumb.sh +11 -0
- data/travis/spec.yml +4 -0
- metadata +158 -140
@@ -20,6 +20,8 @@
|
|
20
20
|
# THE SOFTWARE.
|
21
21
|
#
|
22
22
|
|
23
|
+
require 'logger'
|
24
|
+
|
23
25
|
module JenkinsApi
|
24
26
|
# This module contains classes that define exceptions for various catories.
|
25
27
|
#
|
@@ -28,8 +30,9 @@ module JenkinsApi
|
|
28
30
|
# RuntimeError.
|
29
31
|
#
|
30
32
|
class ApiException < RuntimeError
|
31
|
-
def initialize(message = "")
|
32
|
-
|
33
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
34
|
+
logger.add(log_level) { "#{self.class}: #{message}" }
|
35
|
+
super(message)
|
33
36
|
end
|
34
37
|
end
|
35
38
|
|
@@ -37,57 +40,142 @@ module JenkinsApi
|
|
37
40
|
# but not provided.
|
38
41
|
#
|
39
42
|
class NothingSubmitted < ApiException
|
40
|
-
def initialize(message = "")
|
41
|
-
|
43
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
44
|
+
msg = "Nothing is submitted. #{message}"
|
45
|
+
super(logger, msg)
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
45
49
|
# This exception class handles cases where a job not able to be created
|
46
50
|
# because it already exists.
|
47
51
|
#
|
48
|
-
class
|
49
|
-
def initialize(message = "")
|
50
|
-
super(
|
52
|
+
class JobAlreadyExists < ApiException
|
53
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
54
|
+
super(logger, message)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
# Support for backward compatibility
|
58
|
+
JobAlreadyExistsWithName = JobAlreadyExists
|
59
|
+
|
60
|
+
class ViewAlreadyExists < ApiException
|
61
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
62
|
+
super(logger, message)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class NodeAlreadyExists < ApiException
|
67
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
68
|
+
super(logger, message)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# This exception class handles cases where invalid credentials are provided
|
73
|
+
# to connect to the Jenkins.
|
74
|
+
#
|
75
|
+
class Unauthorized < ApiException
|
76
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
77
|
+
msg = "Invalid credentials are provided. #{message}"
|
78
|
+
super(logger, msg, Logger::FATAL)
|
51
79
|
end
|
52
80
|
end
|
81
|
+
UnauthorizedException = Unauthorized
|
53
82
|
|
54
83
|
# This exception class handles cases where invalid credentials are provided
|
55
84
|
# to connect to the Jenkins.
|
56
85
|
#
|
57
|
-
class
|
58
|
-
def initialize(message = "")
|
59
|
-
|
86
|
+
class Forbidden < ApiException
|
87
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
88
|
+
msg = "The Crumb was expired or not sent to the server." +
|
89
|
+
" Perhaps the CSRF protection was not enabled on the server" +
|
90
|
+
" when the client was initialized. Please re-initialize the" +
|
91
|
+
" client. #{message}"
|
92
|
+
super(logger, msg)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
# Support for backward compatibility
|
96
|
+
ForbiddenException = Forbidden
|
97
|
+
|
98
|
+
# This exception class handles cases where a requested page is not found on
|
99
|
+
# the Jenkins API.
|
100
|
+
#
|
101
|
+
class NotFound < ApiException
|
102
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
103
|
+
msg = "Requested component is not found on the Jenkins CI server." \
|
104
|
+
if message.empty?
|
105
|
+
super(logger, msg)
|
60
106
|
end
|
61
107
|
end
|
108
|
+
# Support for backward compatibility
|
109
|
+
NotFoundException = NotFound
|
62
110
|
|
63
111
|
# This exception class handles cases where a requested page is not found on
|
64
112
|
# the Jenkins API.
|
65
113
|
#
|
66
|
-
class
|
67
|
-
def initialize(message = "")
|
68
|
-
|
69
|
-
|
114
|
+
class CrumbNotFound < NotFound
|
115
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
116
|
+
msg = "No crumb available on the server. #{message}"
|
117
|
+
super(logger, msg)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class JobNotFound < NotFound
|
122
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
123
|
+
msg = "The specified job is not found" if message.empty?
|
124
|
+
super(logger, msg)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class ViewNotFound < NotFound
|
129
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
130
|
+
msg = "The specified view is not found" if message.empty?
|
131
|
+
super(logger, msg)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class NodeNotFound < NotFound
|
136
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
137
|
+
msg = "The specified node is not found" if message.empty?
|
138
|
+
super(logger, msg)
|
70
139
|
end
|
71
140
|
end
|
72
141
|
|
73
142
|
# This exception class handles cases where the Jenkins API returns with a
|
74
143
|
# 500 Internel Server Error.
|
75
144
|
#
|
76
|
-
class
|
77
|
-
def initialize(message = "")
|
78
|
-
|
145
|
+
class InternalServerError < ApiException
|
146
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
147
|
+
msg = "Internel Server Error. Perhaps the in-memory configuration of" +
|
79
148
|
" Jenkins is different from the disk configuration." +
|
80
149
|
" Please try to reload the configuration #{message}"
|
81
|
-
|
150
|
+
super(logger, msg)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
# Support for backward compatibility
|
154
|
+
InternalServerErrorException = InternalServerError
|
155
|
+
|
156
|
+
# This exception class handles cases where the Jenkins is getting restarted
|
157
|
+
# or reloaded where the response code returned is 503
|
158
|
+
#
|
159
|
+
class ServiceUnavailable < ApiException
|
160
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
161
|
+
msg = "Jenkins is being reloaded or restarted. Please wait till" +
|
162
|
+
" Jenkins is completely back online. This can be" +
|
163
|
+
" programatically achieved by System#wait_for_ready #{message}"
|
164
|
+
super(logger, msg)
|
82
165
|
end
|
83
166
|
end
|
167
|
+
# Support for backward compatibility
|
168
|
+
ServiceUnavailableException = ServiceUnavailable
|
84
169
|
|
85
170
|
# Exception occurred while running java CLI commands
|
86
171
|
#
|
87
|
-
class
|
88
|
-
def initialize(message = "")
|
89
|
-
|
172
|
+
class CLIError < ApiException
|
173
|
+
def initialize(logger, message = "", log_level = Logger::ERROR)
|
174
|
+
msg = "Execute CLI Error. #{message}"
|
175
|
+
super(logger, msg)
|
90
176
|
end
|
91
177
|
end
|
178
|
+
# Support for backward compatibility
|
179
|
+
CLIException = CLIError
|
92
180
|
end
|
93
181
|
end
|
@@ -31,6 +31,7 @@ module JenkinsApi
|
|
31
31
|
#
|
32
32
|
def initialize(client)
|
33
33
|
@client = client
|
34
|
+
@logger = @client.logger
|
34
35
|
end
|
35
36
|
|
36
37
|
# Return a string representation of the object
|
@@ -45,6 +46,7 @@ module JenkinsApi
|
|
45
46
|
# @param [XML] xml
|
46
47
|
#
|
47
48
|
def create(job_name, xml)
|
49
|
+
@logger.info "Creating job '#{job_name}'"
|
48
50
|
@client.post_config("/createItem?name=#{job_name}", xml)
|
49
51
|
end
|
50
52
|
|
@@ -102,7 +104,8 @@ module JenkinsApi
|
|
102
104
|
supported_scm = ["git", "subversion", "cvs"]
|
103
105
|
|
104
106
|
# Set default values for params that are not specified.
|
105
|
-
raise
|
107
|
+
raise ArgumentError, "Job name must be specified" \
|
108
|
+
unless params.is_a?(Hash) && params[:name]
|
106
109
|
if params[:keep_dependencies].nil?
|
107
110
|
params[:keep_dependencies] = false
|
108
111
|
end
|
@@ -142,6 +145,8 @@ module JenkinsApi
|
|
142
145
|
params[:child_threshold] = 'failure'
|
143
146
|
end
|
144
147
|
|
148
|
+
@logger.debug "Creating a freestyle job with params: #{params.inspect}"
|
149
|
+
|
145
150
|
# Build the Job xml file based on the parameters given
|
146
151
|
builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') { |xml|
|
147
152
|
xml.project {
|
@@ -210,6 +215,7 @@ module JenkinsApi
|
|
210
215
|
# Adding email notification to a job
|
211
216
|
#
|
212
217
|
# @param [Hash] params parameters to add email notification
|
218
|
+
#
|
213
219
|
# @option params [String] :name Name of the job
|
214
220
|
# @option params [String] :notification_email Email address to send
|
215
221
|
# @option params [TrueClass|FalseClass] :notification_email_for_every_unstable
|
@@ -218,6 +224,8 @@ module JenkinsApi
|
|
218
224
|
def add_email_notification(params)
|
219
225
|
raise "No job name specified" unless params[:name]
|
220
226
|
raise "No email address specified" unless params[:notification_email]
|
227
|
+
@logger.info "Adding '#{params[:notification_email]}' to be" +
|
228
|
+
" notified for '#{params[:name]}'"
|
221
229
|
xml = get_config(params[:name])
|
222
230
|
n_xml = Nokogiri::XML(xml)
|
223
231
|
if n_xml.xpath("//hudson.tasks.Mailer").empty?
|
@@ -255,6 +263,7 @@ module JenkinsApi
|
|
255
263
|
def add_skype_notification(params)
|
256
264
|
raise "No job name specified" unless params[:name]
|
257
265
|
raise "No Skype target specified" unless params[:skype_targets]
|
266
|
+
@logger.info "Adding Skype notification for '#{params[:name]}'"
|
258
267
|
xml = get_config(params[:name])
|
259
268
|
n_xml = Nokogiri::XML(xml)
|
260
269
|
if n_xml.xpath("//hudson.plugins.skype.im.transport.SkypePublisher").empty?
|
@@ -275,6 +284,7 @@ module JenkinsApi
|
|
275
284
|
# @param [String] new_job Name of the new job.
|
276
285
|
#
|
277
286
|
def rename(old_job, new_job)
|
287
|
+
@logger.info "Renaming job '#{old_job}' to '#{new_job}'"
|
278
288
|
@client.api_post_request("/job/#{old_job}/doRename?newName=#{new_job}")
|
279
289
|
end
|
280
290
|
|
@@ -283,6 +293,7 @@ module JenkinsApi
|
|
283
293
|
# @param [String] job_name
|
284
294
|
#
|
285
295
|
def delete(job_name)
|
296
|
+
@logger.info "Deleting job '#{job_name}'"
|
286
297
|
@client.api_post_request("/job/#{job_name}/doDelete")
|
287
298
|
end
|
288
299
|
|
@@ -292,9 +303,19 @@ module JenkinsApi
|
|
292
303
|
# caution.
|
293
304
|
#
|
294
305
|
def delete_all!
|
306
|
+
@logger.info "Deleting all jobs from jenkins"
|
295
307
|
list_all.each { |job| delete(job) }
|
296
308
|
end
|
297
309
|
|
310
|
+
# Wipe out the workspace for a job given the name
|
311
|
+
#
|
312
|
+
# @param [String] job_name
|
313
|
+
#
|
314
|
+
def wipe_out_workspace(job_name)
|
315
|
+
@logger.info "Wiping out the workspace of job '#{job_name}'"
|
316
|
+
@client.api_post_request("/job/#{job_name}/doWipeOutWorkspace")
|
317
|
+
end
|
318
|
+
|
298
319
|
# Stops a running build of a job
|
299
320
|
# This method will stop the current/most recent build if no build number
|
300
321
|
# is specified. The build will be stopped only if it was
|
@@ -306,6 +327,7 @@ module JenkinsApi
|
|
306
327
|
def stop_build(job_name, build_number = 0)
|
307
328
|
build_number = get_current_build_number(job_name) if build_number == 0
|
308
329
|
raise "No builds for #{job_name}" unless build_number
|
330
|
+
@logger.info "Stopping job '#{job_name}' Build ##{build_number}"
|
309
331
|
# Check and see if the build is running
|
310
332
|
is_building = @client.api_get_request(
|
311
333
|
"/job/#{job_name}/#{build_number}"
|
@@ -321,11 +343,25 @@ module JenkinsApi
|
|
321
343
|
# @param [String] job_name
|
322
344
|
#
|
323
345
|
def recreate(job_name)
|
346
|
+
@logger.info "Recreating job '#{job_name}'"
|
324
347
|
job_xml = get_config(job_name)
|
325
348
|
delete(job_name)
|
326
349
|
create(job_name, job_xml)
|
327
350
|
end
|
328
351
|
|
352
|
+
# Copy a job
|
353
|
+
#
|
354
|
+
# @param [String] from_job_name
|
355
|
+
# @param [String] to_job_name
|
356
|
+
#
|
357
|
+
def copy(from_job_name, to_job_name=nil)
|
358
|
+
to_job_name = "copy_of_#{from_job_name}" if to_job_name.nil?
|
359
|
+
@logger.info "Copying job '#{from_job_name}' to '#{to_job_name}'"
|
360
|
+
@client.api_post_request(
|
361
|
+
"/createItem?name=#{to_job_name}&mode=copy&from=#{from_job_name}"
|
362
|
+
)
|
363
|
+
end
|
364
|
+
|
329
365
|
# Get progressive console output from Jenkins server for a job
|
330
366
|
#
|
331
367
|
# @param [String] job_name Name of the Jenkins job
|
@@ -392,9 +428,10 @@ module JenkinsApi
|
|
392
428
|
#
|
393
429
|
def list_by_status(status, jobs = [])
|
394
430
|
jobs = list_all if jobs.empty?
|
395
|
-
|
431
|
+
@logger.info "Obtaining jobs matching status '#{status}'"
|
432
|
+
json_response = @client.api_get_request("", "tree=jobs[name,color]")
|
396
433
|
filtered_jobs = []
|
397
|
-
|
434
|
+
json_response["jobs"].each do |job|
|
398
435
|
if color_to_status(job["color"]) == status &&
|
399
436
|
jobs.include?(job["name"])
|
400
437
|
filtered_jobs << job["name"]
|
@@ -409,6 +446,7 @@ module JenkinsApi
|
|
409
446
|
# @param [Boolean] ignorecase
|
410
447
|
#
|
411
448
|
def list(filter, ignorecase = true)
|
449
|
+
@logger.info "Obtaining jobs matching filter '#{filter}'"
|
412
450
|
response_json = @client.api_get_request("")
|
413
451
|
jobs = []
|
414
452
|
response_json["jobs"].each do |job|
|
@@ -424,8 +462,9 @@ module JenkinsApi
|
|
424
462
|
# List all jobs on the Jenkins CI server along with their details
|
425
463
|
#
|
426
464
|
def list_all_with_details
|
427
|
-
|
428
|
-
|
465
|
+
@logger.info "Obtaining the details of all jobs"
|
466
|
+
response_json = @client.api_get_request("")
|
467
|
+
response_json["jobs"]
|
429
468
|
end
|
430
469
|
|
431
470
|
# List details of a specific job
|
@@ -433,6 +472,7 @@ module JenkinsApi
|
|
433
472
|
# @param [String] job_name
|
434
473
|
#
|
435
474
|
def list_details(job_name)
|
475
|
+
@logger.info "Obtaining the details of '#{job_name}'"
|
436
476
|
@client.api_get_request("/job/#{job_name}")
|
437
477
|
end
|
438
478
|
|
@@ -441,6 +481,7 @@ module JenkinsApi
|
|
441
481
|
# @param [String] job_name
|
442
482
|
#
|
443
483
|
def get_upstream_projects(job_name)
|
484
|
+
@logger.info "Obtaining the upstream projects of '#{job_name}'"
|
444
485
|
response_json = @client.api_get_request("/job/#{job_name}")
|
445
486
|
response_json["upstreamProjects"]
|
446
487
|
end
|
@@ -450,6 +491,7 @@ module JenkinsApi
|
|
450
491
|
# @param [String] job_name
|
451
492
|
#
|
452
493
|
def get_downstream_projects(job_name)
|
494
|
+
@logger.info "Obtaining the down stream projects of '#{job_name}'"
|
453
495
|
response_json = @client.api_get_request("/job/#{job_name}")
|
454
496
|
response_json["downstreamProjects"]
|
455
497
|
end
|
@@ -459,6 +501,7 @@ module JenkinsApi
|
|
459
501
|
# @param [String] job_name
|
460
502
|
#
|
461
503
|
def get_builds(job_name)
|
504
|
+
@logger.info "Obtaining the build details of '#{job_name}'"
|
462
505
|
response_json = @client.api_get_request("/job/#{job_name}")
|
463
506
|
response_json["builds"]
|
464
507
|
end
|
@@ -500,6 +543,7 @@ module JenkinsApi
|
|
500
543
|
# @return [String] status current status of the given job
|
501
544
|
#
|
502
545
|
def get_current_build_status(job_name)
|
546
|
+
@logger.info "Obtaining the current build status of '#{job_name}'"
|
503
547
|
response_json = @client.api_get_request("/job/#{job_name}")
|
504
548
|
color_to_status(response_json["color"])
|
505
549
|
end
|
@@ -512,23 +556,78 @@ module JenkinsApi
|
|
512
556
|
# @return [Number] build_unumber current build number of the given job
|
513
557
|
#
|
514
558
|
def get_current_build_number(job_name)
|
559
|
+
@logger.info "Obtaining the current build number of '#{job_name}'"
|
515
560
|
@client.api_get_request("/job/#{job_name}")['nextBuildNumber'].to_i - 1
|
516
561
|
end
|
517
562
|
|
518
563
|
# Build a job given the name of the job
|
519
|
-
# You can optionally pass in a list of params for Jenkins to use for
|
564
|
+
# You can optionally pass in a list of params for Jenkins to use for
|
565
|
+
# parameterized builds
|
566
|
+
#
|
567
|
+
# @param [String] job_name the name of the job
|
568
|
+
# @param [Hash] params the parameters for parameterized builds
|
569
|
+
# @param [Boolean] return_build_number whether to wait and obtain the build
|
570
|
+
# number
|
571
|
+
#
|
572
|
+
# @return [String, Integer] the response code from the build POST request
|
573
|
+
# if return_build_number is not requested and the build number if the
|
574
|
+
# return_build_number is requested. nil will be returned if the build
|
575
|
+
# number is requested and not available. This can happen if there is
|
576
|
+
# already a job in the queue and concurrent build is disabled.
|
577
|
+
#
|
578
|
+
def build(job_name, params={}, return_build_number = false)
|
579
|
+
msg = "Building job '#{job_name}'"
|
580
|
+
msg << " with parameters: #{params.inspect}" unless params.empty?
|
581
|
+
@logger.info msg
|
582
|
+
build_endpoint = params.empty? ? "build" : "buildWithParameters"
|
583
|
+
raw_response = return_build_number
|
584
|
+
response =@client.api_post_request(
|
585
|
+
"/job/#{job_name}/#{build_endpoint}",
|
586
|
+
params,
|
587
|
+
raw_response
|
588
|
+
)
|
589
|
+
# If return_build_number is enabled, obtain the queue ID from the location
|
590
|
+
# header and wait till the build is moved to one of the executors and a
|
591
|
+
# build number is assigned
|
592
|
+
if return_build_number
|
593
|
+
if response["location"]
|
594
|
+
task_id_match = response["location"].match(/\/item\/(\d*)\//)
|
595
|
+
task_id = task_id_match.nil? ? nil : task_id_match[1]
|
596
|
+
unless task_id.nil?
|
597
|
+
@logger.debug "Queue task ID for job '#{job_name}': #{task_id}"
|
598
|
+
Timeout::timeout(@client.timeout) do
|
599
|
+
while @client.queue.get_item_by_id(task_id)["executable"].nil?
|
600
|
+
sleep 5
|
601
|
+
end
|
602
|
+
end
|
603
|
+
@client.queue.get_item_by_id(task_id)["executable"]["number"]
|
604
|
+
else
|
605
|
+
nil
|
606
|
+
end
|
607
|
+
else
|
608
|
+
nil
|
609
|
+
end
|
610
|
+
else
|
611
|
+
response
|
612
|
+
end
|
613
|
+
end
|
614
|
+
|
615
|
+
# Enable a job given the name of the job
|
520
616
|
#
|
521
617
|
# @param [String] job_name
|
522
|
-
# @param [Hash] params
|
523
618
|
#
|
524
|
-
|
619
|
+
def enable(job_name)
|
620
|
+
@logger.info "Enabling job '#{job_name}'"
|
621
|
+
@client.api_post_request("/job/#{job_name}/enable")
|
622
|
+
end
|
623
|
+
|
624
|
+
# Disable a job given the name of the job
|
525
625
|
#
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
end
|
626
|
+
# @param [String] job_name
|
627
|
+
#
|
628
|
+
def disable(job_name)
|
629
|
+
@logger.info "Disabling job '#{job_name}'"
|
630
|
+
@client.api_post_request("/job/#{job_name}/disable")
|
532
631
|
end
|
533
632
|
|
534
633
|
# Obtain the configuration stored in config.xml of a specific job
|
@@ -538,6 +637,7 @@ module JenkinsApi
|
|
538
637
|
# @return [String] XML Config.xml of the job
|
539
638
|
#
|
540
639
|
def get_config(job_name)
|
640
|
+
@logger.info "Obtaining the config.xml of '#{job_name}'"
|
541
641
|
@client.get_config("/job/#{job_name}")
|
542
642
|
end
|
543
643
|
|
@@ -549,6 +649,7 @@ module JenkinsApi
|
|
549
649
|
# @return [String] response_code return code from HTTP POST
|
550
650
|
#
|
551
651
|
def post_config(job_name, xml)
|
652
|
+
@logger.info "Posting the config.xml of '#{job_name}'"
|
552
653
|
@client.post_config("/job/#{job_name}/config.xml", xml)
|
553
654
|
end
|
554
655
|
|
@@ -559,9 +660,10 @@ module JenkinsApi
|
|
559
660
|
#
|
560
661
|
def get_test_results(job_name, build_num)
|
561
662
|
build_num = get_current_build_number(job_name) if build_num == 0
|
562
|
-
|
663
|
+
@logger.info "Obtaining the test results of '#{job_name}'" +
|
664
|
+
" Build ##{build_num}"
|
563
665
|
@client.api_get_request("/job/#{job_name}/#{build_num}/testReport")
|
564
|
-
rescue Exceptions::
|
666
|
+
rescue Exceptions::NotFound
|
565
667
|
# Not found is acceptable, as not all builds will have test results
|
566
668
|
# and this is what jenkins throws at us in that case
|
567
669
|
nil
|
@@ -574,6 +676,8 @@ module JenkinsApi
|
|
574
676
|
#
|
575
677
|
def get_build_details(job_name, build_num)
|
576
678
|
build_num = get_current_build_number(job_name) if build_num == 0
|
679
|
+
@logger.info "Obtaining the build details of '#{job_name}'" +
|
680
|
+
" Build ##{build_num}"
|
577
681
|
|
578
682
|
@client.api_get_request("/job/#{job_name}/#{build_num}/")
|
579
683
|
end
|
@@ -586,6 +690,7 @@ module JenkinsApi
|
|
586
690
|
# @return [String] response_code return code from HTTP POST
|
587
691
|
#
|
588
692
|
def change_description(job_name, description)
|
693
|
+
@logger.info "Changing the description of '#{job_name}' to '#{description}'"
|
589
694
|
xml = get_config(job_name)
|
590
695
|
n_xml = Nokogiri::XML(xml)
|
591
696
|
desc = n_xml.xpath("//description").first
|
@@ -601,6 +706,8 @@ module JenkinsApi
|
|
601
706
|
# @return [String] response_code return code from HTTP POST
|
602
707
|
#
|
603
708
|
def block_build_when_downstream_building(job_name)
|
709
|
+
@logger.info "Blocking builds of '#{job_name}' when downstream" +
|
710
|
+
" projects are building"
|
604
711
|
xml = get_config(job_name)
|
605
712
|
n_xml = Nokogiri::XML(xml)
|
606
713
|
node = n_xml.xpath("//blockBuildWhenDownstreamBuilding").first
|
@@ -618,6 +725,8 @@ module JenkinsApi
|
|
618
725
|
# @return [String] response_code return code from HTTP POST
|
619
726
|
#
|
620
727
|
def unblock_build_when_downstream_building(job_name)
|
728
|
+
@logger.info "Unblocking builds of '#{job_name}' when downstream" +
|
729
|
+
" projects are building"
|
621
730
|
xml = get_config(job_name)
|
622
731
|
n_xml = Nokogiri::XML(xml)
|
623
732
|
node = n_xml.xpath("//blockBuildWhenDownstreamBuilding").first
|
@@ -635,6 +744,8 @@ module JenkinsApi
|
|
635
744
|
# @return [String] response_code return code from HTTP POST
|
636
745
|
#
|
637
746
|
def block_build_when_upstream_building(job_name)
|
747
|
+
@logger.info "Blocking builds of '#{job_name}' when upstream" +
|
748
|
+
" projects are building"
|
638
749
|
xml = get_config(job_name)
|
639
750
|
n_xml = Nokogiri::XML(xml)
|
640
751
|
node = n_xml.xpath("//blockBuildWhenUpstreamBuilding").first
|
@@ -652,6 +763,8 @@ module JenkinsApi
|
|
652
763
|
# @return [String] response_code return code from HTTP POST
|
653
764
|
#
|
654
765
|
def unblock_build_when_upstream_building(job_name)
|
766
|
+
@logger.info "Unblocking builds of '#{job_name}' when upstream" +
|
767
|
+
" projects are building"
|
655
768
|
xml = get_config(job_name)
|
656
769
|
n_xml = Nokogiri::XML(xml)
|
657
770
|
node = n_xml.xpath("//blockBuildWhenUpstreamBuilding").first
|
@@ -670,6 +783,8 @@ module JenkinsApi
|
|
670
783
|
# @return [String] response_code return code from HTTP POST
|
671
784
|
#
|
672
785
|
def execute_concurrent_builds(job_name, option)
|
786
|
+
@logger.info "Setting the concurrent build execution option of" +
|
787
|
+
" '#{job_name}' to #{option}"
|
673
788
|
xml = get_config(job_name)
|
674
789
|
n_xml = Nokogiri::XML(xml)
|
675
790
|
node = n_xml.xpath("//concurrentBuild").first
|
@@ -688,6 +803,7 @@ module JenkinsApi
|
|
688
803
|
# @return [Array] params_array Array of parameters for the given job
|
689
804
|
#
|
690
805
|
def get_build_params(job_name)
|
806
|
+
@logger.info "Obtaining the build params of '#{job_name}'"
|
691
807
|
xml = get_config(job_name)
|
692
808
|
n_xml = Nokogiri::XML(xml)
|
693
809
|
params = n_xml.xpath("//parameterDefinitions").first
|
@@ -791,13 +907,16 @@ module JenkinsApi
|
|
791
907
|
# @param [String] job_name
|
792
908
|
# @param [String] downstream_projects
|
793
909
|
# @param [String] threshold - failure, success, or unstable
|
794
|
-
# @param [
|
910
|
+
# @param [Boolean] overwrite - true or false
|
795
911
|
#
|
796
912
|
# @return [String] response_code return code from HTTP POST
|
797
913
|
#
|
798
914
|
def add_downstream_projects(job_name,
|
799
915
|
downstream_projects,
|
800
916
|
threshold, overwrite = false)
|
917
|
+
@logger.info "Adding #{downstream_projects.inspect} as downstream" +
|
918
|
+
" projects for '#{job_name}' with the threshold of '#{threshold}'" +
|
919
|
+
" and overwrite option of '#{overwrite}'"
|
801
920
|
name, ord, col = get_threshold_params(threshold)
|
802
921
|
xml = get_config(job_name)
|
803
922
|
n_xml = Nokogiri::XML(xml)
|
@@ -836,6 +955,7 @@ module JenkinsApi
|
|
836
955
|
# @return [String] response_code return code from HTTP POST
|
837
956
|
#
|
838
957
|
def remove_downstream_projects(job_name)
|
958
|
+
@logger.info "Removing the downstream projects of '#{job_name}'"
|
839
959
|
xml = get_config(job_name)
|
840
960
|
n_xml = Nokogiri::XML(xml)
|
841
961
|
n_xml.search("//hudson.tasks.BuildTrigger").each do |node|
|
@@ -870,6 +990,7 @@ module JenkinsApi
|
|
870
990
|
# @return [String] response_code return code from HTTP POST
|
871
991
|
#
|
872
992
|
def restrict_to_node(job_name, node_name)
|
993
|
+
@logger.info "Restricting '#{job_name}' to '#{node_name}' node"
|
873
994
|
xml = get_config(job_name)
|
874
995
|
n_xml = Nokogiri::XML(xml)
|
875
996
|
if (node = n_xml.xpath("//assignedNode").first)
|
@@ -889,11 +1010,8 @@ module JenkinsApi
|
|
889
1010
|
# @param [Array] job_names Array of job names to be unchained
|
890
1011
|
#
|
891
1012
|
def unchain(job_names)
|
892
|
-
|
893
|
-
|
894
|
-
puts log_msg if @client.debug
|
895
|
-
remove_downstream_projects(job)
|
896
|
-
end
|
1013
|
+
@logger.info "Unchaining jobs: #{job_names.inspect}"
|
1014
|
+
job_names.each { |job| remove_downstream_projects(job) }
|
897
1015
|
end
|
898
1016
|
|
899
1017
|
# Chain the jobs given based on specified criteria
|
@@ -911,12 +1029,13 @@ module JenkinsApi
|
|
911
1029
|
raise "Parallel jobs should be at least 1" if parallel < 1
|
912
1030
|
unchain(job_names)
|
913
1031
|
|
1032
|
+
@logger.info "Chaining jobs: #{job_names.inspect}" +
|
1033
|
+
" with threshold of '#{threshold}' and criteria as '#{criteria}'" +
|
1034
|
+
" with #{parallel} number of parallel jobs"
|
914
1035
|
filtered_job_names = []
|
915
1036
|
if criteria.include?("all") || criteria.empty?
|
916
1037
|
filtered_job_names = job_names
|
917
1038
|
else
|
918
|
-
log_msg = "[INFO] Criteria is specified. Filtering jobs..."
|
919
|
-
puts log_msg if @client.debug
|
920
1039
|
job_names.each do |job|
|
921
1040
|
filtered_job_names << job if criteria.include?(
|
922
1041
|
@client.job.get_current_build_status(job)
|
@@ -926,10 +1045,6 @@ module JenkinsApi
|
|
926
1045
|
|
927
1046
|
filtered_job_names.each_with_index do |job_name, index|
|
928
1047
|
break if index >= (filtered_job_names.length - parallel)
|
929
|
-
msg = "[INFO] Adding <#{filtered_job_names[index+1]}> as a"
|
930
|
-
msg << " downstream project to <#{job_name}> with <#{threshold}> as"
|
931
|
-
msg << " the threshold"
|
932
|
-
puts msg if @client.debug
|
933
1048
|
@client.job.add_downstream_projects(
|
934
1049
|
job_name, filtered_job_names[index + parallel], threshold, true
|
935
1050
|
)
|