engineyard-serverside 2.0.7 → 2.1.0.pre

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 (98) hide show
  1. data/lib/engineyard-serverside.rb +0 -1
  2. data/lib/engineyard-serverside/cli.rb +44 -42
  3. data/lib/engineyard-serverside/configuration.rb +55 -4
  4. data/lib/engineyard-serverside/dependency_manager.rb +17 -0
  5. data/lib/engineyard-serverside/dependency_manager/base.rb +65 -0
  6. data/lib/engineyard-serverside/dependency_manager/bundler.rb +124 -0
  7. data/lib/engineyard-serverside/dependency_manager/bundler_lock.rb +155 -0
  8. data/lib/engineyard-serverside/dependency_manager/legacy_helpers.rb +24 -0
  9. data/lib/engineyard-serverside/dependency_manager/npm.rb +16 -0
  10. data/lib/engineyard-serverside/deploy.rb +86 -178
  11. data/lib/engineyard-serverside/deprecation.rb +11 -1
  12. data/lib/engineyard-serverside/paths.rb +6 -0
  13. data/lib/engineyard-serverside/propagator.rb +2 -2
  14. data/lib/engineyard-serverside/rails_assets.rb +152 -0
  15. data/lib/engineyard-serverside/rails_assets/strategy.rb +197 -0
  16. data/lib/engineyard-serverside/server.rb +5 -0
  17. data/lib/engineyard-serverside/servers.rb +19 -7
  18. data/lib/engineyard-serverside/shell.rb +7 -5
  19. data/lib/engineyard-serverside/shell/command_result.rb +1 -1
  20. data/lib/engineyard-serverside/strategies/git.rb +14 -4
  21. data/lib/engineyard-serverside/task.rb +1 -0
  22. data/lib/engineyard-serverside/version.rb +1 -1
  23. data/spec/bundler_deploy_spec.rb +36 -33
  24. data/spec/configuration_spec.rb +5 -4
  25. data/spec/custom_deploy_spec.rb +11 -9
  26. data/spec/deploy_hook_spec.rb +10 -3
  27. data/spec/ey_yml_customized_deploy_spec.rb +1 -1
  28. data/spec/fixtures/lockfiles/1.0-no-bundler +1 -1
  29. data/spec/fixtures/lockfiles/1.0.0.rc.1-with-bundler +1 -1
  30. data/spec/fixtures/lockfiles/1.0.18-do_mysql +1 -1
  31. data/spec/fixtures/lockfiles/1.0.18-do_postgres +1 -1
  32. data/spec/fixtures/lockfiles/1.0.18-mysql +1 -1
  33. data/spec/fixtures/lockfiles/1.0.18-mysql2 +1 -1
  34. data/spec/fixtures/lockfiles/1.0.18-pg +1 -1
  35. data/spec/fixtures/lockfiles/1.0.6-no-bundler +2 -2
  36. data/spec/fixtures/lockfiles/1.0.6-with-any-bundler +2 -2
  37. data/spec/fixtures/lockfiles/1.0.6-with-bundler +2 -2
  38. data/spec/fixtures/lockfiles/1.3.1-rails-3.2.13 +112 -0
  39. data/spec/fixtures/repos/{assets_enabled → assets_detected}/Gemfile +1 -2
  40. data/spec/fixtures/repos/{assets_enabled → assets_detected}/Gemfile.lock +1 -3
  41. data/spec/fixtures/repos/{assets_enabled → assets_detected}/README +0 -0
  42. data/spec/fixtures/repos/assets_detected/Rakefile +5 -0
  43. data/spec/fixtures/repos/{assets_enabled → assets_detected}/app/assets/empty +0 -0
  44. data/spec/fixtures/repos/{assets_enabled → assets_detected}/config/application.rb +0 -0
  45. data/spec/fixtures/repos/assets_detected/config/ey.yml +3 -0
  46. data/spec/fixtures/repos/assets_disabled/Gemfile +1 -2
  47. data/spec/fixtures/repos/assets_disabled/Gemfile.lock +1 -3
  48. data/spec/fixtures/repos/assets_disabled/Rakefile +1 -0
  49. data/spec/fixtures/repos/assets_disabled/config/ey.yml +3 -0
  50. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Gemfile +1 -2
  51. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Gemfile.lock +1 -3
  52. data/spec/fixtures/repos/assets_disabled_in_ey_yml/Rakefile +1 -0
  53. data/spec/fixtures/repos/assets_disabled_in_ey_yml/config/ey.yml +1 -0
  54. data/spec/fixtures/repos/assets_enabled_all/Gemfile +1 -2
  55. data/spec/fixtures/repos/assets_enabled_all/Gemfile.lock +1 -3
  56. data/spec/fixtures/repos/assets_enabled_all/Rakefile +1 -0
  57. data/spec/fixtures/repos/assets_enabled_all/config/ey.yml +1 -0
  58. data/spec/fixtures/repos/assets_enabled_in_ey_yml/Gemfile +1 -1
  59. data/spec/fixtures/repos/assets_enabled_in_ey_yml/Gemfile.lock +1 -1
  60. data/spec/fixtures/repos/assets_enabled_in_ey_yml/Rakefile +1 -0
  61. data/spec/fixtures/repos/assets_enabled_util_only/Gemfile +1 -2
  62. data/spec/fixtures/repos/assets_enabled_util_only/Gemfile.lock +1 -3
  63. data/spec/fixtures/repos/assets_enabled_util_only/Rakefile +1 -0
  64. data/spec/fixtures/repos/assets_enabled_util_only/config/ey.yml +1 -0
  65. data/spec/fixtures/repos/assets_in_hook/Gemfile +1 -2
  66. data/spec/fixtures/repos/assets_in_hook/Gemfile.lock +1 -3
  67. data/spec/fixtures/repos/assets_in_hook/config/ey.yml +3 -0
  68. data/spec/fixtures/repos/assets_in_hook/deploy/before_compile_assets.rb +1 -1
  69. data/spec/fixtures/repos/bundle_fails/Gemfile +1 -0
  70. data/spec/fixtures/repos/bundle_fails/README +1 -0
  71. data/spec/fixtures/repos/bundle_fails/deploy/after_bundle.rb +1 -0
  72. data/spec/fixtures/repos/default/Gemfile +1 -2
  73. data/spec/fixtures/repos/default/Gemfile.lock +1 -3
  74. data/spec/fixtures/repos/default/ey.yml +3 -0
  75. data/spec/fixtures/repos/ey_yml/Gemfile +1 -1
  76. data/spec/fixtures/repos/ey_yml/Gemfile.lock +1 -1
  77. data/spec/fixtures/repos/ey_yml/config/ey.yml +11 -7
  78. data/spec/fixtures/repos/ey_yml_alt/Gemfile +1 -1
  79. data/spec/fixtures/repos/ey_yml_alt/Gemfile.lock +1 -1
  80. data/spec/fixtures/repos/no_ey_config/Gemfile +1 -2
  81. data/spec/fixtures/repos/no_ey_config/Gemfile.lock +1 -3
  82. data/spec/fixtures/repos/no_ey_config/ey.yml +3 -0
  83. data/spec/fixtures/repos/no_gemfile_lock/Gemfile +1 -2
  84. data/spec/fixtures/repos/no_gemfile_lock/ey.yml +3 -0
  85. data/spec/fixtures/repos/sqlite3/Gemfile +1 -1
  86. data/spec/fixtures/repos/sqlite3/Gemfile.lock +1 -1
  87. data/spec/lockfile_parser_spec.rb +25 -11
  88. data/spec/rails31_deploy_spec.rb +46 -5
  89. data/spec/restart_spec.rb +3 -3
  90. data/spec/services_deploy_spec.rb +89 -86
  91. data/spec/shell_spec.rb +0 -8
  92. data/spec/spec_helper.rb +81 -36
  93. data/spec/sqlite3_deploy_spec.rb +4 -5
  94. data/spec/support/integration.rb +22 -37
  95. metadata +167 -154
  96. data/lib/engineyard-serverside/lockfile_parser.rb +0 -101
  97. data/lib/engineyard-serverside/rails_asset_support.rb +0 -132
  98. data/spec/fixtures/repos/assets_enabled/Rakefile +0 -5
@@ -22,7 +22,6 @@ require 'engineyard-serverside/task'
22
22
  require 'engineyard-serverside/server'
23
23
  require 'engineyard-serverside/deploy'
24
24
  require 'engineyard-serverside/deploy_hook'
25
- require 'engineyard-serverside/lockfile_parser'
26
25
  require 'engineyard-serverside/cli'
27
26
  require 'engineyard-serverside/configuration'
28
27
  require 'engineyard-serverside/deprecation'
@@ -30,8 +30,9 @@ module EY
30
30
 
31
31
  desc "deploy", "Deploy code from /data/<app>"
32
32
  def deploy(default_task=:deploy)
33
- servers, config, shell = init_and_propagate(options, default_task.to_s)
34
- EY::Serverside::Deploy.new(servers, config, shell).send(default_task)
33
+ init_and_propagate(options, default_task.to_s) do |servers, config, shell|
34
+ EY::Serverside::Deploy.new(servers, config, shell).send(default_task)
35
+ end
35
36
  end
36
37
 
37
38
  account_app_env_options
@@ -40,8 +41,9 @@ module EY
40
41
  verbose_option
41
42
  desc "enable_maintenance", "Enable maintenance page (disables web access)"
42
43
  def enable_maintenance
43
- servers, config, shell = init_and_propagate(options, 'enable_maintenance')
44
- EY::Serverside::Maintenance.new(servers, config, shell).manually_enable
44
+ init_and_propagate(options, 'enable_maintenance') do |servers, config, shell|
45
+ EY::Serverside::Maintenance.new(servers, config, shell).manually_enable
46
+ end
45
47
  end
46
48
 
47
49
  account_app_env_options
@@ -50,8 +52,9 @@ module EY
50
52
  verbose_option
51
53
  desc "disable_maintenance", "Disable maintenance page (enables web access)"
52
54
  def disable_maintenance
53
- servers, config, shell = init_and_propagate(options, 'disable_maintenance')
54
- EY::Serverside::Maintenance.new(servers, config, shell).manually_disable
55
+ init_and_propagate(options, 'disable_maintenance') do |servers, config, shell|
56
+ EY::Serverside::Maintenance.new(servers, config, shell).manually_disable
57
+ end
55
58
  end
56
59
 
57
60
  method_option :release_path, :type => :string,
@@ -69,8 +72,9 @@ module EY
69
72
  verbose_option
70
73
  desc "hook [NAME]", "Run a particular deploy hook"
71
74
  def hook(hook_name)
72
- config, shell = init(options, "hook-#{hook_name}")
73
- EY::Serverside::DeployHook.new(config, shell, hook_name).call
75
+ init(options, "hook-#{hook_name}") do |config, shell|
76
+ EY::Serverside::DeployHook.new(config, shell, hook_name).call
77
+ end
74
78
  end
75
79
 
76
80
  account_app_env_options
@@ -91,22 +95,24 @@ module EY
91
95
  # we have to deploy the same SHA there as here
92
96
  integrate_options[:branch] = current_app_dir.join('REVISION').read.strip
93
97
 
94
- servers, config, shell = init_and_propagate(integrate_options, 'integrate')
98
+ init_and_propagate(integrate_options, 'integrate') do |servers, config, shell|
95
99
 
96
- # We have to rsync the entire app dir, so we need all the permissions to be correct!
97
- shell.logged_system "sudo sh -l -c 'find #{app_dir} -not -user #{config.user} -or -not -group #{config.group} -exec chown #{config.user}:#{config.group} {} +'"
100
+ # We have to rsync the entire app dir, so we need all the permissions to be correct!
101
+ rsync_command = "find #{app_dir} -not -user #{config.user} -or -not -group #{config.group} -exec chown #{config.user}:#{config.group} {} +"
102
+ shell.logged_system "sudo sh -l -c '#{rsync_command}'"
98
103
 
99
- servers.each do |server|
100
- shell.logged_system server.sync_directory_command(app_dir)
101
- # we're just about to recreate this, so it has to be gone
102
- # first. otherwise, non-idempotent deploy hooks could screw
103
- # things up, and since we don't control deploy hooks, we must
104
- # assume the worst.
105
- shell.logged_system server.command_on_server('sh -l -c', "rm -rf #{current_app_dir}")
106
- end
104
+ servers.each do |server|
105
+ shell.logged_system server.sync_directory_command(app_dir)
106
+ # we're just about to recreate this, so it has to be gone
107
+ # first. otherwise, non-idempotent deploy hooks could screw
108
+ # things up, and since we don't control deploy hooks, we must
109
+ # assume the worst.
110
+ shell.logged_system server.command_on_server('sh -l -c', "rm -rf #{current_app_dir}")
111
+ end
107
112
 
108
- # deploy local-ref to other instances into /data/$app/local-current
109
- EY::Serverside::Deploy.new(servers, config, shell).cached_deploy
113
+ # deploy local-ref to other instances into /data/$app/local-current
114
+ EY::Serverside::Deploy.new(servers, config, shell).cached_deploy
115
+ end
110
116
  end
111
117
 
112
118
  account_app_env_options
@@ -115,32 +121,19 @@ module EY
115
121
  verbose_option
116
122
  desc "restart", "Restart app servers, conditionally enabling maintenance page"
117
123
  def restart
118
- servers, config, shell = init_and_propagate(options, 'restart')
119
- EY::Serverside::Deploy.new(servers, config, shell).restart_with_maintenance_page
120
- end
121
-
122
- desc "install_bundler [VERSION]", "Make sure VERSION of bundler is installed (in system ruby)"
123
- def install_bundler(version)
124
- egrep_escaped_version = version.gsub(/\./, '\.')
125
- # the grep "bundler " is so that gems like bundler08 don't get
126
- # their versions considered too
127
- #
128
- # the [,$] is to stop us from looking for e.g. 0.9.2, seeing
129
- # 0.9.22, and mistakenly thinking 0.9.2 is there
130
- has_bundler_cmd = "gem list bundler | grep \"bundler \" | egrep -q '#{egrep_escaped_version}[,)]'"
131
-
132
- unless system(has_bundler_cmd)
133
- system("gem install bundler -q --no-rdoc --no-ri -v '#{version}'")
124
+ init_and_propagate(options, 'restart') do |servers, config, shell|
125
+ EY::Serverside::Deploy.new(servers, config, shell).restart_with_maintenance_page
134
126
  end
135
127
  end
136
128
 
137
129
  private
138
130
 
139
131
  def init_and_propagate(*args)
140
- config, shell = init(*args)
141
- servers = load_servers(config)
142
- Propagator.call(servers, config, shell)
143
- [servers, config, shell]
132
+ init(*args) do |config, shell|
133
+ servers = load_servers(config)
134
+ Propagator.call(servers, config, shell)
135
+ yield servers, config, shell
136
+ end
144
137
  end
145
138
 
146
139
  def init(options, action)
@@ -150,7 +143,15 @@ module EY
150
143
  :log_path => File.join(ENV['HOME'], "#{config.app}-#{action}.log")
151
144
  )
152
145
  shell.debug "Initializing #{About.name_with_version}."
153
- [config, shell]
146
+ begin
147
+ yield config, shell
148
+ rescue EY::Serverside::RemoteFailure => e
149
+ shell.exception "#{e.message}"
150
+ raise
151
+ rescue Exception => e
152
+ shell.exception "#{e.backtrace[0]}: #{e.message} (#{e.class})"
153
+ raise
154
+ end
154
155
  end
155
156
 
156
157
  def load_servers(config)
@@ -166,6 +167,7 @@ module EY
166
167
  }
167
168
  }
168
169
  end
170
+
169
171
  end
170
172
  end
171
173
  end
@@ -1,6 +1,7 @@
1
1
  require 'multi_json'
2
2
  require 'thor'
3
3
  require 'pp'
4
+ require 'yaml'
4
5
  require 'engineyard-serverside/paths'
5
6
 
6
7
  module EY
@@ -56,7 +57,10 @@ module EY
56
57
 
57
58
  def_option :repo, nil
58
59
  def_option :migrate, nil
59
- def_option :precompile_assets, nil
60
+ def_option :precompile_assets, 'detect'
61
+ def_option :precompile_assets_task, 'assets:precompile'
62
+ def_option :asset_strategy, 'shifting'
63
+ def_option :asset_dependencies, %w[app/assets lib/assets vendor/assets Gemfile.lock config/routes.rb]
60
64
  def_option :stack, nil
61
65
  def_option :strategy, 'Git'
62
66
  def_option :branch, 'master'
@@ -64,11 +68,15 @@ module EY
64
68
  def_option :current_name, nil
65
69
  def_option :asset_roles, [:app_master, :app, :solo]
66
70
  def_option :copy_exclude, []
67
- def_option(:bundle_without) { (%w[test development] - [framework_env]).join(' ') }
71
+ def_option :bundle_options, nil
72
+ def_option(:bundle_without) { %w[test development] - [framework_env] }
68
73
  def_option(:user) { ENV['USER'] }
69
74
  def_option(:group) { user }
75
+ def_option :services_check_command, "which /usr/local/ey_resin/ruby/bin/ey-services-setup >/dev/null 2>&1"
76
+ def_option(:services_setup_command) { "/usr/local/ey_resin/ruby/bin/ey-services-setup #{app}" }
70
77
 
71
78
  def_boolean_option :verbose, false
79
+ def_boolean_option :precompile_unchanged_assets, false
72
80
  def_boolean_option :ignore_database_adapter_warning, false
73
81
  def_boolean_option :maintenance_on_migrate, true
74
82
  def_boolean_option(:maintenance_on_restart) { required_downtime_stack? }
@@ -106,6 +114,8 @@ module EY
106
114
  end
107
115
 
108
116
  def load_ey_yml_data(data, shell)
117
+ loaded = false
118
+
109
119
  environments = data['environments']
110
120
  if environments && environments[environment_name]
111
121
  shell.substatus "ey.yml configuration loaded for environment #{environment_name.inspect}."
@@ -113,7 +123,19 @@ module EY
113
123
  env_data = string_keys(environments[environment_name])
114
124
  shell.debug "#{environment_name}:\n#{env_data.pretty_inspect}"
115
125
 
116
- append_config_source(string_keys(env_data)) # insert at lowest priority so as not to disturb important config
126
+ append_config_source(env_data) # insert at higher priority than defaults
127
+ loaded = true
128
+ end
129
+
130
+ defaults = data['defaults']
131
+ if defaults
132
+ shell.substatus "ey.yml configuration loaded."
133
+ append_config_source(string_keys(defaults)) # insert at lowest priority so as not to disturb important config
134
+ shell.debug "defaults:\n#{defaults.pretty_inspect}"
135
+ loaded = true
136
+ end
137
+
138
+ if loaded
117
139
  true
118
140
  else
119
141
  shell.info "No matching ey.yml configuration found for environment #{environment_name.inspect}."
@@ -198,6 +220,22 @@ module EY
198
220
  end
199
221
  alias revision latest_revision
200
222
 
223
+ def previous_revision
224
+ prev = paths.previous_revision
225
+ prev && prev.readable? && prev.read.strip
226
+ end
227
+
228
+ # The nodatabase.yml file is dropped by server configuration when there is
229
+ # no database in the cluster.
230
+ def has_database?
231
+ paths.shared_config.join('database.yml').exist? &&
232
+ !paths.shared_config.join('nodatabase.yml').exist?
233
+ end
234
+
235
+ def check_database_adapter?
236
+ !ignore_database_adapter_warning? && has_database?
237
+ end
238
+
201
239
  def migrate?
202
240
  !!migration_command
203
241
  end
@@ -222,8 +260,15 @@ module EY
222
260
  framework_env_names.each { |e| ENV[e] = environment }
223
261
  end
224
262
 
263
+ def extra_bundle_install_options
264
+ opts = []
265
+ opts += ["--without", bundle_without] if bundle_without
266
+ opts += [bundle_options] if bundle_options
267
+ opts.flatten
268
+ end
269
+
225
270
  def precompile_assets_inferred?
226
- !precompile_assets? && !skip_precompile_assets?
271
+ precompile_assets.nil? || precompile_assets == "detect"
227
272
  end
228
273
 
229
274
  def precompile_assets?
@@ -249,6 +294,12 @@ module EY
249
294
  enable_maintenance_page?
250
295
  end
251
296
 
297
+ def configured_services
298
+ services = YAML.load_file(paths.shared_services_yml.to_s)
299
+ services.respond_to?(:keys) && !services.empty? ? services.keys : nil
300
+ rescue
301
+ nil
302
+ end
252
303
  end
253
304
  end
254
305
  end
@@ -0,0 +1,17 @@
1
+ require 'engineyard-serverside/dependency_manager/base'
2
+ require 'engineyard-serverside/dependency_manager/bundler'
3
+ require 'engineyard-serverside/dependency_manager/bundler_lock'
4
+ require 'engineyard-serverside/dependency_manager/npm'
5
+
6
+ module EY
7
+ module Serverside
8
+ module DependencyManager
9
+ def self.detect(servers, config, shell, runner)
10
+ Bundler.detect(servers, config, shell, runner) ||
11
+ BundlerLock.detect(servers, config, shell, runner) ||
12
+ Npm.detect(servers, config, shell, runner) ||
13
+ Base.new(servers, config, shell, runner)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,65 @@
1
+ module EY
2
+ module Serverside
3
+ module DependencyManager
4
+ class Base
5
+ def self.detect(servers, config, shell, runner)
6
+ manager = new(servers, config, shell, runner)
7
+ manager.detected? && manager
8
+ end
9
+
10
+ attr_reader :servers, :config, :shell, :runner
11
+
12
+ def initialize(servers, config, shell, runner)
13
+ @servers, @config, @shell = servers, config, shell
14
+ @runner = runner
15
+ end
16
+
17
+ # Public interface
18
+ #
19
+
20
+ def detected?() true end
21
+ def check() end
22
+ def install() end
23
+
24
+ # assume not using sqlite3 unless a dependency system says so
25
+ def uses_sqlite3?() false end
26
+ def rails_version() end
27
+ def check_ey_config() end
28
+
29
+ # Legacy methods, this should not be public API to this class
30
+ # With proper warning, cut these methods off
31
+ def gemfile?() end
32
+ def bundler_config
33
+ raise "This method has been removed. Use bundle_options in ey.yml"
34
+ end
35
+ def lockfile() end
36
+ def check_ruby_bundler() end
37
+ def check_node_npm() end
38
+ def clean_bundle_on_system_version_change() end
39
+ def write_system_version() end
40
+
41
+ protected
42
+
43
+ def paths
44
+ config.paths
45
+ end
46
+
47
+ def on_roles
48
+ [:app_master, :app, :solo, :util]
49
+ end
50
+
51
+ def run(cmd)
52
+ runner.roles(on_roles) do
53
+ runner.run(cmd)
54
+ end
55
+ end
56
+
57
+ def sudo(cmd)
58
+ runner.roles(on_roles) do
59
+ runner.sudo(cmd)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,124 @@
1
+ module EY
2
+ module Serverside
3
+ module DependencyManager
4
+ class Bundler < Base
5
+ DEFAULT_VERSION = "1.3.4"
6
+
7
+ def self.default_version
8
+ DEFAULT_VERSION
9
+ end
10
+
11
+ def detected?
12
+ gemfile? && !lockfile?
13
+ end
14
+
15
+ def gemfile?
16
+ paths.gemfile.exist?
17
+ end
18
+
19
+ def lockfile?
20
+ lockfile_path.exist?
21
+ end
22
+
23
+ def check
24
+ shell.warning <<-WARN
25
+ Gemfile found but Gemfile.lock is missing!
26
+ You can get different versions of gems in production than what you tested with.
27
+ You can get different versions of gems on every deployment even if your Gemfile hasn't changed.
28
+ Deploying will take longer and some deploy options will be limited.
29
+
30
+ To fix this problem, commit your Gemfile.lock to your repository and redeploy.
31
+ WARN
32
+ end
33
+
34
+ def install
35
+ check_ruby_bundler
36
+ end
37
+
38
+ # Without Gemfile.lock, don't do anything with sqlite3
39
+ def uses_sqlite3?
40
+ false
41
+ end
42
+
43
+ # Without Gemfile.lock, don't do anything about ey_config
44
+ def check_ey_config
45
+ end
46
+
47
+ # Without Gemfile.lock, there is no determining the rails version.
48
+ def rails_version
49
+ nil
50
+ end
51
+
52
+ private
53
+
54
+ def lockfile_path
55
+ paths.gemfile_lock
56
+ end
57
+
58
+ def write_system_version
59
+ store_ruby_version = "#{config.ruby_version_command} > #{paths.ruby_version}"
60
+ store_system_version = "#{config.system_version_command} > #{paths.system_version}"
61
+
62
+ run "mkdir -p #{paths.bundled_gems} && chown #{config.user}:#{config.group} #{paths.bundled_gems}"
63
+ run "#{store_ruby_version} && #{store_system_version}"
64
+ end
65
+
66
+ def check_ruby_bundler
67
+ shell.status "Bundling gems..."
68
+ clean_bundle_on_system_version_change
69
+ install_bundler_gem
70
+ run "#{clean_environment} && cd #{paths.active_release} && #{bundle_install_command}"
71
+ write_system_version
72
+ end
73
+
74
+ # Install bundler in the system ruby
75
+ def install_bundler_gem
76
+ egrep_escaped_version = bundler_version.gsub(/\./, '\.')
77
+ # the grep "bundler " is so that gems like bundler08 don't get
78
+ # their versions considered too
79
+ #
80
+ # the [,)] is to stop us from looking for e.g. 0.9.2, seeing
81
+ # 0.9.22, and mistakenly thinking 0.9.2 is there
82
+ clean_ruby = %{unset RUBYOPT}
83
+ has_gem_cmd = %{gem list bundler | grep "bundler " | egrep -q "#{egrep_escaped_version}[,)]"}
84
+ install_cmd = %{gem install bundler -q --no-rdoc --no-ri -v "#{bundler_version}"}
85
+ sudo "#{clean_ruby} && #{has_gem_cmd} || #{install_cmd}"
86
+ end
87
+
88
+ # GIT_SSH needs to be defined in the environment for customers with private bundler repos in their Gemfile.
89
+ # It seems redundant to declare the env var again, but I'm hesitant to remove it right now.
90
+ def clean_environment
91
+ %{export GIT_SSH="#{ENV['GIT_SSH']}" && export LANG="en_US.UTF-8" && unset RUBYOPT BUNDLE_PATH BUNDLE_FROZEN BUNDLE_WITHOUT BUNDLE_BIN BUNDLE_GEMFILE}
92
+ end
93
+
94
+ def bundle_install_options
95
+ options = [
96
+ "--gemfile", "#{paths.gemfile}",
97
+ "--path", "#{paths.bundled_gems}",
98
+ "--binstubs", "#{paths.binstubs}",
99
+ ]
100
+ options += config.extra_bundle_install_options
101
+ options
102
+ end
103
+
104
+ def bundle_install_command
105
+ "ruby -S bundle _#{bundler_version}_ install #{bundle_install_options.join(" ")}"
106
+ end
107
+
108
+ def clean_bundle_on_system_version_change
109
+ # diff exits with 0 for same and 1/2 for different/file not found.
110
+ check_ruby = "#{config.ruby_version_command} | diff - #{paths.ruby_version} >/dev/null 2>&1"
111
+ check_system = "#{config.system_version_command} | diff - #{paths.system_version} >/dev/null 2>&1"
112
+ clean_bundle = "rm -Rf #{paths.bundled_gems}"
113
+
114
+ shell.substatus "Checking for system version changes"
115
+ run "#{check_ruby} && #{check_system} || #{clean_bundle}"
116
+ end
117
+
118
+ def bundler_version
119
+ self.class.default_version
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end