hudson 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.gitignore +1 -0
  2. data/Changelog.md +3 -0
  3. data/Gemfile.lock +11 -43
  4. data/README.md +3 -151
  5. data/Rakefile +0 -77
  6. data/bin/hudson +2 -10
  7. data/hudson.gemspec +2 -12
  8. data/lib/hudson.rb +1 -8
  9. data/lib/hudson/version.rb +1 -1
  10. metadata +8 -203
  11. data/features/default_host.feature +0 -19
  12. data/features/development.feature +0 -14
  13. data/features/launch_server.feature +0 -17
  14. data/features/listing_jobs.feature +0 -34
  15. data/features/manage_jobs.feature +0 -207
  16. data/features/manage_slave_nodes.feature +0 -80
  17. data/features/step_definitions/common_steps.rb +0 -197
  18. data/features/step_definitions/fixture_project_steps.rb +0 -8
  19. data/features/step_definitions/hudson_steps.rb +0 -104
  20. data/features/step_definitions/scm_steps.rb +0 -12
  21. data/features/support/common.rb +0 -37
  22. data/features/support/env.rb +0 -14
  23. data/features/support/hooks.rb +0 -16
  24. data/features/support/hudson_helpers.rb +0 -6
  25. data/features/support/matchers.rb +0 -10
  26. data/lib/hudson/api.rb +0 -219
  27. data/lib/hudson/cli.rb +0 -253
  28. data/lib/hudson/cli/formatting.rb +0 -53
  29. data/lib/hudson/config.rb +0 -27
  30. data/lib/hudson/core_ext/hash.rb +0 -9
  31. data/lib/hudson/core_ext/object/blank.rb +0 -77
  32. data/lib/hudson/hudson-cli.jar +0 -0
  33. data/lib/hudson/installation.rb +0 -136
  34. data/lib/hudson/job_config_builder.rb +0 -287
  35. data/lib/hudson/project_scm.rb +0 -22
  36. data/lib/hudson/remote.rb +0 -11
  37. data/spec/fixtures/ec2_global.config.xml +0 -103
  38. data/spec/fixtures/rails.multi.config.xml +0 -82
  39. data/spec/fixtures/rails.single.config.triggers.xml +0 -84
  40. data/spec/fixtures/rails.single.config.xml +0 -80
  41. data/spec/fixtures/ruby.multi-ruby-multi-labels.config.xml +0 -84
  42. data/spec/fixtures/ruby.multi.config.xml +0 -77
  43. data/spec/fixtures/ruby.single.config.xml +0 -58
  44. data/spec/fixtures/therubyracer.config.xml +0 -77
  45. data/spec/hash_key_cleaner_spec.rb +0 -25
  46. data/spec/job_config_builder_spec.rb +0 -137
  47. data/spec/spec_helper.rb +0 -15
@@ -1,8 +0,0 @@
1
- Given /^I am in the "([^\"]*)" project folder$/ do |project|
2
- project_folder = File.expand_path(File.dirname(__FILE__) + "/../../fixtures/projects/#{project}")
3
- in_tmp_folder do
4
- FileUtils.cp_r(project_folder, project)
5
- setup_active_project_folder(project)
6
- end
7
- end
8
-
@@ -1,104 +0,0 @@
1
- Given /^I have a Hudson server running$/ do
2
- unless @hudson_port
3
- port = 3010
4
- begin
5
- res = Net::HTTP.start("localhost", port) { |http| http.get('/api/json') }
6
- Hudson::Api.base_uri "http://localhost:#{port}"
7
- rescue Errno::ECONNREFUSED => e
8
- raise Exception, "To run tests, launch hudson in test mode: 'rake hudson:server:test'"
9
- end
10
- @hudson_port = port.to_s
11
- @hudson_host = 'localhost'
12
- end
13
- end
14
-
15
- Given /^the Hudson server has no current jobs$/ do
16
- if port = @hudson_port
17
- Hudson::Api.summary['jobs'].each do |job|
18
- Hudson::Api.delete_job(job['name'])
19
- end
20
- Hudson::Api.summary['jobs'].should == []
21
- else
22
- puts "WARNING: Run 'I have a Hudson server running' step first."
23
- end
24
- end
25
-
26
- Given /^the Hudson server has no slaves$/ do
27
- if port = @hudson_port
28
- Hudson::Api.summary['jobs'].each do |job|
29
- Hudson::Api.delete_job(job['name'])
30
- end
31
- Hudson::Api.summary['jobs'].should == []
32
-
33
- Hudson::Api.nodes['computer'].each do |node|
34
- name = node['displayName']
35
- Hudson::Api.delete_node(name) unless name == "master"
36
- end
37
- Hudson::Api.nodes['computer'].size.should == 1
38
- else
39
- puts "WARNING: Run 'I have a Hudson server running' step first."
40
- end
41
- end
42
-
43
- Given /^there is nothing listening on port (\d+)$/ do |port|
44
- lambda {
45
- TCPSocket.open("localhost", port) {}
46
- }.should raise_error
47
- end
48
-
49
- Given /^I cleanup any hudson processes with control port (\d+)$/ do |port|
50
- @hudson_cleanup << port
51
- end
52
-
53
- def try(times, interval = 1)
54
- begin
55
- times -= 1
56
- return yield
57
- rescue Exception => e
58
- if times >= 0
59
- sleep(interval)
60
- retry
61
- end
62
- raise e
63
- end
64
- end
65
-
66
- When /^I run hudson server with arguments "(.*)"/ do |arguments|
67
- @stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
68
- executable = File.expand_path(File.join(File.dirname(__FILE__), "/../../bin","hudson"))
69
- in_project_folder do
70
- system "ruby #{executable.inspect} server #{arguments} > #{@stdout.inspect} 2> #{@stdout.inspect}"
71
- end
72
- end
73
-
74
-
75
- Then /^I should see a hudson server on port (\d+)$/ do |port|
76
- require 'json'
77
- try(15, 2) do
78
- Hudson::Api.base_uri "http://localhost:#{port}"
79
- Hudson::Api.summary['nodeDescription'].should == "the master Hudson node"
80
- end
81
- end
82
-
83
- When /^I (re|)create a job$/ do |override|
84
- override = override.blank? ? "" : " --override"
85
- steps <<-CUCUMBER
86
- When the project uses "git" scm
87
- When I run local executable "hudson" with arguments "create . --host localhost --port 3010#{override}"
88
- CUCUMBER
89
- end
90
-
91
- Then /^the job "([^"]*)" config "([^"]*)" should be:$/ do |job_name, xpath, string|
92
- raise "Cannot yet fetch XML config from non-localhost Hudson" unless Hudson::Api.base_uri =~ /localhost/
93
- require "hpricot"
94
- config = Hpricot.XML(File.read("#{test_hudson_path}/jobs/#{job_name}/config.xml"))
95
- config.search(xpath).to_s.should == string
96
- end
97
-
98
- Then /^the Hudson config "([^"]*)" should be:$/ do |xpath, string|
99
- raise "Cannot yet fetch XML config from non-localhost Hudson" unless Hudson::Api.base_uri =~ /localhost/
100
- require "hpricot"
101
- config = Hpricot.XML(File.read("#{test_hudson_path}/config.xml"))
102
- config.search(xpath).to_s.should == string
103
- end
104
-
@@ -1,12 +0,0 @@
1
- Given /^the project uses "git" scm$/ do
2
- repo = "git://some.host/drnic/ruby.git"
3
- in_project_folder do
4
- unless File.exist?(".git")
5
- %x[ git init ]
6
- %x[ git add . ]
7
- %x[ git commit -m "initial commit" ]
8
- %x[ git remote add origin #{repo} ]
9
- end
10
- end
11
- end
12
-
@@ -1,37 +0,0 @@
1
- module CommonHelpers
2
- def get_command_output
3
- strip_color_codes(File.read(@stdout)).chomp
4
- end
5
-
6
- def strip_color_codes(text)
7
- text.gsub(/\e\[\d+m/, '')
8
- end
9
-
10
- def in_tmp_folder(&block)
11
- FileUtils.chdir(@tmp_root, &block)
12
- end
13
-
14
- def in_project_folder(&block)
15
- project_folder = @active_project_folder || @tmp_root
16
- FileUtils.chdir(project_folder, &block)
17
- end
18
-
19
- def in_home_folder(&block)
20
- FileUtils.chdir(@home_path, &block)
21
- end
22
-
23
- def force_local_lib_override(project_name = @project_name)
24
- rakefile = File.read(File.join(project_name, 'Rakefile'))
25
- File.open(File.join(project_name, 'Rakefile'), "w+") do |f|
26
- f << "$:.unshift('#{@lib_path}')\n"
27
- f << rakefile
28
- end
29
- end
30
-
31
- def setup_active_project_folder project_name
32
- @active_project_folder = File.join(@tmp_root, project_name)
33
- @project_name = project_name
34
- end
35
- end
36
-
37
- World(CommonHelpers)
@@ -1,14 +0,0 @@
1
- $:.unshift(File.expand_path(File.dirname(__FILE__) + "/../../lib"))
2
- require 'hudson.rb'
3
- require 'bundler/setup'
4
- require 'ap'
5
-
6
- Before do
7
- @tmp_root = File.dirname(__FILE__) + "/../../tmp"
8
- @home_path = File.expand_path(File.join(@tmp_root, "home"))
9
- @lib_path = File.expand_path(File.dirname(__FILE__) + "/../../lib")
10
- FileUtils.rm_rf @tmp_root
11
- FileUtils.mkdir_p @home_path
12
- ENV['HOME'] = @home_path
13
- ENV['CUCUMBER_RUNNING'] = 'oooh yes'
14
- end
@@ -1,16 +0,0 @@
1
- require 'socket'
2
-
3
- Before do
4
- @hudson_cleanup = []
5
- end
6
-
7
- After do
8
- for port in @hudson_cleanup do
9
- begin
10
- TCPSocket.open("localhost", port) do |sock|
11
- sock.write("0")
12
- end
13
- rescue
14
- end
15
- end
16
- end
@@ -1,6 +0,0 @@
1
- module HudsonHelper
2
- def test_hudson_path
3
- "/tmp/test_hudson"
4
- end
5
- end
6
- World(HudsonHelper)
@@ -1,10 +0,0 @@
1
-
2
- module Matchers
3
- RSpec::Matchers.define :contain do |expected_text|
4
- match do |text|
5
- text.index expected_text
6
- end
7
- end
8
- end
9
-
10
- World(Matchers)
@@ -1,219 +0,0 @@
1
- require 'httparty'
2
- require 'cgi'
3
- require 'uri'
4
- require 'json'
5
-
6
- require 'hudson/core_ext/hash'
7
- require 'hudson/config'
8
-
9
- module Hudson
10
- module Api
11
- include HTTParty
12
-
13
- headers 'content-type' => 'application/json'
14
- format :json
15
- # http_proxy 'localhost', '8888'
16
-
17
- JobAlreadyExistsError = Class.new(Exception)
18
-
19
- def self.setup_base_url(options)
20
- options = options.with_clean_keys
21
- # Thor's HashWithIndifferentAccess is based on string keys which URI::HTTP.build ignores
22
- options = options.inject({}) { |mem, (key, val)| mem[key.to_sym] = val; mem }
23
- options[:host] ||= ENV['HUDSON_HOST']
24
- options[:port] ||= ENV['HUDSON_PORT']
25
- options[:port] &&= options[:port].to_i
26
- return false unless options[:host] || Hudson::Config.config["base_uri"]
27
- uri = options[:host] ? URI::HTTP.build(options) : Hudson::Config.config["base_uri"]
28
- base_uri uri.to_s
29
- uri
30
- end
31
-
32
- # returns true if successfully create a new job on Hudson
33
- # +job_config+ is a Hudson::JobConfigBuilder instance
34
- # +options+ are:
35
- # :override - true, will delete any existing job with same name, else error
36
- #
37
- # returns true if successful, else false
38
- #
39
- # TODO Exceptions?
40
- def self.create_job(name, job_config, options = {})
41
- options = options.with_clean_keys
42
- delete_job(name) if options[:override]
43
- begin
44
- res = post "/createItem/api/xml?name=#{CGI.escape(name)}", {
45
- :body => job_config.to_xml, :format => :xml, :headers => { 'content-type' => 'application/xml' }
46
- }
47
- if res.code.to_i == 200
48
- cache_base_uri
49
- true
50
- else
51
- require "hpricot"
52
- doc = Hpricot(res.body)
53
- error_msg = doc.search("td#main-panel p")
54
- unless error_msg.inner_text.blank?
55
- $stderr.puts error_msg.inner_text
56
- else
57
- # TODO - what are the errors we get?
58
- puts "Server error:"
59
- p res.code
60
- puts res.body
61
- end
62
- false
63
- end
64
- rescue REXML::ParseException => e
65
- # For some reason, if the job exists we get back half a page of HTML
66
- raise JobAlreadyExistsError.new(name)
67
- end
68
- end
69
-
70
- # Attempts to delete a job +name+
71
- def self.delete_job(name)
72
- res = post_plain "#{job_url name}/doDelete"
73
- res.code.to_i == 302
74
- end
75
-
76
- def self.build_job(name)
77
- res = get_plain "/job/#{name}/build"
78
- res.code.to_i == 302
79
- end
80
-
81
- def self.summary
82
- json = get "/api/json"
83
- cache_base_uri
84
- json
85
- end
86
-
87
- def self.job_names
88
- summary["jobs"].map {|job| job["name"]}
89
- end
90
-
91
- # Return hash of job statuses
92
- def self.job(name)
93
- begin
94
- json = get "/job/#{name}/api/json"
95
- cache_base_uri
96
- json
97
- rescue Crack::ParseError
98
- false
99
- end
100
- end
101
-
102
- def self.nodes
103
- json = get "/computer/api/json"
104
- cache_base_uri
105
- json
106
- end
107
-
108
- # Adds SSH nodes only, for now
109
- def self.add_node(options = {})
110
- options = options.with_clean_keys
111
- default_options = Hash.new
112
- if options[:vagrant]
113
- default_options.merge!(
114
- :slave_port => 2222,
115
- :slave_user => 'vagrant',
116
- :master_key => "/Library/Ruby/Gems/1.8/gems/vagrant-0.6.7/keys/vagrant", # FIXME - hardcoded master username assumption
117
- :slave_fs => "/vagrant/tmp/hudson-slave/",
118
- :description => "Automatically created by Hudson.rb",
119
- :executors => 2,
120
- :exclusive => true
121
- )
122
- else
123
- default_options.merge!(
124
- :slave_port => 22,
125
- :slave_user => 'deploy',
126
- :master_key => "/home/deploy/.ssh/id_rsa", # FIXME - hardcoded master username assumption
127
- :slave_fs => "/data/hudson-slave/",
128
- :description => "Automatically created by Hudson.rb",
129
- :executors => 2,
130
- :exclusive => true
131
- )
132
- end
133
- options = default_options.merge(options)
134
-
135
- slave_host = options[:slave_host]
136
- name = options[:name] || slave_host
137
- labels = options[:labels].split(/\s*,\s*/).join(' ') if options[:labels]
138
-
139
- type = "hudson.slaves.DumbSlave$DescriptorImpl"
140
-
141
- fields = {
142
- "name" => name,
143
- "type" => type,
144
-
145
- "json" => {
146
- "name" => name,
147
- "nodeDescription" => options[:description],
148
- "numExecutors" => options[:executors],
149
- "remoteFS" => options[:slave_fs],
150
- "labelString" => labels,
151
- "mode" => options[:exclusive] ? "EXCLUSIVE" : "NORMAL",
152
- "type" => type,
153
- "retentionStrategy" => { "stapler-class" => "hudson.slaves.RetentionStrategy$Always" },
154
- "nodeProperties" => { "stapler-class-bag" => "true" },
155
- "launcher" => {
156
- "stapler-class" => "hudson.plugins.sshslaves.SSHLauncher",
157
- "host" => slave_host,
158
- "port" => options[:slave_port],
159
- "username" => options[:slave_user],
160
- "privatekey" => options[:master_key],
161
- }
162
- }.to_json
163
- }
164
-
165
- url = URI.parse("#{base_uri}/computer/doCreateItem")
166
-
167
- req = Net::HTTP::Post.new(url.path)
168
- req.set_form_data(fields)
169
-
170
- http = Net::HTTP.new(url.host, url.port)
171
-
172
- response = http.request(req)
173
- case response
174
- when Net::HTTPFound
175
- { :name => name, :slave_host => slave_host }
176
- else
177
- # error message looks like:
178
- # <td id="main-panel">
179
- # <h1>Error</h1><p>Slave called 'localhost' already exists</p>
180
- require "hpricot"
181
- error = Hpricot(response.body).search("td#main-panel p").text
182
- unless error.blank?
183
- puts error
184
- else
185
- puts response.body # so we can find other errors
186
- end
187
- false
188
- end
189
- end
190
-
191
- def self.delete_node(name)
192
- post_plain("#{base_uri}/computer/#{CGI::escape(name).gsub('+', '%20')}/doDelete/api/json")
193
- end
194
-
195
- # Helper for POST that don't barf at Hudson's crappy API responses
196
- def self.post_plain(path, options = {})
197
- options = options.with_clean_keys
198
- uri = URI.parse base_uri
199
- res = Net::HTTP.start(uri.host, uri.port) { |http| http.post(path, options) }
200
- end
201
-
202
- # Helper for GET that don't barf at Hudson's crappy API responses
203
- def self.get_plain(path, options = {})
204
- options = options.with_clean_keys
205
- uri = URI.parse base_uri
206
- res = Net::HTTP.start(uri.host, uri.port) { |http| http.get(path, options) }
207
- end
208
-
209
- private
210
- def self.cache_base_uri
211
- Hudson::Config.config["base_uri"] = base_uri
212
- Hudson::Config.store!
213
- end
214
-
215
- def self.job_url(name)
216
- "#{base_uri}/job/#{name}"
217
- end
218
- end
219
- end
@@ -1,253 +0,0 @@
1
- require 'thor'
2
- require 'hudson/core_ext/object/blank'
3
- require 'hudson/core_ext/hash'
4
- require 'hudson/cli/formatting'
5
- require 'hudson/remote'
6
-
7
- module Hudson
8
- class CLI < Thor
9
- include CLI::Formatting
10
-
11
- map "-v" => :version, "--version" => :version, "-h" => :help, "--help" => :help
12
-
13
- def self.common_options
14
- method_option :host, :desc => 'connect to hudson server on this host'
15
- method_option :port, :desc => 'connect to hudson server on this port'
16
- end
17
-
18
- desc "server [options]", "run a hudson server"
19
- method_option :home, :desc => "use this directory to store server data", :type => :string, :default => File.join(ENV['HOME'], ".hudson", "server"), :banner => "PATH"
20
- method_option :port, :desc => "run hudson server on this port", :type => :numeric, :default => 3001, :aliases => "-p"
21
- method_option :control, :desc => "set the shutdown/control port", :type => :numeric, :default => 3002, :aliases => "-c"
22
- method_option :daemon, :desc => "fork into background and run as a daemon", :type => :boolean, :default => false
23
- method_option :kill, :desc => "send shutdown signal to control port", :type => :boolean, :aliases => "-k"
24
- method_option :logfile, :desc => "redirect log messages to this file", :type => :string, :banner => "PATH"
25
- method_option :upgrade, :desc => "upgrade hudson server and plugins to latest version", :type => :boolean
26
- def server
27
- installation = Hudson::Installation.new(shell, options)
28
- if options[:kill]
29
- installation.kill!
30
- exit(0)
31
- elsif options[:upgrade]
32
- installation.upgrade!
33
- exit(0)
34
- else
35
- installation.launch!
36
- end
37
- end
38
-
39
- desc "create project_path [options]", "create a build for your project"
40
- common_options
41
- method_option :rubies, :desc => "run tests against multiple explicit rubies via RVM", :type => :string
42
- method_option :"node-labels", :desc => "run tests against multiple slave nodes by their label (comma separated)"
43
- method_option :"assigned-node", :desc => "only use slave nodes with this label (similar to --node-labels)"
44
- method_option :"no-build", :desc => "create job without initial build", :type => :boolean, :default => false
45
- method_option :override, :desc => "override if job exists", :type => :boolean, :default => false
46
- method_option :"scm", :desc => "specific SCM URI", :type => :string
47
- method_option :"scm-branches", :desc => "list of branches to build from (comma separated)", :type => :string, :default => "master"
48
- method_option :"public-scm", :desc => "use public scm URL", :type => :boolean, :default => false
49
- method_option :template, :desc => "template of job steps (available: #{JobConfigBuilder::VALID_JOB_TEMPLATES.join ','})", :default => 'ruby'
50
- method_option :"no-template", :desc => "do not use a template of default steps; avoids Gemfile requirement", :type => :boolean, :default => false
51
- def create(project_path)
52
- select_hudson_server(options)
53
- FileUtils.chdir(project_path) do
54
- unless scm = Hudson::ProjectScm.discover(options[:scm])
55
- error "Cannot determine project SCM. Currently supported: #{Hudson::ProjectScm.supported}"
56
- end
57
- unless (options[:template] == "none" || options[:"no-template"]) || File.exists?("Gemfile")
58
- error "Ruby/Rails projects without a Gemfile are currently unsupported."
59
- end
60
- begin
61
- template = options[:"no-template"] ? 'none' : options[:template]
62
- job_config = Hudson::JobConfigBuilder.new(template) do |c|
63
- c.rubies = options[:rubies].split(/\s*,\s*/) if options[:rubies]
64
- c.node_labels = options[:"node-labels"].split(/\s*,\s*/) if options[:"node-labels"]
65
- c.scm = scm.url
66
- c.scm_branches = options[:"scm-branches"].split(/\s*,\s*/)
67
- c.assigned_node = options[:"assigned-node"] if options[:"assigned-node"]
68
- c.public_scm = options[:"public-scm"]
69
- end
70
- name = File.basename(FileUtils.pwd)
71
- if Hudson::Api.create_job(name, job_config, options)
72
- build_url = "#{@uri}/job/#{name.gsub(/\s/,'%20')}/build"
73
- shell.say "Added#{' ' + template unless template == 'none'} project '#{name}' to Hudson.", :green
74
- unless options[:"no-build"]
75
- shell.say "Triggering initial build..."
76
- Hudson::Api.build_job(name)
77
- shell.say "Trigger additional builds via:"
78
- else
79
- shell.say "Trigger builds via:"
80
- end
81
- shell.say " URL: "; shell.say "#{build_url}", :yellow
82
- shell.say " CLI: "; shell.say "#{cmd} build #{name}", :yellow
83
- else
84
- error "Failed to create project '#{name}'"
85
- end
86
- rescue Hudson::JobConfigBuilder::InvalidTemplate
87
- error "Invalid job template '#{template}'."
88
- rescue Hudson::Api::JobAlreadyExistsError
89
- error "Job '#{name}' already exists."
90
- end
91
- end
92
- end
93
-
94
- desc "build [PROJECT_PATH]", "trigger build of this project's build job"
95
- common_options
96
- def build(project_path = ".")
97
- select_hudson_server(options)
98
- FileUtils.chdir(project_path) do
99
- name = File.basename(FileUtils.pwd)
100
- if Hudson::Api.build_job(name)
101
- shell.say "Build for '#{name}' running now..."
102
- else
103
- error "No job '#{name}' on server."
104
- end
105
- end
106
- end
107
-
108
- desc "remove PROJECT_PATH", "remove this project's build job from Hudson"
109
- common_options
110
- def remove(project_path)
111
- select_hudson_server(options)
112
- FileUtils.chdir(project_path) do
113
- name = File.basename(FileUtils.pwd)
114
- if Hudson::Api.delete_job(name)
115
- shell.say "Removed project '#{name}' from Hudson."
116
- else
117
- error "Failed to delete project '#{name}'."
118
- end
119
- end
120
- end
121
-
122
- desc "job NAME", "Display job details"
123
- method_option :hash, :desc => 'Dump as formatted Ruby hash format'
124
- method_option :json, :desc => 'Dump as JSON format'
125
- method_option :yaml, :desc => 'Dump as YAML format'
126
- common_options
127
- def job(name)
128
- select_hudson_server(options)
129
- if job = Hudson::Api.job(name)
130
- if options[:hash]
131
- require "ap"
132
- ap job.parsed_response
133
- elsif options[:json]
134
- puts job.parsed_response.to_json
135
- elsif options[:yaml]
136
- require "yaml"
137
- puts job.parsed_response.to_yaml
138
- else
139
- error "Select an output format: --json, --xml, --yaml, --hash"
140
- end
141
- else
142
- error "Cannot find project '#{name}'."
143
- end
144
- end
145
-
146
- desc "list [options]", "list jobs on a hudson server"
147
- common_options
148
- def list
149
- select_hudson_server(options)
150
- summary = Hudson::Api.summary
151
- unless summary["jobs"].blank?
152
- shell.say "#{@uri}:", :bold
153
- summary["jobs"].each do |job|
154
- bold = job['color'] =~ /anime/
155
- color = 'red' if job['color'] =~ /red/
156
- color = 'green' if job['color'] =~ /(blue|green)/
157
- color ||= 'yellow' # if color =~ /grey/ || color == 'disabled'
158
- shell.say "* "; shell.say(shell.set_color(job['name'], color.to_sym, bold), nil, true)
159
- end
160
- shell.say ""
161
- else
162
- shell.say "#{@uri}: "; shell.say "no jobs", :yellow
163
- end
164
- end
165
-
166
- desc "nodes", "list hudson server nodes"
167
- common_options
168
- def nodes
169
- select_hudson_server(options)
170
- nodes = Hudson::Api.nodes
171
- nodes["computer"].each do |node|
172
- color = node["offline"] ? :red : :green
173
- shell.say node["displayName"], color
174
- end
175
- end
176
-
177
- desc "add_node SLAVE_HOST", "add a URI (user@host:port) server as a slave node"
178
- method_option :labels, :desc => 'Labels for a job --assigned_node to match against to select a slave (comma separated)'
179
- method_option :"slave-user", :desc => 'SSH user for Hudson to connect to slave node (default: deploy)'
180
- method_option :"slave-port", :desc => 'SSH port for Hudson to connect to slave node (default: 22)'
181
- method_option :"master-key", :desc => 'Location of master public key or identity file'
182
- method_option :"slave-fs", :desc => 'Location of file system on slave for Hudson to use'
183
- method_option :name, :desc => 'Name of slave node (default SLAVE_HOST)'
184
- method_option :vagrant, :desc => 'Use settings for a Vagrant VM', :type => :boolean, :default => false
185
- common_options
186
- def add_node(slave_host)
187
- select_hudson_server(options)
188
- if results = Hudson::Api.add_node({:slave_host => slave_host}.merge(options))
189
- shell.say "Added slave node '#{results[:name]}' to #{results[:slave_host]}", :green
190
- else
191
- error "Failed to add slave node #{slave_host}"
192
- end
193
- end
194
-
195
- desc "default_host", "display current default host:port URI"
196
- def default_host
197
- if select_hudson_server({})
198
- display Hudson::Api.base_uri
199
- else
200
- display "No default host yet. Use '--host host --port port' on your first request."
201
- end
202
- end
203
-
204
- desc "help [command]", "show help for hudson or for a specific command"
205
- def help(*args)
206
- super(*args)
207
- end
208
-
209
- desc "version", "show version information"
210
- def version
211
- shell.say "#{Hudson::VERSION}"
212
- end
213
-
214
- def self.help(shell, *)
215
- list = printable_tasks
216
- shell.say <<-USEAGE
217
- Hudson.rb is a smart set of utilities for making
218
- continuous integration as simple as possible
219
-
220
- Usage: hudson command [arguments] [options]
221
-
222
- USEAGE
223
-
224
- shell.say "Commands:"
225
- shell.print_table(list, :ident => 2, :truncate => true)
226
- shell.say
227
- class_options_help(shell)
228
- end
229
-
230
- private
231
-
232
- def select_hudson_server(options)
233
- unless @uri = Hudson::Api.setup_base_url(options)
234
- error "Either use --host or add remote servers."
235
- end
236
- @uri
237
- end
238
-
239
- def display(text)
240
- shell.say text
241
- exit
242
- end
243
-
244
- def error(text)
245
- shell.say "ERROR: #{text}", :red
246
- exit
247
- end
248
-
249
- def cmd
250
- ENV['CUCUMBER_RUNNING'] ? 'hudson' : $0
251
- end
252
- end
253
- end