hudson 0.5.0 → 0.6.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 (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