jenkins_api_client 0.6.2 → 0.7.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.
Files changed (40) hide show
  1. data/.gitignore +3 -0
  2. data/.jenkins.yml +9 -0
  3. data/.travis.yml +11 -15
  4. data/CHANGELOG.md +15 -0
  5. data/Gemfile +2 -2
  6. data/README.md +7 -9
  7. data/Rakefile +27 -14
  8. data/lib/jenkins_api_client.rb +36 -6
  9. data/lib/jenkins_api_client/build_queue.rb +213 -0
  10. data/lib/jenkins_api_client/cli/base.rb +10 -6
  11. data/lib/jenkins_api_client/cli/helper.rb +13 -4
  12. data/lib/jenkins_api_client/cli/job.rb +6 -9
  13. data/lib/jenkins_api_client/cli/node.rb +6 -4
  14. data/lib/jenkins_api_client/cli/system.rb +2 -1
  15. data/lib/jenkins_api_client/client.rb +31 -25
  16. data/lib/jenkins_api_client/job.rb +248 -95
  17. data/lib/jenkins_api_client/node.rb +128 -10
  18. data/lib/jenkins_api_client/system.rb +4 -2
  19. data/lib/jenkins_api_client/version.rb +2 -2
  20. data/lib/jenkins_api_client/view.rb +17 -4
  21. data/scripts/login_with_irb.rb +4 -3
  22. data/spec/func_tests/client_spec.rb +90 -0
  23. data/spec/func_tests/job_spec.rb +348 -0
  24. data/spec/func_tests/node_spec.rb +174 -0
  25. data/spec/{spec_helper.rb → func_tests/spec_helper.rb} +2 -2
  26. data/spec/func_tests/system_spec.rb +55 -0
  27. data/spec/func_tests/view_spec.rb +53 -0
  28. data/spec/unit_tests/client_spec.rb +211 -0
  29. data/spec/unit_tests/fixtures/files/computer_sample.xml +17 -0
  30. data/spec/unit_tests/fixtures/files/job_sample.xml +16 -0
  31. data/spec/unit_tests/job_spec.rb +355 -0
  32. data/spec/unit_tests/node_spec.rb +192 -0
  33. data/spec/unit_tests/spec_helper.rb +8 -0
  34. data/spec/unit_tests/system_spec.rb +54 -0
  35. data/spec/unit_tests/view_spec.rb +127 -0
  36. metadata +34 -23
  37. data/spec/client_spec.rb +0 -52
  38. data/spec/job_spec.rb +0 -158
  39. data/spec/node_spec.rb +0 -48
  40. data/spec/system_spec.rb +0 -46
@@ -32,12 +32,16 @@ module JenkinsApi
32
32
 
33
33
  class Base < Thor
34
34
 
35
- class_option :username, :aliases => "-u", :desc => "Name of Jenkins user"
36
- class_option :password, :aliases => "-p", :desc => "Password of Jenkins user"
37
- class_option :password_base64, :aliases => "-b", :desc => "Base 64 encoded password of Jenkins user"
38
- class_option :server_ip, :aliases => "-s", :desc => "Jenkins server IP address"
39
- class_option :server_port, :aliases => "-o", :desc => "Jenkins server port"
40
- class_option :creds_file, :aliases => "-c", :desc => "Credentials file for communicating with Jenkins server"
35
+ class_option :username, :aliases => "-u", :desc => "Name of Jenkins user"
36
+ class_option :password, :aliases => "-p",
37
+ :desc => "Password of Jenkins user"
38
+ class_option :password_base64, :aliases => "-b",
39
+ :desc => "Base 64 encoded password of Jenkins user"
40
+ class_option :server_ip, :aliases => "-s",
41
+ :desc => "Jenkins server IP address"
42
+ class_option :server_port, :aliases => "-o", :desc => "Jenkins port"
43
+ class_option :creds_file, :aliases => "-c",
44
+ :desc => "Credentials file for communicating with Jenkins server"
41
45
 
42
46
 
43
47
  map "-v" => :version
@@ -26,14 +26,23 @@ module JenkinsApi
26
26
  module CLI
27
27
  class Helper
28
28
  def self.setup(options)
29
- if options[:username] && options[:server_ip] && (options[:password] || options[:password_base64])
29
+ if options[:username] && options[:server_ip] && \
30
+ (options[:password] || options[:password_base64])
30
31
  creds = options
31
32
  elsif options[:creds_file]
32
- creds = YAML.load_file(File.expand_path(options[:creds_file], __FILE__))
33
+ creds = YAML.load_file(
34
+ File.expand_path(options[:creds_file], __FILE__)
35
+ )
33
36
  elsif File.exist?("#{ENV['HOME']}/.jenkins_api_client/login.yml")
34
- creds = YAML.load_file(File.expand_path("#{ENV['HOME']}/.jenkins_api_client/login.yml", __FILE__))
37
+ creds = YAML.load_file(
38
+ File.expand_path(
39
+ "#{ENV['HOME']}/.jenkins_api_client/login.yml", __FILE__
40
+ )
41
+ )
35
42
  else
36
- puts "Credentials are not set. Please pass them as parameters or set them in the default credentials file"
43
+ msg = "Credentials are not set. Please pass them as parameters or"
44
+ msg << " set them in the default credentials file"
45
+ puts msg
37
46
  exit 1
38
47
  end
39
48
  JenkinsApi::Client.new(creds)
@@ -31,7 +31,8 @@ module JenkinsApi
31
31
 
32
32
  desc "list", "List jobs"
33
33
  method_option :status, :aliases => "-t", :desc => "Status to filter"
34
- method_option :filter, :aliases => "-f", :desc => "Regular expression to filter jobs"
34
+ method_option :filter, :aliases => "-f",
35
+ :desc => "Regular expression to filter jobs"
35
36
  def list
36
37
  @client = Helper.setup(parent_options)
37
38
  if options[:filter] && options[:status]
@@ -64,12 +65,6 @@ module JenkinsApi
64
65
  puts @client.job.get_current_build_status(job)
65
66
  end
66
67
 
67
- desc "listrunning", "List running jobs"
68
- def listrunning
69
- @client = Helper.setup(parent_options)
70
- puts @client.job.list_running
71
- end
72
-
73
68
  desc "delete JOB", "Delete the job"
74
69
  def delete(job)
75
70
  @client = Helper.setup(parent_options)
@@ -77,10 +72,12 @@ module JenkinsApi
77
72
  end
78
73
 
79
74
  desc "console JOB", "Print the progressive console output of a job"
80
- method_option :sleep, :aliases => "-z", :desc => "Time to wait between querying the API for console output"
75
+ method_option :sleep, :aliases => "-z",
76
+ :desc => "Time to wait between querying the API for console output"
81
77
  def console(job)
82
78
  @client = Helper.setup(parent_options)
83
- # If debug is enabled, disable it. It shouldn't interfere with console output.
79
+ # If debug is enabled, disable it. It shouldn't interfere
80
+ # with console output.
84
81
  debug_changed = false
85
82
  if @client.debug == true
86
83
  @client.debug = false
@@ -28,9 +28,11 @@ module JenkinsApi
28
28
  module CLI
29
29
  class Node < Thor
30
30
  include Thor::Actions
31
+ include Terminal
31
32
 
32
33
  desc "list", "List all nodes"
33
- method_option :filter, :aliases => "-f", :desc => "Regular expression to filter jobs"
34
+ method_option :filter, :aliases => "-f",
35
+ :desc => "Regular expression to filter jobs"
34
36
  def list
35
37
  @client = Helper.setup(parent_options)
36
38
  if options[:filter]
@@ -48,7 +50,7 @@ module JenkinsApi
48
50
  general_attributes.each do |attr|
49
51
  rows << [attr, @client.node.method("get_#{attr}").call]
50
52
  end
51
- table = Terminal::Table.new :headings => ['Attribute', 'Value'], :rows => rows
53
+ table = Table.new :headings => ['Attribute', 'Value'], :rows => rows
52
54
  puts table
53
55
  end
54
56
 
@@ -60,7 +62,7 @@ module JenkinsApi
60
62
  node_attributes.each do |attr|
61
63
  rows << [attr, @client.node.method("get_node_#{attr}").call(node)]
62
64
  end
63
- table = Terminal::Table.new :headings => ['Attribute', 'Value'], :rows => rows
65
+ table = Table.new :headings => ['Attribute', 'Value'], :rows => rows
64
66
  puts "Node: #{node}"
65
67
  puts table
66
68
  end
@@ -73,7 +75,7 @@ module JenkinsApi
73
75
  node_properties.each do |property|
74
76
  rows << [property, @client.node.method("is_#{property}?").call(node)]
75
77
  end
76
- table = Terminal::Table.new :headings => ['Property', 'Value'], :rows => rows
78
+ table = Table.new :headings => ['Property', 'Value'], :rows => rows
77
79
  puts "Node: #{node}"
78
80
  puts table
79
81
  end
@@ -41,7 +41,8 @@ module JenkinsApi
41
41
  end
42
42
 
43
43
  desc "restart", "Restarts the Jenkins server"
44
- method_option :force, :type => :boolean, :aliases => "-s", :desc => "Force restart"
44
+ method_option :force, :type => :boolean, :aliases => "-s",
45
+ :desc => "Force restart"
45
46
  def restart
46
47
  @client = Helper.setup(parent_options)
47
48
  force = options[:force] ? true : false
@@ -28,38 +28,34 @@ require 'active_support/core_ext'
28
28
  require 'active_support/builder'
29
29
  require 'base64'
30
30
 
31
- require File.expand_path('../version', __FILE__)
32
- require File.expand_path('../exceptions', __FILE__)
33
- require File.expand_path('../job', __FILE__)
34
- require File.expand_path('../system', __FILE__)
35
- require File.expand_path('../node', __FILE__)
36
-
37
31
  module JenkinsApi
38
32
  class Client
39
33
  attr_accessor :debug
40
- @debug = false
41
34
  DEFAULT_SERVER_PORT = 8080
42
35
  VALID_PARAMS = %w(server_ip server_port username password debug)
43
36
 
44
- # Initialize a Client object with Jenkins CI server information and credentials
37
+ # Initialize a Client object with Jenkins CI server credentials
45
38
  #
46
39
  # @param [Hash] args
47
40
  # * the +:server_ip+ param is the IP address of the Jenkins CI server
48
- # * the +:server_port+ param is the port on which the Jenkins server listens
49
- # * the +:username+ param is the username used for connecting to the CI server
41
+ # * the +:server_port+ param is the port on which the Jenkins listens
42
+ # * the +:username+ param is the username used for connecting to the server
50
43
  # * the +:password+ param is the password for connecting to the CI server
51
44
  #
52
45
  def initialize(args)
53
- args.each { |key, value|
46
+ args.each do |key, value|
54
47
  instance_variable_set("@#{key}", value) if value
55
- } if args.is_a? Hash
56
- raise "Server IP is required to connect to Jenkins Server" unless @server_ip
57
- raise "Credentials are required to connect to te Jenkins Server" unless @username && (@password || @password_base64)
48
+ end if args.is_a? Hash
49
+ raise "Server IP is required to connect to Jenkins" unless @server_ip
50
+ unless @username && (@password || @password_base64)
51
+ raise "Credentials are required to connect to te Jenkins Server"
52
+ end
58
53
  @server_port = DEFAULT_SERVER_PORT unless @server_port
54
+ @debug = false unless @debug
59
55
 
60
- # Base64 decode inserts a newline character at the end. As a workaround added chomp
61
- # to remove newline characters. I hope nobody uses newline characters at the end of
62
- # their passwords :)
56
+ # Base64 decode inserts a newline character at the end. As a workaround
57
+ # added chomp to remove newline characters. I hope nobody uses newline
58
+ # characters at the end of their passwords :)
63
59
  @password = Base64.decode64(@password_base64).chomp if @password_base64
64
60
  end
65
61
 
@@ -93,6 +89,12 @@ module JenkinsApi
93
89
  JenkinsApi::Client::View.new(self)
94
90
  end
95
91
 
92
+ # Creates an instance to the BuildQueue by passing a reference to self
93
+ #
94
+ def queue
95
+ JenkinsApi::Client::BuildQueue.new(self)
96
+ end
97
+
96
98
  # Returns a string representing the class name
97
99
  #
98
100
  def to_s
@@ -119,6 +121,7 @@ module JenkinsApi
119
121
  request = Net::HTTP::Get.new("#{url_prefix}#{url_suffix}?#{tree}") if tree
120
122
  request.basic_auth @username, @password
121
123
  response = http.request(request)
124
+ msg = "HTTP Code: #{response.code}, Response Body: #{response.body}"
122
125
  case response.code.to_i
123
126
  when 200
124
127
  if url_suffix =~ /json/
@@ -127,36 +130,39 @@ module JenkinsApi
127
130
  return response
128
131
  end
129
132
  when 401
130
- raise Exceptions::UnautherizedException.new("HTTP Code: #{response.code.to_s}, Response Body: #{response.body}")
133
+ raise Exceptions::UnautherizedException.new(msg)
131
134
  when 404
132
- raise Exceptions::NotFoundException.new("HTTP Code: #{response.code.to_s}, Response Body: #{response.body}")
135
+ raise Exceptions::NotFoundException.new(msg)
133
136
  when 500
134
- raise Exceptions::InternelServerErrorException.new("HTTP Code: #{response.code.to_s}, Response Body: #{response.body}")
137
+ raise Exceptions::InternelServerErrorException.new(msg)
135
138
  else
136
- raise Exceptions::ApiException.new("HTTP Code: #{response.code.to_s}, Response body: #{response.body}")
139
+ raise Exceptions::ApiException.new(msg)
137
140
  end
138
141
  end
139
142
 
140
143
  # Sends a POST message to the Jenkins CI server with the specified URL
141
144
  #
142
145
  # @param [String] url_prefix
146
+ # @param [Hash] form_data form data to send with POST request
143
147
  #
144
- def api_post_request(url_prefix)
148
+ def api_post_request(url_prefix, form_data = nil)
145
149
  http = Net::HTTP.start(@server_ip, @server_port)
146
150
  request = Net::HTTP::Post.new("#{url_prefix}")
147
151
  puts "[INFO] PUT #{url_prefix}" if @debug
148
152
  request.basic_auth @username, @password
149
153
  request.content_type = 'application/json'
154
+ request.set_form_data(form_data) unless form_data.nil?
150
155
  response = http.request(request)
156
+ msg = "HTTP Code: #{response.code}, Response Body: #{response.body}"
151
157
  case response.code.to_i
152
158
  when 200, 302
153
159
  return response.code
154
160
  when 404
155
- raise Exceptions::NotFoundException.new("HTTP Code: #{response.code.to_s}, Response Body: #{response.body}")
161
+ raise Exceptions::NotFoundException.new(msg)
156
162
  when 500
157
- raise Exceptions::InternelServerErrorException.new("HTTP Code: #{response.code.to_s}, Response Body: #{response.body}")
163
+ raise Exceptions::InternelServerErrorException.new(msg)
158
164
  else
159
- raise Exceptions::ApiException.new("HTTP Code: #{response.code.to_s}, Response body: #{response.body}")
165
+ raise Exceptions::ApiException.new(msg)
160
166
  end
161
167
  end
162
168
 
@@ -46,8 +46,8 @@ module JenkinsApi
46
46
  end
47
47
 
48
48
  # Create a job with params given as a hash instead of the xml
49
- # This gives some flexibility for creating simple jobs so the user doesn't have to
50
- # learn about handling xml.
49
+ # This gives some flexibility for creating simple jobs so the user
50
+ # doesn't have to learn about handling xml.
51
51
  #
52
52
  # @param [Hash] params
53
53
  # * +:name+ name of the job
@@ -55,33 +55,61 @@ module JenkinsApi
55
55
  # * +:block_build_when_downstream_building+ true or false
56
56
  # * +:block_build_when_upstream_building+ true or false
57
57
  # * +:concurrent_build+ true or false
58
- # * +:scm_provider+ type of source control system. Supported: git, subversion
58
+ # * +:scm_provider+ type of source control system. Supported: Git, SVN
59
59
  # * +:scm_url+ remote url for scm
60
+ # * +:scm_module+ Module to download. Only for CVS.
60
61
  # * +:scm_branch+ branch to use in scm. Uses master by default
62
+ # * +:scm_tag+ tag to download from scm. Only for CVS.
63
+ # * +:scm_use_head_if_tag_not_found+ Only for CVS.
61
64
  # * +:shell_command+ command to execute in the shell
62
65
  # * +:child_projects+ projects to add as downstream projects
63
- # * +:child_threshold+ threshold for child projects. success, failure, or unstable. Default: failure.
66
+ # * +:child_threshold+ threshold for child projects.
67
+ # success, failure, or unstable. Default: failure.
64
68
  #
65
69
  def create_freestyle(params)
66
- # TODO: Add support for all SCM providers supported by Jenkins
67
- supported_scm_providers = ['git', 'subversion']
70
+ # Supported SCM providers
71
+ supported_scm = ["git", "subversion", "cvs"]
68
72
 
69
- # Set default values for params that are not specified and Error handling.
73
+ # Set default values for params that are not specified.
70
74
  raise 'Job name must be specified' unless params[:name]
71
- params[:keep_dependencies] = false if params[:keep_dependencies].nil?
72
- params[:block_build_when_downstream_building] = false if params[:block_build_when_downstream_building].nil?
73
- params[:block_build_when_upstream_building] = false if params[:block_build_when_upstream_building].nil?
75
+ if params[:keep_dependencies].nil?
76
+ params[:keep_dependencies] = false
77
+ end
78
+ if params[:block_build_when_downstream_building].nil?
79
+ params[:block_build_when_downstream_building] = false
80
+ end
81
+ if params[:block_build_when_upstream_building].nil?
82
+ params[:block_build_when_upstream_building] = false
83
+ end
74
84
  params[:concurrent_build] = false if params[:concurrent_build].nil?
85
+ if params[:notification_email]
86
+ if params[:notification_email_for_every_unstable_build].nil?
87
+ params[:notification_email_for_every_unstable] = false
88
+ end
89
+ if params[:notification_email_send_to_individuals].nil?
90
+ params[:notification_email_send_to_individuals] ||= false
91
+ end
92
+ end
75
93
 
76
- # SCM configurations and Error handling. Presently only Git plugin is supported.
77
- unless supported_scm_providers.include?(params[:scm_provider]) || params[:scm_provider].nil?
94
+ # SCM configurations and Error handling.
95
+ unless supported_scm.include?(params[:scm_provider]) ||
96
+ params[:scm_provider].nil?
78
97
  raise "SCM #{params[:scm_provider]} is currently not supported"
79
98
  end
80
- raise 'SCM URL must be specified' if params[:scm_url].nil? && !params[:scm_provider].nil?
81
- params[:scm_branch] = "master" if params[:scm_branch].nil? && !params[:scm_provider].nil?
99
+ if params[:scm_url].nil? && !params[:scm_provider].nil?
100
+ raise 'SCM URL must be specified'
101
+ end
102
+ if params[:scm_branch].nil? && !params[:scm_provider].nil?
103
+ params[:scm_branch] = "master"
104
+ end
105
+ if params[:scm_use_head_if_tag_not_found].nil?
106
+ params[:scm_use_head_if_tag_not_found] = false
107
+ end
82
108
 
83
109
  # Child projects configuration and Error handling
84
- params[:child_threshold] = 'failure' if params[:child_threshold].nil? && !params[:child_projects].nil?
110
+ if params[:child_threshold].nil? && !params[:child_projects].nil?
111
+ params[:child_threshold] = 'failure'
112
+ end
85
113
 
86
114
  # Build the Job xml file based on the parameters given
87
115
  builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') { |xml|
@@ -92,7 +120,8 @@ module JenkinsApi
92
120
  xml.properties
93
121
  # SCM related stuff
94
122
  if params[:scm_provider] == 'subversion'
95
- xml.scm(:class => "hudson.scm.SubversionSCM", :plugin => "subversion@1.39") {
123
+ xml.scm(:class => "hudson.scm.SubversionSCM",
124
+ :plugin => "subversion@1.39") {
96
125
  xml.locations {
97
126
  xml.send("hudson.scm.SubversionSCM_-ModuleLocation") {
98
127
  xml.remote "#{params[:scm_url]}"
@@ -104,9 +133,31 @@ module JenkinsApi
104
133
  xml.excludedUsers
105
134
  xml.excludedRevprop
106
135
  xml.excludedCommitMessages
107
- xml.workspaceUpdater(:class => "hudson.scm.subversion.UpdateUpdater")
136
+ xml.workspaceUpdater(:class =>
137
+ "hudson.scm.subversion.UpdateUpdater")
138
+ }
139
+ elsif params[:scm_provider] == "cvs"
140
+ xml.scm(:class => "hudson.scm.CVSSCM",
141
+ :plugin => "cvs@1.6") {
142
+ xml.cvsroot "#{params[:scm_url]}"
143
+ xml.module "#{params[:scm_module]}"
144
+ if params[:scm_branch]
145
+ xml.branch "#{params[:scm_branch]}"
146
+ else
147
+ xml.branch "#{params[:scm_tag]}"
148
+ end
149
+ xml.canUseUpdate true
150
+ xml.useHeadIfNotFound(
151
+ "#{params[:scm_use_head_if_tag_not_found]}")
152
+ xml.flatten true
153
+ if params[:scm_tag]
154
+ xml.isTag true
155
+ else
156
+ xml.isTag false
157
+ end
158
+ xml.excludedRegions
108
159
  }
109
- elsif params[:scm_provider] == 'git'
160
+ elsif params[:scm_provider] == "git"
110
161
  xml.scm(:class => "hudson.plugins.git.GitSCM") {
111
162
  xml.configVersion "2"
112
163
  xml.userRemoteConfigs {
@@ -131,7 +182,8 @@ module JenkinsApi
131
182
  xml.remotePoll "false"
132
183
  xml.ignoreNotifyCommit "false"
133
184
  xml.useShallowClone "false"
134
- xml.buildChooser(:class => "hudson.plugins.git.util.DefaultBuildChooser")
185
+ xml.buildChooser(:class =>
186
+ "hudson.plugins.git.util.DefaultBuildChooser")
135
187
  xml.gitTool "Default"
136
188
  xml.submoduleCfg(:class => "list")
137
189
  xml.relativeTargetDir
@@ -147,10 +199,18 @@ module JenkinsApi
147
199
  else
148
200
  xml.scm(:class => "hudson.scm.NullSCM")
149
201
  end
150
- xml.canRoam "true"
202
+ # Restrict job to run in a specified node
203
+ if params[:restricted_node]
204
+ xml.assignedNode "#{params[:restricted_node]}"
205
+ xml.canRoam "false"
206
+ else
207
+ xml.canRoam "true"
208
+ end
151
209
  xml.disabled "false"
152
- xml.blockBuildWhenDownstreamBuilding "#{params[:block_build_when_downstream_building]}"
153
- xml.blockBuildWhenUpstreamBuilding "#{params[:block_build_when_upstream_building]}"
210
+ xml.blockBuildWhenDownstreamBuilding(
211
+ "#{params[:block_build_when_downstream_building]}")
212
+ xml.blockBuildWhenUpstreamBuilding(
213
+ "#{params[:block_build_when_upstream_building]}")
154
214
  xml.triggers.vector
155
215
  xml.concurrentBuild "#{params[:concurrent_build]}"
156
216
  # Shell command stuff
@@ -165,8 +225,9 @@ module JenkinsApi
165
225
  xml.publishers {
166
226
  if params[:child_projects]
167
227
  xml.send("hudson.tasks.BuildTrigger") {
168
- xml.childProjects"#{params[:child_projects]}"
169
- name, ordinal, color = get_threshold_params(params[:child_threshold])
228
+ xml.childProjects "#{params[:child_projects]}"
229
+ threshold = params[:child_threshold]
230
+ name, ordinal, color = get_threshold_params(threshold)
170
231
  xml.threshold {
171
232
  xml.name "#{name}"
172
233
  xml.ordinal "#{ordinal}"
@@ -174,6 +235,15 @@ module JenkinsApi
174
235
  }
175
236
  }
176
237
  end
238
+ if params[:notification_email]
239
+ xml.send("hudson.tasks.Mailer") {
240
+ xml.recipients "#{params[:notification_email]}"
241
+ xml.dontNotifyEveryUnstableBuild(
242
+ "#{params[:notification_email_for_every_unstable]}")
243
+ xml.sendToIndividuals(
244
+ "#{params[:notification_email_send_to_individuals]}")
245
+ }
246
+ end
177
247
  }
178
248
  xml.buildWrappers
179
249
  }
@@ -191,7 +261,8 @@ module JenkinsApi
191
261
 
192
262
  # Stops a running build of a job
193
263
  # This method will stop the current/most recent build if no build number
194
- # is specified. The build will be stopped only if it was in 'running' state.
264
+ # is specified. The build will be stopped only if it was
265
+ # in 'running' state.
195
266
  #
196
267
  # @param [String] job_name
197
268
  # @param [Number] build_number
@@ -200,8 +271,12 @@ module JenkinsApi
200
271
  build_number = get_current_build_number(job_name) if build_number == 0
201
272
  raise "No builds for #{job_name}" unless build_number
202
273
  # Check and see if the build is running
203
- is_building = @client.api_get_request("/job/#{job_name}/#{build_number}")["building"]
204
- @client.api_post_request("/job/#{job_name}/#{build_number}/stop") if is_building
274
+ is_building = @client.api_get_request(
275
+ "/job/#{job_name}/#{build_number}"
276
+ )["building"]
277
+ if is_building
278
+ @client.api_post_request("/job/#{job_name}/#{build_number}/stop")
279
+ end
205
280
  end
206
281
 
207
282
  # Re-create the same job
@@ -218,18 +293,21 @@ module JenkinsApi
218
293
  # Get progressive console output from Jenkins server for a job
219
294
  #
220
295
  # @param [String] job_name Name of the Jenkins job
221
- # @param [Number] build_number Specific build number to obtain the console output from. Default is the recent build
296
+ # @param [Number] build_number Specific build number to obtain the
297
+ # console output from. Default is the recent build
222
298
  # @param [Number] start start offset to get only a portion of the text
223
299
  # @param [String] mode Mode of text output. 'text' or 'html'
224
300
  #
225
301
  # @return [Hash] response
226
302
  # * +output+ Console output of the job
227
- # * +size+ Size of the text. This can be used as 'start' for the next call to get progressive output
228
- # * +more+ More data available for the job. 'true' if available and nil otherwise
229
- #
230
- def get_console_output(job_name, build_number = 0, start = 0, mode = 'text')
231
- build_number = get_current_build_number(job_name) if build_number == 0
232
- if build_number == 0
303
+ # * +size+ Size of the text. This can be used as 'start' for the
304
+ # next call to get progressive output
305
+ # * +more+ More data available for the job. 'true' if available
306
+ # and nil otherwise
307
+ #
308
+ def get_console_output(job_name, build_num = 0, start = 0, mode = 'text')
309
+ build_num = get_current_build_number(job_name) if build_num == 0
310
+ if build_num == 0
233
311
  puts "No builds for this job '#{job_name}' yet."
234
312
  return nil
235
313
  end
@@ -240,7 +318,9 @@ module JenkinsApi
240
318
  else
241
319
  raise "Mode should either be 'text' or 'html'. You gave: #{mode}"
242
320
  end
243
- api_response = @client.api_get_request("/job/#{job_name}/#{build_number}/logText/progressive#{mode}?start=#{start}", nil, nil)
321
+ get_msg = "/job/#{job_name}/#{build_num}/logText/progressice#{mode}?"
322
+ get_msg << "start=#{start}"
323
+ api_response = @client.api_get_request(get_msg, nil, nil)
244
324
  #puts "Response: #{api_response.header['x-more-data']}"
245
325
  response = {}
246
326
  response['output'] = api_response.body
@@ -278,7 +358,10 @@ module JenkinsApi
278
358
  xml_response = @client.api_get_request("", "tree=jobs[name,color]")
279
359
  filtered_jobs = []
280
360
  xml_response["jobs"].each do |job|
281
- filtered_jobs << job["name"] if color_to_status(job["color"]) == status && jobs.include?(job["name"])
361
+ if color_to_status(job["color"]) == status &&
362
+ jobs.include?(job["name"])
363
+ filtered_jobs << job["name"]
364
+ end
282
365
  end
283
366
  filtered_jobs
284
367
  end
@@ -347,6 +430,8 @@ module JenkinsApi
347
430
  #
348
431
  # @param [String] color color given by the API for a job
349
432
  #
433
+ # @return [String] status status of the given job matching the color
434
+ #
350
435
  def color_to_status(color)
351
436
  case color
352
437
  when "blue"
@@ -372,37 +457,30 @@ module JenkinsApi
372
457
  #
373
458
  # @param [String] job_name
374
459
  #
460
+ # @return [String] status current status of the given job
461
+ #
375
462
  def get_current_build_status(job_name)
376
463
  response_json = @client.api_get_request("/job/#{job_name}")
377
464
  color_to_status(response_json["color"])
378
465
  end
379
466
 
380
467
  # Obtain the current build number of the given job
381
- # This function returns nil if there were no builds for the given job name.
468
+ # This function returns nil if there were no builds for the given job.
382
469
  #
383
470
  # @param [String] job_name
384
471
  #
385
- def get_current_build_number(job_name)
386
- @client.api_get_request("/job/#{job_name}")['nextBuildNumber'] - 1
387
- end
388
-
389
- # This functions lists all jobs that are currently running on the Jenkins CI server
390
- # This method is deprecated. Please use list_by_status instead.
472
+ # @return [Number] build_unumber current build number of the given job
391
473
  #
392
- def list_running
393
- puts "[WARN] list_running is deprecated. Please use list_by_status('running') instead."
394
- xml_response = @client.api_get_request("", "tree=jobs[name,color]")
395
- running_jobs = []
396
- xml_response["jobs"].each { |job|
397
- running_jobs << job["name"] if color_to_status(job["color"]) == "running"
398
- }
399
- running_jobs
474
+ def get_current_build_number(job_name)
475
+ @client.api_get_request("/job/#{job_name}")['nextBuildNumber'].to_i - 1
400
476
  end
401
477
 
402
478
  # Build a job given the name of the job
403
479
  #
404
480
  # @param [String] job_name
405
481
  #
482
+ # @return [String] response_code return code from HTTP POST
483
+ #
406
484
  def build(job_name)
407
485
  @client.api_post_request("/job/#{job_name}/build")
408
486
  end
@@ -411,6 +489,8 @@ module JenkinsApi
411
489
  #
412
490
  # @param [String] job_name
413
491
  #
492
+ # @return [String] XML Config.xml of the job
493
+ #
414
494
  def get_config(job_name)
415
495
  @client.get_config("/job/#{job_name}")
416
496
  end
@@ -420,6 +500,8 @@ module JenkinsApi
420
500
  # @param [String] job_name
421
501
  # @param [String] xml
422
502
  #
503
+ # @return [String] response_code return code from HTTP POST
504
+ #
423
505
  def post_config(job_name, xml)
424
506
  @client.post_config("/job/#{job_name}/config.xml", xml)
425
507
  end
@@ -429,6 +511,8 @@ module JenkinsApi
429
511
  # @param [String] job_name
430
512
  # @param [String] description
431
513
  #
514
+ # @return [String] response_code return code from HTTP POST
515
+ #
432
516
  def change_description(job_name, description)
433
517
  xml = get_config(job_name)
434
518
  n_xml = Nokogiri::XML(xml)
@@ -442,6 +526,8 @@ module JenkinsApi
442
526
  #
443
527
  # @param [String] job_name
444
528
  #
529
+ # @return [String] response_code return code from HTTP POST
530
+ #
445
531
  def block_build_when_downstream_building(job_name)
446
532
  xml = get_config(job_name)
447
533
  n_xml = Nokogiri::XML(xml)
@@ -457,6 +543,8 @@ module JenkinsApi
457
543
  #
458
544
  # @param [String] job_name
459
545
  #
546
+ # @return [String] response_code return code from HTTP POST
547
+ #
460
548
  def unblock_build_when_downstream_building(job_name)
461
549
  xml = get_config(job_name)
462
550
  n_xml = Nokogiri::XML(xml)
@@ -472,6 +560,8 @@ module JenkinsApi
472
560
  #
473
561
  # @param [String] job_name
474
562
  #
563
+ # @return [String] response_code return code from HTTP POST
564
+ #
475
565
  def block_build_when_upstream_building(job_name)
476
566
  xml = get_config(job_name)
477
567
  n_xml = Nokogiri::XML(xml)
@@ -487,6 +577,8 @@ module JenkinsApi
487
577
  #
488
578
  # @param [String] job_name
489
579
  #
580
+ # @return [String] response_code return code from HTTP POST
581
+ #
490
582
  def unblock_build_when_upstream_building(job_name)
491
583
  xml = get_config(job_name)
492
584
  n_xml = Nokogiri::XML(xml)
@@ -498,11 +590,13 @@ module JenkinsApi
498
590
  end
499
591
  end
500
592
 
501
- # Allow to either execute concurrent builds or disable concurrent execution
593
+ # Allow or disable concurrent build execution
502
594
  #
503
595
  # @param [String] job_name
504
596
  # @param [Bool] option true or false
505
597
  #
598
+ # @return [String] response_code return code from HTTP POST
599
+ #
506
600
  def execute_concurrent_builds(job_name, option)
507
601
  xml = get_config(job_name)
508
602
  n_xml = Nokogiri::XML(xml)
@@ -519,7 +613,7 @@ module JenkinsApi
519
613
  #
520
614
  # @param [String] job_name
521
615
  #
522
- # @return [Array] params_array
616
+ # @return [Array] params_array Array of parameters for the given job
523
617
  #
524
618
  def get_build_params(job_name)
525
619
  xml = get_config(job_name)
@@ -530,39 +624,58 @@ module JenkinsApi
530
624
  params.children.each do |param|
531
625
  param_hash = {}
532
626
  case param.name
533
- when "hudson.model.StringParameterDefinition", "hudson.model.BooleanParameterDefinition", "hudson.model.TextParameterDefinition", "hudson.model.PasswordParameterDefinition"
627
+ when "hudson.model.StringParameterDefinition",
628
+ "hudson.model.BooleanParameterDefinition",
629
+ "hudson.model.TextParameterDefinition",
630
+ "hudson.model.PasswordParameterDefinition"
534
631
  param_hash[:type] = 'string' if param.name =~ /string/i
535
632
  param_hash[:type] = 'boolean' if param.name =~ /boolean/i
536
633
  param_hash[:type] = 'text' if param.name =~ /text/i
537
634
  param_hash[:type] = 'password' if param.name =~ /password/i
538
635
  param.children.each do |value|
539
636
  param_hash[:name] = value.content if value.name == "name"
540
- param_hash[:description] = value.content if value.name == "description"
541
- param_hash[:default] = value.content if value.name == "defaultValue"
637
+ if value.name == "description"
638
+ param_hash[:description] = value.content
639
+ end
640
+ if value.name == "defaultValue"
641
+ param_hash[:default] = value.content
642
+ end
542
643
  end
543
644
  when "hudson.model.RunParameterDefinition"
544
645
  param_hash[:type] = 'run'
545
646
  param.children.each do |value|
546
647
  param_hash[:name] = value.content if value.name == "name"
547
- param_hash[:description] = value.content if value.name == "description"
548
- param_hash[:project] = value.content if value.name == "projectName"
648
+ if value.name == "description"
649
+ param_hash[:description] = value.content
650
+ end
651
+ if value.name == "projectName"
652
+ param_hash[:project] = value.content
653
+ end
549
654
  end
550
655
  when "hudson.model.FileParameterDefinition"
551
656
  param_hash[:type] = 'file'
552
657
  param.children.each do |value|
553
658
  param_hash[:name] = value.content if value.name == "name"
554
- param_hash[:description] = value.content if value.name == "description"
659
+ param_hash[:description] = value.content \
660
+ if value.name == "description"
555
661
  end
556
662
  when "hudson.scm.listtagsparameter.ListSubversionTagsParameterDefinition"
557
663
  param_hash[:type] = 'list_tags'
558
664
  param.children.each do |value|
559
- param_hash[:name] = value.content if value.name == "name"
560
- param_hash[:description] = value.content if value.name == "description"
561
- param_hash[:tags_dir] = value.content if value.name == "tagsDir"
562
- param_hash[:tags_filter] = value.content if value.name == "tagsFilter"
563
- param_hash[:reverse_by_date] = value.content if value.name == "reverseByDate"
564
- param_hash[:reverse_by_name] = value.content if value.name == "reverseByName"
565
- param_hash[:default] = value.content if value.name == "defaultValue"
665
+ param_hash[:name] = value.content \
666
+ if value.name == "name"
667
+ param_hash[:description] = value.content \
668
+ if value.name == "description"
669
+ param_hash[:tags_dir] = value.content \
670
+ if value.name == "tagsDir"
671
+ param_hash[:tags_filter] = value.content \
672
+ if value.name == "tagsFilter"
673
+ param_hash[:reverse_by_date] = value.content \
674
+ if value.name == "reverseByDate"
675
+ param_hash[:reverse_by_name] = value.content \
676
+ if value.name == "reverseByName"
677
+ param_hash[:default] = value.content \
678
+ if value.name == "defaultValue"
566
679
  param_hash[:max_tags] = value.content if value.name == "maxTags"
567
680
  param_hash[:uuid] = value.content if value.name == "uuid"
568
681
  end
@@ -570,13 +683,15 @@ module JenkinsApi
570
683
  param_hash[:type] = 'choice'
571
684
  param.children.each do |value|
572
685
  param_hash[:name] = value.content if value.name == "name"
573
- param_hash[:description] = value.content if value.name == "description"
686
+ param_hash[:description] = value.content \
687
+ if value.name == "description"
574
688
  choices = []
575
689
  if value.name == "choices"
576
690
  value.children.each do |value_child|
577
691
  if value_child.name == "a"
578
692
  value_child.children.each do |choice_child|
579
- choices << choice_child.content.strip unless choice_child.content.strip.empty?
693
+ choices << choice_child.content.strip \
694
+ unless choice_child.content.strip.empty?
580
695
  end
581
696
  end
582
697
  end
@@ -585,15 +700,18 @@ module JenkinsApi
585
700
  end
586
701
  end
587
702
  params_array << param_hash unless param_hash.empty?
588
- end
589
- end
590
- params_array
703
+ end
704
+ end
705
+ params_array
591
706
  end
592
707
 
593
- # Obtains the threshold params used by jenkins in the XML file given the threshold
708
+ # Obtains the threshold params used by jenkins in the XML file
709
+ # given the threshold
594
710
  #
595
711
  # @param [String] threshold success, failure, or unstable
596
712
  #
713
+ # @return [String] status readable status matching the color
714
+ #
597
715
  def get_threshold_params(threshold)
598
716
  case threshold
599
717
  when 'success'
@@ -612,16 +730,20 @@ module JenkinsApi
612
730
  return name, ordinal, color
613
731
  end
614
732
 
615
- # Add downstream projects to a specific job given the job name, projects to be
616
- # added as downstream projects, and the threshold
733
+ # Add downstream projects to a specific job given the job name,
734
+ # projects to be added as downstream projects, and the threshold
617
735
  #
618
736
  # @param [String] job_name
619
737
  # @param [String] downstream_projects
620
738
  # @param [String] threshold - failure, success, or unstable
621
739
  # @param [Bool] overwrite - true or false
622
740
  #
623
- def add_downstream_projects(job_name, downstream_projects, threshold, overwrite = false)
624
- name, ordinal, color = get_threshold_params(threshold)
741
+ # @return [String] response_code return code from HTTP POST
742
+ #
743
+ def add_downstream_projects(job_name,
744
+ downstream_projects,
745
+ threshold, overwrite = false)
746
+ name, ord, col = get_threshold_params(threshold)
625
747
  xml = get_config(job_name)
626
748
  n_xml = Nokogiri::XML(xml)
627
749
  child_projects_node = n_xml.xpath("//childProjects").first
@@ -629,14 +751,24 @@ module JenkinsApi
629
751
  if overwrite
630
752
  child_projects_node.content = "#{downstream_projects}"
631
753
  else
632
- child_projects_node.content = child_projects_node.content + ", #{downstream_projects}"
754
+ to_replace = child_projects_node.content +
755
+ ", #{downstream_projects}"
756
+ child_projects_node.content = to_replace
633
757
  end
634
758
  else
635
759
  publisher_node = n_xml.xpath("//publishers").first
636
- build_trigger_node = publisher_node.add_child("<hudson.tasks.BuildTrigger/>")
637
- child_project_node = build_trigger_node.first.add_child("<childProjects>#{downstream_projects}</childProjects>")
638
- threshold_node = child_project_node.first.add_next_sibling("<threshold/>")
639
- threshold_node.first.add_child("<name>#{name}</name><ordinal>#{ordinal}</ordinal><color>#{color}</color>")
760
+ build_trigger_node = publisher_node.add_child(
761
+ "<hudson.tasks.BuildTrigger/>"
762
+ )
763
+ child_project_node = build_trigger_node.first.add_child(
764
+ "<childProjects>#{downstream_projects}</childProjects>"
765
+ )
766
+ threshold_node = child_project_node.first.add_next_sibling(
767
+ "<threshold/>"
768
+ )
769
+ threshold_node.first.add_child(
770
+ "<name>#{name}</name><ordinal>#{ord}</ordinal><color>#{col}</color>"
771
+ )
640
772
  end
641
773
  xml_modified = n_xml.to_xml
642
774
  post_config(job_name, xml_modified)
@@ -646,6 +778,8 @@ module JenkinsApi
646
778
  #
647
779
  # @param [String] job_name
648
780
  #
781
+ # @return [String] response_code return code from HTTP POST
782
+ #
649
783
  def remove_downstream_projects(job_name)
650
784
  xml = get_config(job_name)
651
785
  n_xml = Nokogiri::XML(xml)
@@ -678,6 +812,8 @@ module JenkinsApi
678
812
  # @param [String] job_name
679
813
  # @param [String] node_name
680
814
  #
815
+ # @return [String] response_code return code from HTTP POST
816
+ #
681
817
  def restrict_to_node(job_name, node_name)
682
818
  xml = get_config(job_name)
683
819
  n_xml = Nokogiri::XML(xml)
@@ -685,7 +821,7 @@ module JenkinsApi
685
821
  node.content = node_name
686
822
  else
687
823
  project = n_xml.xpath("//scm").first
688
- child_node = project.add_next_sibling("<assignedNode>#{node_name}</assignedNode>")
824
+ project.add_next_sibling("<assignedNode>#{node_name}</assignedNode>")
689
825
  roam_node = n_xml.xpath("//canRoam").first
690
826
  roam_node.content = "false"
691
827
  end
@@ -698,37 +834,54 @@ module JenkinsApi
698
834
  # @param [Array] job_names Array of job names to be unchained
699
835
  #
700
836
  def unchain(job_names)
701
- job_names.each { |job|
702
- puts "[INFO] Removing downstream projects for <#{job}>" if @client.debug
703
- @client.job.remove_downstream_projects(job)
704
- }
837
+ job_names.each do |job|
838
+ log_msg = "[INFO] Removing downstream projects for <#{job}>"
839
+ puts log_msg if @client.debug
840
+ remove_downstream_projects(job)
841
+ end
705
842
  end
706
843
 
707
844
  # Chain the jobs given based on specified criteria
708
845
  #
709
846
  # @param [Array] job_names Array of job names to be chained
710
- # @param [String] threshold what should be the threshold for running the next job
711
- # @param [Array] criteria criteria which should be applied for picking the jobs for the chain
712
- # @param [Integer] parallel Number of jobs that should be considered for parallel run
713
- #
847
+ # @param [String] threshold threshold for running the next job
848
+ # @param [Array] criteria criteria which should be applied for
849
+ # picking the jobs for the chain
850
+ # @param [Integer] parallel Number of jobs that should be considered
851
+ # for parallel run
852
+ #
853
+ # @return [Array] job_names Names of jobs that are in the top of the
854
+ # chain
714
855
  def chain(job_names, threshold, criteria, parallel = 1)
715
856
  raise "Parallel jobs should be at least 1" if parallel < 1
716
857
  unchain(job_names)
858
+
717
859
  filtered_job_names = []
718
860
  if criteria.include?("all") || criteria.empty?
719
861
  filtered_job_names = job_names
720
862
  else
721
- puts "[INFO] Criteria is specified. Filtering jobs..." if @client.debug
863
+ log_msg = "[INFO] Criteria is specified. Filtering jobs..."
864
+ puts log_msg if @client.debug
722
865
  job_names.each do |job|
723
- filtered_job_names << job if criteria.include?(@client.job.get_current_build_status(job))
866
+ filtered_job_names << job if criteria.include?(
867
+ @client.job.get_current_build_status(job)
868
+ )
724
869
  end
725
870
  end
871
+
726
872
  filtered_job_names.each_with_index do |job_name, index|
727
873
  break if index >= (filtered_job_names.length - parallel)
728
- puts "[INFO] Adding <#{filtered_job_names[index+1]}> as a downstream project to <#{job_name}> with <#{threshold}> as the threshold" if @client.debug
729
- @client.job.add_downstream_projects(job_name, filtered_job_names[index + parallel], threshold, true)
874
+ msg = "[INFO] Adding <#{filtered_job_names[index+1]}> as a"
875
+ msg << " downstream project to <#{job_name}> with <#{threshold}> as"
876
+ msg << " the threshold"
877
+ puts msg if @client.debug
878
+ @client.job.add_downstream_projects(
879
+ job_name, filtered_job_names[index + parallel], threshold, true
880
+ )
881
+ end
882
+ if parallel > filtered_job_names.length
883
+ parallel = filtered_job_names.length
730
884
  end
731
- parallel = filtered_job_names.length if parallel > filtered_job_names.length
732
885
  filtered_job_names[0..parallel-1]
733
886
  end
734
887