engineyard-hudson 0.2.2 → 0.3.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 (31) hide show
  1. data/Gemfile.lock +42 -22
  2. data/Rakefile +6 -1
  3. data/engineyard-hudson.gemspec +10 -5
  4. data/features/install.feature +2 -6
  5. data/features/server.feature +40 -13
  6. data/features/step_definitions/api_steps.rb +10 -0
  7. data/features/step_definitions/common_steps.rb +16 -4
  8. data/features/step_definitions/hudson_steps.rb +8 -2
  9. data/features/support/common.rb +15 -1
  10. data/features/support/engineyard.rb +24 -0
  11. data/features/support/env.rb +2 -1
  12. data/fixtures/hudson_boot_sequence/hudson_booting.html +1 -0
  13. data/fixtures/hudson_boot_sequence/hudson_ready.html +1 -0
  14. data/fixtures/hudson_boot_sequence/pre_hudson_booting.html +1 -0
  15. data/lib/engineyard-hudson/appcloud_env.rb +49 -0
  16. data/lib/engineyard-hudson/cli.rb +73 -4
  17. data/lib/engineyard-hudson/cli/install_server.rb +25 -0
  18. data/lib/engineyard-hudson/cli/{server → install_server}/templates/attributes.rb.tt +0 -0
  19. data/lib/engineyard-hudson/cli/{server → install_server}/templates/cookbooks/hudson_master/recipes/default.rb +0 -0
  20. data/lib/engineyard-hudson/cli/{server → install_server}/templates/cookbooks/hudson_master/templates/default/init.sh.erb +0 -0
  21. data/lib/engineyard-hudson/cli/{server → install_server}/templates/cookbooks/hudson_master/templates/default/proxy.conf.erb +0 -0
  22. data/lib/engineyard-hudson/cli/{server → install_server}/templates/cookbooks/main/attributes/recipe.rb +0 -0
  23. data/lib/engineyard-hudson/cli/{server → install_server}/templates/cookbooks/main/definitions/ey_cloud_report.rb +0 -0
  24. data/lib/engineyard-hudson/cli/{server → install_server}/templates/cookbooks/main/libraries/ruby_block.rb +0 -0
  25. data/lib/engineyard-hudson/cli/{server → install_server}/templates/cookbooks/main/libraries/run_for_app.rb +0 -0
  26. data/lib/engineyard-hudson/cli/{server → install_server}/templates/cookbooks/main/recipes/default.rb +0 -0
  27. data/lib/engineyard-hudson/version.rb +1 -1
  28. data/spec/appcloud_env_spec.rb +75 -0
  29. data/spec/spec_helper.rb +4 -0
  30. metadata +112 -26
  31. data/lib/engineyard-hudson/cli/server.rb +0 -41
data/Gemfile.lock CHANGED
@@ -1,26 +1,28 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- engineyard-hudson (0.2.2)
5
- engineyard (~> 1.3.3)
6
- thor (~> 0.14.3)
4
+ engineyard-hudson (0.3.0)
5
+ engineyard (~> 1.3.4)
6
+ ruby-debug
7
+ thor (~> 0.14.6)
7
8
 
8
9
  GEM
9
10
  remote: http://rubygems.org/
10
11
  specs:
11
12
  awesome_print (0.2.1)
12
13
  builder (2.1.2)
13
- cucumber (0.9.3)
14
+ columnize (0.3.1)
15
+ cucumber (0.9.4)
14
16
  builder (~> 2.1.2)
15
17
  diff-lcs (~> 1.1.2)
16
18
  gherkin (~> 2.2.9)
17
19
  json (~> 1.4.6)
18
20
  term-ansicolor (~> 1.0.5)
19
21
  diff-lcs (1.1.2)
20
- engineyard (1.3.3)
22
+ engineyard (1.3.4)
21
23
  engineyard-serverside-adapter (= 1.3.5)
22
24
  escape (~> 0.0.4)
23
- highline (~> 1.5.2)
25
+ highline (~> 1.6.1)
24
26
  json_pure
25
27
  rest-client (~> 1.4)
26
28
  thor (~> 0.14.3)
@@ -28,38 +30,56 @@ GEM
28
30
  escape (~> 0.0.4)
29
31
  json_pure
30
32
  escape (0.0.4)
33
+ fakeweb (1.3.0)
31
34
  gherkin (2.2.9)
32
35
  json (~> 1.4.6)
33
36
  term-ansicolor (~> 1.0.5)
34
- highline (1.5.2)
37
+ highline (1.6.1)
35
38
  json (1.4.6)
36
39
  json_pure (1.4.6)
40
+ linecache (0.43)
37
41
  mime-types (1.16)
42
+ open4 (1.0.1)
43
+ rack (1.2.1)
38
44
  rake (0.8.7)
45
+ realweb (0.1.6)
46
+ rack (>= 1.1.0)
39
47
  rest-client (1.6.1)
40
48
  mime-types (>= 1.16)
41
- rspec (2.0.1)
42
- rspec-core (~> 2.0.1)
43
- rspec-expectations (~> 2.0.1)
44
- rspec-mocks (~> 2.0.1)
45
- rspec-core (2.0.1)
46
- rspec-expectations (2.0.1)
47
- diff-lcs (>= 1.1.2)
48
- rspec-mocks (2.0.1)
49
- rspec-core (~> 2.0.1)
50
- rspec-expectations (~> 2.0.1)
49
+ rspec (2.1.0)
50
+ rspec-core (~> 2.1.0)
51
+ rspec-expectations (~> 2.1.0)
52
+ rspec-mocks (~> 2.1.0)
53
+ rspec-core (2.1.0)
54
+ rspec-expectations (2.1.0)
55
+ diff-lcs (~> 1.1.2)
56
+ rspec-mocks (2.1.0)
57
+ ruby-debug (0.10.3)
58
+ columnize (>= 0.1)
59
+ ruby-debug-base (~> 0.10.3.0)
60
+ ruby-debug-base (0.10.3)
61
+ linecache (>= 0.3)
62
+ sinatra (1.1.0)
63
+ rack (~> 1.1)
64
+ tilt (~> 1.1)
51
65
  term-ansicolor (1.0.5)
52
- thor (0.14.3)
66
+ thor (0.14.6)
67
+ tilt (1.1)
53
68
 
54
69
  PLATFORMS
55
70
  ruby
56
71
 
57
72
  DEPENDENCIES
58
73
  awesome_print
59
- cucumber (~> 0.9.3)
60
- engineyard (~> 1.3.3)
74
+ cucumber (~> 0.9.4)
75
+ engineyard (~> 1.3.4)
61
76
  engineyard-hudson!
77
+ fakeweb (~> 1.3.0)
62
78
  json (~> 1.4.0)
79
+ open4
63
80
  rake (~> 0.8.7)
64
- rspec (~> 2.0.1)
65
- thor (~> 0.14.3)
81
+ realweb (~> 0.1.6)
82
+ rspec (~> 2.1.0)
83
+ ruby-debug
84
+ sinatra
85
+ thor (~> 0.14.6)
data/Rakefile CHANGED
@@ -1,6 +1,11 @@
1
1
  require 'bundler'
2
2
  Bundler::GemHelper.install_tasks
3
3
 
4
+ require 'rspec/core/rake_task'
5
+
6
+ desc "Run all examples"
7
+ RSpec::Core::RakeTask.new
8
+
4
9
  namespace :cucumber do
5
10
  require 'cucumber/rake/task'
6
11
  Cucumber::Rake::Task.new(:wip, 'Run features that are being worked on') do |t|
@@ -16,4 +21,4 @@ desc 'Alias for cucumber:ok'
16
21
  task :cucumber => 'cucumber:ok'
17
22
 
18
23
  desc "Start test server; Run cucumber:ok; Kill Test Server;"
19
- task :default => ["cucumber"]
24
+ task :default => ["spec", "cucumber"]
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "engineyard-hudson"
5
- s.version = '0.2.2'
5
+ s.version = '0.3.0'
6
6
  s.platform = Gem::Platform::RUBY
7
7
  s.authors = ["Dr Nic Williams"]
8
8
  s.email = ["drnicwilliams@gmail.com"]
@@ -17,12 +17,17 @@ Gem::Specification.new do |s|
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
  s.require_paths = ["lib"]
19
19
 
20
- s.add_dependency("thor", ["~> 0.14.3"])
21
- s.add_dependency("engineyard", ["~> 1.3.3"])
20
+ s.add_dependency("thor", ["~> 0.14.6"])
21
+ s.add_dependency("engineyard", ["~> 1.3.4"])
22
22
 
23
23
  s.add_development_dependency("rake", ["~> 0.8.7"])
24
- s.add_development_dependency("cucumber", ["~> 0.9.3"])
25
- s.add_development_dependency("rspec", ["~> 2.0.1"])
24
+ s.add_development_dependency("cucumber", ["~> 0.9.4"])
25
+ s.add_development_dependency("rspec", ["~> 2.1.0"])
26
26
  s.add_development_dependency("json", ["~>1.4.0"])
27
27
  s.add_development_dependency("awesome_print")
28
+ s.add_development_dependency("realweb", '~>0.1.6')
29
+ s.add_development_dependency("open4")
30
+ s.add_development_dependency("sinatra")
31
+ s.add_development_dependency("fakeweb", "~>1.3.0")
32
+ s.add_dependency("ruby-debug")
28
33
  end
@@ -2,9 +2,7 @@ Feature: Managing a rails project as a Hudson CI job on AppCloud
2
2
  I want to build/test my project in the same environment I run in Engine Yard AppCloud
3
3
 
4
4
  Scenario: Setup first project as a slave for Hudson
5
- Given I have an environment "hudson" on account "drnic" on AppCloud
6
- And I have an environment "my_app_ci" on account "drnic" on AppCloud
7
- And I am in the "rails" project folder
5
+ Given I am in the "rails" project folder
8
6
  When I run local executable "ey-hudson" with arguments "install ."
9
7
  Then file "cookbooks/hudson_slave/attributes/default.rb" is created
10
8
  And file "cookbooks/hudson_slave/recipes/default.rb" is created
@@ -30,9 +28,7 @@ Feature: Managing a rails project as a Hudson CI job on AppCloud
30
28
  """
31
29
 
32
30
  Scenario: Setup project with existing cookbooks as a slave for Hudson
33
- Given I have an environment "hudson" on account "drnic" on AppCloud
34
- And I have an environment "my_app_ci" on account "drnic" on AppCloud
35
- And I am in the "rails" project folder
31
+ Given I am in the "rails" project folder
36
32
  And I already have cookbooks installed
37
33
  When I run local executable "ey-hudson" with arguments "install ."
38
34
  Then file "cookbooks/hudson_slave/attributes/default.rb" is created
@@ -1,9 +1,13 @@
1
1
  Feature: Managing ey hudson server
2
- I want to setup and manage a Hudson CI server hosted on Engine Yard AppCloud
2
+ I want to install a Hudson CI server hosted on Engine Yard AppCloud
3
3
 
4
- Scenario: Setup new Hudson CI server on AppCloud
5
- Given I have an environment "hudson" on account "drnic" on AppCloud
6
- When I run local executable "ey-hudson" with arguments "server ."
4
+ Background:
5
+ Given I have setup my engineyard email/password for API access
6
+ And I have "two accounts, two apps, two environments, ambiguous"
7
+ And I want to fake out the boot sequence of Hudson
8
+
9
+ Scenario: Install new Hudson CI server on AppCloud
10
+ When I run local executable "ey-hudson" with arguments "install_server . --account account_2 --environment giblets"
7
11
  Then file "cookbooks/main/recipes/default.rb" is created
8
12
  And file "cookbooks/hudson_master/recipes/default.rb" is created
9
13
  And file "cookbooks/hudson_master/attributes/default.rb" contains ":plugins => %w[git github rake ruby greenballs envfile]"
@@ -20,20 +24,43 @@ Feature: Managing ey hudson server
20
24
  create cookbooks/main/recipes/default.rb
21
25
  create cookbooks/hudson_master/attributes/default.rb
22
26
 
23
- Finally:
24
- * edit cookbooks/hudson_master/attributes/default.rb as necessary.
25
- * run: ey recipes upload # use --environment(-e) & --account(-c)
26
- * run: ey recipes apply # to select environment
27
- * Boot your environment if not already booted.
28
- When the recipe completes, your solo instance will host a Hudson CI!
27
+ Uploading to 'giblets' environment on 'account_2' account...
28
+ Environment is rebuilding...
29
+ ..
30
+ Hudson is starting...
31
+
32
+ Done! Hudson CI hosted at http://app-master-hostname.compute-1.amazonaws.com
29
33
  """
30
34
 
31
- Scenario: Setup Hudson CI server with additional Hudson plugins
32
- Given I have an environment "hudson" on account "drnic" on AppCloud
33
- When I run local executable "ey-hudson" with arguments "server . -p ' chucknorris , googleanalytics '"
35
+ @wip
36
+ Scenario: Install Hudson CI server with additional Hudson plugins
37
+ When I run local executable "ey-hudson" with arguments "install_server . -p ' chucknorris , googleanalytics ' -c account_2 -e giblets"
34
38
  Then file "cookbooks/main/recipes/default.rb" is created
35
39
  And file "cookbooks/hudson_master/recipes/default.rb" is created
36
40
  And file "cookbooks/hudson_master/attributes/default.rb" contains ":plugins => %w[git github rake ruby greenballs envfile chucknorris googleanalytics]"
41
+
42
+ Scenario: Display example explicit calls if multiple accounts/options
43
+ When I run local executable "ey-hudson" with arguments "install_server . -e giblets"
44
+ Then file "cookbooks/main/recipes/default.rb" is not created
45
+ And I should see exactly
46
+ """
47
+ Multiple environments possible, please be more specific:
48
+
49
+ ey-hudson install_server --environment 'giblets' --account 'main'
50
+ ey-hudson install_server --environment 'giblets' --account 'account_2'
51
+ """
52
+
53
+ Scenario: Ask for environment/account details if no obvious hudson environment on AppCloud
54
+ When I run local executable "ey-hudson" with arguments "install_server ."
55
+ Then file "cookbooks/main/recipes/default.rb" is not created
56
+ And I should see exactly
57
+ """
58
+ No environments with name hudson, hudson_server, hudson_production, hudson_server_production.
59
+ Either:
60
+ * Create an AppCloud environment called hudson, hudson_server, hudson_production, hudson_server_production
61
+ * Use --environment/--account flags to select AppCloud environment
62
+ """
63
+
37
64
 
38
65
 
39
66
 
@@ -0,0 +1,10 @@
1
+ Given /^I have setup my engineyard email\/password for API access$/ do
2
+ ENV['EYRC'] = File.join(@home_path, ".eyrc")
3
+ token = { ENV['CLOUD_URL'] => {
4
+ "api_token" => "f81a1706ddaeb148cfb6235ddecfc1cf"} }
5
+ File.open(ENV['EYRC'], "w"){|f| YAML.dump(token, f) }
6
+ end
7
+
8
+ When /^I have "two accounts, two apps, two environments, ambiguous"$/ do
9
+ api_scenario "two accounts, two apps, two environments, ambiguous"
10
+ end
@@ -44,10 +44,22 @@ When /^I run project executable "(.*)" with arguments "(.*)"/ do |executable, ar
44
44
  end
45
45
 
46
46
  When /^I run local executable "(.*)" with arguments "(.*)"/ do |executable, arguments|
47
- @stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
48
- executable = File.expand_path(File.join(File.dirname(__FILE__), "/../../bin", executable))
49
- in_project_folder do
50
- system "ruby -rubygems #{executable.inspect} #{arguments} > #{@stdout.inspect} 2> #{@stdout.inspect}"
47
+ if executable == "ey-hudson"
48
+ require 'engineyard-hudson'
49
+ require 'engineyard-hudson/cli'
50
+ in_project_folder do
51
+ stdout, stderr = capture_stdios do
52
+ Engineyard::Hudson::CLI.start(arguments.split(/ /))
53
+ end
54
+ @stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
55
+ File.open(@stdout, "w") {|f| f << stdout; f << stderr}
56
+ end
57
+ else
58
+ @stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
59
+ executable = File.expand_path(File.join(File.dirname(__FILE__), "/../../bin", executable))
60
+ in_project_folder do
61
+ system "ruby -rubygems #{executable.inspect} #{arguments} > #{@stdout.inspect} 2> #{@stdout.inspect}"
62
+ end
51
63
  end
52
64
  end
53
65
 
@@ -1,3 +1,9 @@
1
- Given /^I have an environment "([^"]*)" on account "([^"]*)" on AppCloud$/ do |env, account|
2
-
1
+ Given /^I want to fake out the boot sequence of Hudson$/ do
2
+ base_path = File.join(File.dirname(__FILE__) + "/../../fixtures/hudson_boot_sequence/")
3
+ FakeWeb.register_uri(:get, "http://app-master-hostname.compute-1.amazonaws.com/", [
4
+ {:body => File.read(base_path + "pre_hudson_booting.html")},
5
+ {:body => File.read(base_path + "hudson_booting.html")},
6
+ {:body => File.read(base_path + "hudson_ready.html")}
7
+ ])
3
8
  end
9
+
@@ -32,6 +32,20 @@ module CommonHelpers
32
32
  @active_project_folder = File.join(@tmp_root, project_name)
33
33
  @project_name = project_name
34
34
  end
35
- end
36
35
 
36
+ # capture both [stdout, stderr] as well as stdin
37
+ def capture_stdios(input = nil, &block)
38
+ require 'stringio'
39
+ org_stdin, $stdin = $stdin, StringIO.new(input) if input
40
+ org_stdout, $stdout = $stdout, StringIO.new
41
+ org_stderr, $stderr = $stdout, StringIO.new
42
+ yield
43
+ return [$stdout.string, $stderr.string]
44
+ ensure
45
+ $stderr = org_stderr
46
+ $stdout = org_stdout
47
+ $stdin = org_stdin
48
+ end
49
+ end
50
+
37
51
  World(CommonHelpers)
@@ -0,0 +1,24 @@
1
+ engineyard_loaded_path = $:.select { |path| path =~ %r|gems/engineyard-\d+| }.first
2
+ EY_ROOT = engineyard_loaded_path.gsub(%r|/\w+$|,'')
3
+
4
+ # helper to be stubbed out from engineyard spec_helper.rb
5
+ def shared_examples_for(title)
6
+ end
7
+
8
+ support = Dir[File.join(EY_ROOT,'/spec/support/*.rb')]
9
+ support.each{|helper| require helper }
10
+ World(Spec::Helpers)
11
+
12
+ require "fakeweb"
13
+
14
+ Before do
15
+ ENV["NO_SSH"] = "true"
16
+ ENV['CLOUD_URL'] = EY.fake_awsm
17
+ FakeWeb.allow_net_connect = true
18
+ end
19
+
20
+ After do
21
+ ENV.delete('CLOUD_URL')
22
+ ENV.delete('EYRC')
23
+ ENV.delete('NO_SSH')
24
+ end
@@ -1,9 +1,10 @@
1
1
  $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../lib'))
2
- require 'engineyard-hudson'
3
2
  require 'bundler/setup'
3
+ require 'engineyard-hudson'
4
4
 
5
5
  Before do
6
6
  @tmp_root = File.dirname(__FILE__) + "/../../tmp"
7
+ @active_project_folder = @tmp_root
7
8
  @home_path = File.expand_path(File.join(@tmp_root, "home"))
8
9
  @lib_path = File.expand_path(File.dirname(__FILE__) + "/../../lib")
9
10
  @fixtures_path = File.expand_path(File.dirname(__FILE__) + "/../../fixtures")
@@ -0,0 +1 @@
1
+ Please wait while Hudson is getting ready to work
@@ -0,0 +1 @@
1
+ Hudson is up!
@@ -0,0 +1 @@
1
+ This is some page before the instance is launched.
@@ -0,0 +1,49 @@
1
+ require "engineyard"
2
+ require "engineyard/thor"
3
+ require "engineyard/cli"
4
+ require "engineyard/cli/ui"
5
+ require "engineyard/error"
6
+ module Engineyard
7
+ module Hudson
8
+ class AppcloudEnv
9
+ include EY::UtilityMethods
10
+
11
+ # Returns [environment, account] based on current .eyrc credentials and/or CLI options
12
+ # Returns [nil, nil] if no unique environment can be selected
13
+ def find_environments(options = {})
14
+ Thor::Base.shell = EY::CLI::UI
15
+ EY.ui = EY::CLI::UI.new
16
+ query_environments = options[:environment] ? [options[:environment]] : default_query_environments
17
+ query_environments.inject([]) do |envs, env_name|
18
+ begin
19
+ if environment = fetch_environment(env_name, options[:account])
20
+ clean_host_name(environment)
21
+ envs << [env_name, environment.account.name, environment]
22
+ end
23
+ rescue EY::NoEnvironmentError
24
+ rescue EY::MultipleMatchesError => e
25
+ # e.message looks something like:
26
+ # Multiple environments possible, please be more specific:
27
+ #
28
+ # hudson # ey <command> --environment='hudson' --account='drnic-demo'
29
+ # hudson # ey <command> --environment='hudson' --account='rails-hudson'
30
+ e.message.scan(/--environment='([^']+)' --account='([^']+)'/) do
31
+ envs << [$1, $2, nil]
32
+ end
33
+ end
34
+ envs
35
+ end
36
+ end
37
+
38
+ def default_query_environments
39
+ %w[hudson hudson_server hudson_production hudson_server_production]
40
+ end
41
+
42
+ # Currently the engineyard gem has badly formed URLs in its same data
43
+ # This method cleans app_master_hostname.compute-1.amazonaws.com -> app-master-hostname.compute-1.amazonaws.com
44
+ def clean_host_name(environment)
45
+ environment.instances.first.public_hostname.gsub!(/_/,'-') if environment.instances.first
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,5 +1,6 @@
1
1
  require 'thor'
2
2
  require 'engineyard-hudson/thor-ext/actions/directory'
3
+ require 'engineyard-hudson/appcloud_env'
3
4
 
4
5
  module Engineyard
5
6
  module Hudson
@@ -11,10 +12,74 @@ module Engineyard
11
12
  Engineyard::Hudson::Install.start(ARGV[1..-1])
12
13
  end
13
14
 
14
- desc "server PROJECT_PATH", "Setup a Hudson CI server on AppCloud."
15
- def server(project_path)
16
- require 'engineyard-hudson/cli/server'
17
- Engineyard::Hudson::Server.start(ARGV[1..-1])
15
+ desc "install_server [PROJECT_PATH]", "Install Hudson CI into an AppCloud environment."
16
+ method_option :verbose, :aliases => ["-V"], :desc => "Display more output"
17
+ method_option :environment, :aliases => ["-e"], :desc => "Environment in which to deploy this application", :type => :string
18
+ method_option :account, :aliases => ["-c"], :desc => "Name of the account you want to deploy in"
19
+ def install_server(project_path=nil)
20
+ environments = Engineyard::Hudson::AppcloudEnv.new.find_environments(options)
21
+ if environments.size == 0
22
+ say "No environments with name hudson, hudson_server, hudson_production, hudson_server_production.", :red
23
+ say "Either:"
24
+ say " * Create an AppCloud environment called hudson, hudson_server, hudson_production, hudson_server_production"
25
+ say " * Use --environment/--account flags to select AppCloud environment"
26
+ return
27
+ elsif environments.size > 1
28
+ say "Multiple environments possible, please be more specific:", :red
29
+ say ""
30
+ environments.each do |env_name, account_name, environment|
31
+ say " ey-hudson install_server --environment "; say "'#{env_name}' ", :yellow;
32
+ say "--account "; say "'#{account_name}'", :yellow
33
+ end
34
+ return
35
+ end
36
+
37
+ env_name, account_name, environment = environments.first
38
+ public_hostname, status = environment.instances.first.public_hostname, environment.instances.first.status if environment.instances.first
39
+
40
+ temp_project_path = File.expand_path(project_path || File.join(Dir.tmpdir, "temp_hudson_server"))
41
+ shell.say "Temp installation dir: #{temp_project_path}" if options[:verbose]
42
+ FileUtils.mkdir_p(temp_project_path)
43
+ FileUtils.chdir(FileUtils.mkdir_p(temp_project_path)) do
44
+ require 'engineyard-hudson/cli/install_server'
45
+ Engineyard::Hudson::InstallServer.start(ARGV.unshift(temp_project_path))
46
+
47
+ require 'engineyard/cli/recipes'
48
+ say ""
49
+ say "Uploading to "; say "'#{env_name}' ", :yellow; say "environment on "; say "'#{account_name}' ", :yellow; say "account..."
50
+ environment.upload_recipes
51
+
52
+ if status == "running"
53
+ environment.run_custom_recipes
54
+ say "Environment is rebuilding..."
55
+ waiting = true
56
+ while waiting
57
+ begin
58
+ Net::HTTP.start(public_hostname, 80) do |http|
59
+ waiting = (body = http.get("/").body) !~ /Please wait while Hudson is getting ready to work/
60
+ end
61
+ sleep 1; print '.'; $stdout.flush
62
+ rescue SocketError => e
63
+ sleep 1; print 'x'; $stdout.flush
64
+ rescue Exception
65
+ sleep 1; print '.'; $stdout.flush
66
+ end
67
+ end
68
+ say ""
69
+ say "Hudson is starting..."
70
+ Net::HTTP.start(public_hostname, 80) do |http|
71
+ while http.get("/").body =~ /Please wait while Hudson is getting ready to work/
72
+ sleep 1; print '.'; $stdout.flush
73
+ end
74
+ end
75
+ say ""
76
+ say "Done! Hudson CI hosted at "; say "http://#{public_hostname}", :green
77
+ else
78
+ say ""
79
+ say "Almost there..."
80
+ say "* Boot your environment via https://cloud.engineyard.com", :yellow
81
+ end
82
+ end
18
83
  end
19
84
 
20
85
  desc "version", "show version information"
@@ -26,6 +91,10 @@ module Engineyard
26
91
  map "-v" => :version, "--version" => :version, "-h" => :help, "--help" => :help
27
92
 
28
93
  private
94
+ def say(msg, color = nil)
95
+ color ? shell.say(msg, color) : shell.say(msg)
96
+ end
97
+
29
98
  def display(text)
30
99
  shell.say text
31
100
  exit
@@ -0,0 +1,25 @@
1
+ require 'thor/group'
2
+
3
+ module Engineyard
4
+ module Hudson
5
+ class InstallServer < Thor::Group
6
+ include Thor::Actions
7
+
8
+ class_option :plugins, :aliases => '-p', :desc => 'additional Hudson CI plugins (comma separated)'
9
+
10
+ def self.source_root
11
+ File.join(File.dirname(__FILE__), "install_server", "templates")
12
+ end
13
+
14
+ def cookbooks
15
+ directory "cookbooks"
16
+ end
17
+
18
+ def attributes
19
+ @plugins = %w[git github rake ruby greenballs envfile] + (options[:plugins] || '').strip.split(/\s*,\s*/)
20
+ template "attributes.rb.tt", "cookbooks/hudson_master/attributes/default.rb"
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -1,5 +1,5 @@
1
1
  module Engineyard
2
2
  module Hudson
3
- VERSION = '0.2.2'
3
+ VERSION = '0.3.0'
4
4
  end
5
5
  end
@@ -0,0 +1,75 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ require 'engineyard-hudson/appcloud_env'
4
+
5
+ describe Engineyard::Hudson::AppcloudEnv do
6
+ def appcloud_env
7
+ @appcloud_env ||= Engineyard::Hudson::AppcloudEnv.new
8
+ end
9
+
10
+ def find_environments(options = {})
11
+ appcloud_env.find_environments(options)
12
+ end
13
+
14
+ before do
15
+ @tmp_root = File.dirname(__FILE__) + "/../tmp"
16
+ @home_path = File.expand_path(File.join(@tmp_root, "home"))
17
+ FileUtils.mkdir_p(@home_path)
18
+ ENV['EYRC'] = File.join(@home_path, ".eyrc")
19
+ appcloud_env.stub(:clean_host_name)
20
+ end
21
+ describe ".find_environments - no args" do
22
+ it "return [nil, nil] unless it has reason to return something else" do
23
+ appcloud_env.stub(:fetch_environment).and_raise(EY::NoEnvironmentError)
24
+ find_environments.should == []
25
+ end
26
+ it "returns [env_name, account_name] if finds one env 'hudson' in any account" do
27
+ appcloud_env.should_receive(:fetch_environment).with("hudson", nil).and_return(env = EY::Model::App.new(123, EY::Model::Account.new(789, 'mine')))
28
+ appcloud_env.should_receive(:fetch_environment).with("hudson_server", nil).and_raise(EY::NoEnvironmentError)
29
+ appcloud_env.should_receive(:fetch_environment).with("hudson_production", nil).and_raise(EY::NoEnvironmentError)
30
+ appcloud_env.should_receive(:fetch_environment).with("hudson_server_production", nil).and_raise(EY::NoEnvironmentError)
31
+ find_environments.should == [['hudson', 'mine', env]]
32
+ end
33
+ it "returns many result pairs" do
34
+ appcloud_env.should_receive(:fetch_environment).with("hudson", nil).and_return(env = EY::Model::App.new(123, EY::Model::Account.new(789, 'mine')))
35
+ appcloud_env.should_receive(:fetch_environment).with("hudson_server", nil).and_raise(EY::NoEnvironmentError)
36
+ appcloud_env.should_receive(:fetch_environment).with("hudson_server_production", nil).and_raise(EY::NoEnvironmentError)
37
+ appcloud_env.should_receive(:fetch_environment).with("hudson_production", nil) {
38
+ raise EY::MultipleMatchesError, <<-ERROR.gsub(/^\s+/, '')
39
+ hudson_production # ey <command> --environment='hudson_production' --account='mine'
40
+ hudson_production # ey <command> --environment='hudson_production' --account='yours'
41
+ ERROR
42
+ }
43
+ find_environments.should == [['hudson', 'mine', env], ['hudson_production', 'mine', nil], ['hudson_production', 'yours', nil]]
44
+ end
45
+ end
46
+
47
+ describe ".find_environments - specific account" do
48
+ it "return [nil, nil] unless it has reason to return something else" do
49
+ appcloud_env.stub(:fetch_environment).and_raise(EY::NoEnvironmentError)
50
+ find_environments(:account => "mine").should == []
51
+ end
52
+ it "returns [env_name, account_name] if finds one env 'hudson' in specific account" do
53
+ appcloud_env.should_receive(:fetch_environment).with("hudson", "mine").and_return(env = EY::Model::App.new(123, EY::Model::Account.new(789, 'mine')))
54
+ appcloud_env.should_receive(:fetch_environment).with("hudson_server", "mine").and_raise(EY::NoEnvironmentError)
55
+ appcloud_env.should_receive(:fetch_environment).with("hudson_production", "mine").and_raise(EY::NoEnvironmentError)
56
+ appcloud_env.should_receive(:fetch_environment).with("hudson_server_production", "mine").and_raise(EY::NoEnvironmentError)
57
+ find_environments(:account => "mine").should == [['hudson', 'mine', env]]
58
+ end
59
+ end
60
+
61
+ describe ".find_environments - specific environment" do
62
+ it "return [nil, nil] unless it has reason to return something else" do
63
+ appcloud_env.stub(:fetch_environment).and_raise(EY::NoEnvironmentError)
64
+ find_environments(:environment => "hudson").should == []
65
+ end
66
+ it "returns [env_name, account_name] if finds one env 'hudson' in any account" do
67
+ appcloud_env.should_receive(:fetch_environment).with("hudson", nil).and_return(env = EY::Model::App.new(123, EY::Model::Account.new(789, 'mine')))
68
+ find_environments(:environment => "hudson").should == [['hudson', 'mine', env]]
69
+ end
70
+ it "returns [env_name, account_name] if finds one env 'hudson' in specific account" do
71
+ appcloud_env.should_receive(:fetch_environment).with("hudson", "mine").and_return(env = EY::Model::App.new(123, EY::Model::Account.new(789, 'mine')))
72
+ find_environments(:environment => "hudson", :account => "mine").should == [['hudson', 'mine', env]]
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,4 @@
1
+ $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
2
+ require 'bundler/setup'
3
+ require 'engineyard-hudson'
4
+ require 'rspec'
metadata CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 2
9
- - 2
10
- version: 0.2.2
8
+ - 3
9
+ - 0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Dr Nic Williams
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-03 00:00:00 -07:00
18
+ date: 2010-11-24 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -26,12 +26,12 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- hash: 33
29
+ hash: 43
30
30
  segments:
31
31
  - 0
32
32
  - 14
33
- - 3
34
- version: 0.14.3
33
+ - 6
34
+ version: 0.14.6
35
35
  type: :runtime
36
36
  version_requirements: *id001
37
37
  - !ruby/object:Gem::Dependency
@@ -42,12 +42,12 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- hash: 29
45
+ hash: 19
46
46
  segments:
47
47
  - 1
48
48
  - 3
49
- - 3
50
- version: 1.3.3
49
+ - 4
50
+ version: 1.3.4
51
51
  type: :runtime
52
52
  version_requirements: *id002
53
53
  - !ruby/object:Gem::Dependency
@@ -74,12 +74,12 @@ dependencies:
74
74
  requirements:
75
75
  - - ~>
76
76
  - !ruby/object:Gem::Version
77
- hash: 61
77
+ hash: 51
78
78
  segments:
79
79
  - 0
80
80
  - 9
81
- - 3
82
- version: 0.9.3
81
+ - 4
82
+ version: 0.9.4
83
83
  type: :development
84
84
  version_requirements: *id004
85
85
  - !ruby/object:Gem::Dependency
@@ -90,12 +90,12 @@ dependencies:
90
90
  requirements:
91
91
  - - ~>
92
92
  - !ruby/object:Gem::Version
93
- hash: 13
93
+ hash: 11
94
94
  segments:
95
95
  - 2
96
- - 0
97
96
  - 1
98
- version: 2.0.1
97
+ - 0
98
+ version: 2.1.0
99
99
  type: :development
100
100
  version_requirements: *id005
101
101
  - !ruby/object:Gem::Dependency
@@ -128,6 +128,80 @@ dependencies:
128
128
  version: "0"
129
129
  type: :development
130
130
  version_requirements: *id007
131
+ - !ruby/object:Gem::Dependency
132
+ name: realweb
133
+ prerelease: false
134
+ requirement: &id008 !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ~>
138
+ - !ruby/object:Gem::Version
139
+ hash: 23
140
+ segments:
141
+ - 0
142
+ - 1
143
+ - 6
144
+ version: 0.1.6
145
+ type: :development
146
+ version_requirements: *id008
147
+ - !ruby/object:Gem::Dependency
148
+ name: open4
149
+ prerelease: false
150
+ requirement: &id009 !ruby/object:Gem::Requirement
151
+ none: false
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ hash: 3
156
+ segments:
157
+ - 0
158
+ version: "0"
159
+ type: :development
160
+ version_requirements: *id009
161
+ - !ruby/object:Gem::Dependency
162
+ name: sinatra
163
+ prerelease: false
164
+ requirement: &id010 !ruby/object:Gem::Requirement
165
+ none: false
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ hash: 3
170
+ segments:
171
+ - 0
172
+ version: "0"
173
+ type: :development
174
+ version_requirements: *id010
175
+ - !ruby/object:Gem::Dependency
176
+ name: fakeweb
177
+ prerelease: false
178
+ requirement: &id011 !ruby/object:Gem::Requirement
179
+ none: false
180
+ requirements:
181
+ - - ~>
182
+ - !ruby/object:Gem::Version
183
+ hash: 27
184
+ segments:
185
+ - 1
186
+ - 3
187
+ - 0
188
+ version: 1.3.0
189
+ type: :development
190
+ version_requirements: *id011
191
+ - !ruby/object:Gem::Dependency
192
+ name: ruby-debug
193
+ prerelease: false
194
+ requirement: &id012 !ruby/object:Gem::Requirement
195
+ none: false
196
+ requirements:
197
+ - - ">="
198
+ - !ruby/object:Gem::Version
199
+ hash: 3
200
+ segments:
201
+ - 0
202
+ version: "0"
203
+ type: :runtime
204
+ version_requirements: *id012
131
205
  description: Run your continuous integration (CI) tests against your Engine Yard AppCloud environments - the exact same configuration you are using in production!
132
206
  email:
133
207
  - drnicwilliams@gmail.com
@@ -148,18 +222,24 @@ files:
148
222
  - engineyard-hudson.gemspec
149
223
  - features/install.feature
150
224
  - features/server.feature
225
+ - features/step_definitions/api_steps.rb
151
226
  - features/step_definitions/common_steps.rb
152
227
  - features/step_definitions/fixture_project_steps.rb
153
228
  - features/step_definitions/hudson_steps.rb
154
229
  - features/support/common.rb
230
+ - features/support/engineyard.rb
155
231
  - features/support/env.rb
156
232
  - features/support/matchers.rb
157
233
  - fixtures/cookbooks/main/recipes/default.rb
158
234
  - fixtures/cookbooks/redis/recipes/default.rb
235
+ - fixtures/hudson_boot_sequence/hudson_booting.html
236
+ - fixtures/hudson_boot_sequence/hudson_ready.html
237
+ - fixtures/hudson_boot_sequence/pre_hudson_booting.html
159
238
  - fixtures/projects/rails/Gemfile
160
239
  - fixtures/projects/rails/Gemfile.lock
161
240
  - fixtures/projects/rails/Rakefile
162
241
  - lib/engineyard-hudson.rb
242
+ - lib/engineyard-hudson/appcloud_env.rb
163
243
  - lib/engineyard-hudson/cli.rb
164
244
  - lib/engineyard-hudson/cli/install.rb
165
245
  - lib/engineyard-hudson/cli/install/templates/attributes.rb.tt
@@ -168,18 +248,20 @@ files:
168
248
  - lib/engineyard-hudson/cli/install/templates/cookbooks/main/libraries/ruby_block.rb
169
249
  - lib/engineyard-hudson/cli/install/templates/cookbooks/main/libraries/run_for_app.rb
170
250
  - lib/engineyard-hudson/cli/install/templates/recipes.rb
171
- - lib/engineyard-hudson/cli/server.rb
172
- - lib/engineyard-hudson/cli/server/templates/attributes.rb.tt
173
- - lib/engineyard-hudson/cli/server/templates/cookbooks/hudson_master/recipes/default.rb
174
- - lib/engineyard-hudson/cli/server/templates/cookbooks/hudson_master/templates/default/init.sh.erb
175
- - lib/engineyard-hudson/cli/server/templates/cookbooks/hudson_master/templates/default/proxy.conf.erb
176
- - lib/engineyard-hudson/cli/server/templates/cookbooks/main/attributes/recipe.rb
177
- - lib/engineyard-hudson/cli/server/templates/cookbooks/main/definitions/ey_cloud_report.rb
178
- - lib/engineyard-hudson/cli/server/templates/cookbooks/main/libraries/ruby_block.rb
179
- - lib/engineyard-hudson/cli/server/templates/cookbooks/main/libraries/run_for_app.rb
180
- - lib/engineyard-hudson/cli/server/templates/cookbooks/main/recipes/default.rb
251
+ - lib/engineyard-hudson/cli/install_server.rb
252
+ - lib/engineyard-hudson/cli/install_server/templates/attributes.rb.tt
253
+ - lib/engineyard-hudson/cli/install_server/templates/cookbooks/hudson_master/recipes/default.rb
254
+ - lib/engineyard-hudson/cli/install_server/templates/cookbooks/hudson_master/templates/default/init.sh.erb
255
+ - lib/engineyard-hudson/cli/install_server/templates/cookbooks/hudson_master/templates/default/proxy.conf.erb
256
+ - lib/engineyard-hudson/cli/install_server/templates/cookbooks/main/attributes/recipe.rb
257
+ - lib/engineyard-hudson/cli/install_server/templates/cookbooks/main/definitions/ey_cloud_report.rb
258
+ - lib/engineyard-hudson/cli/install_server/templates/cookbooks/main/libraries/ruby_block.rb
259
+ - lib/engineyard-hudson/cli/install_server/templates/cookbooks/main/libraries/run_for_app.rb
260
+ - lib/engineyard-hudson/cli/install_server/templates/cookbooks/main/recipes/default.rb
181
261
  - lib/engineyard-hudson/thor-ext/actions/directory.rb
182
262
  - lib/engineyard-hudson/version.rb
263
+ - spec/appcloud_env_spec.rb
264
+ - spec/spec_helper.rb
183
265
  has_rdoc: true
184
266
  homepage: http://github.com/engineyard/engineyard-hudson
185
267
  licenses: []
@@ -217,9 +299,13 @@ summary: Easier to do CI than not to. Use Hudson CI with Engine Yard AppCloud.
217
299
  test_files:
218
300
  - features/install.feature
219
301
  - features/server.feature
302
+ - features/step_definitions/api_steps.rb
220
303
  - features/step_definitions/common_steps.rb
221
304
  - features/step_definitions/fixture_project_steps.rb
222
305
  - features/step_definitions/hudson_steps.rb
223
306
  - features/support/common.rb
307
+ - features/support/engineyard.rb
224
308
  - features/support/env.rb
225
309
  - features/support/matchers.rb
310
+ - spec/appcloud_env_spec.rb
311
+ - spec/spec_helper.rb
@@ -1,41 +0,0 @@
1
- require 'thor/group'
2
-
3
- module Engineyard
4
- module Hudson
5
- class Server < Thor::Group
6
- include Thor::Actions
7
-
8
- argument :project_path
9
-
10
- class_option :plugins, :aliases => '-p', :desc => 'additional Hudson CI plugins (comma separated)'
11
-
12
- def self.source_root
13
- File.join(File.dirname(__FILE__), "server", "templates")
14
- end
15
-
16
- def cookbooks
17
- directory "cookbooks"
18
- end
19
-
20
- def attributes
21
- @plugins = %w[git github rake ruby greenballs envfile] + (options[:plugins] || '').strip.split(/\s*,\s*/)
22
- template "attributes.rb.tt", "cookbooks/hudson_master/attributes/default.rb"
23
- end
24
-
25
- def readme
26
- say ""
27
- say "Finally:"
28
- say "* edit "; say "cookbooks/hudson_master/attributes/default.rb ", :yellow; say "as necessary."
29
- say "* run: "; say "ey recipes upload ", :green; say "# use --environment(-e) & --account(-c)"
30
- say "* run: "; say "ey recipes apply ", :green; say "# to select environment"
31
- say "* "; say "Boot your environment ", :yellow; say "if not already booted."
32
- say "When the recipe completes, your solo instance will host a Hudson CI!"
33
- end
34
-
35
- private
36
- def say(msg, color = nil)
37
- color ? shell.say(msg, color) : shell.say(msg)
38
- end
39
- end
40
- end
41
- end