heroku_hatchet 1.3.7 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/CHANGELOG.md +5 -0
- data/hatchet.gemspec +2 -0
- data/hatchet.json +2 -1
- data/lib/hatchet.rb +1 -1
- data/lib/hatchet/app.rb +4 -3
- data/lib/hatchet/version.rb +1 -1
- data/test/hatchet/allow_failure_anvil_test.rb +0 -29
- data/test/hatchet/anvil_test.rb +0 -16
- data/test/hatchet/app_test.rb +9 -0
- data/test/hatchet/config_test.rb +9 -6
- data/test/hatchet/edit_repo_test.rb +3 -3
- data/test/hatchet/heroku_api_test.rb +7 -2
- data/test/hatchet/multi_cmd_runner_test.rb +2 -6
- data/test/hatchet/runner_test.rb +2 -2
- metadata +33 -65
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/.gitignore +0 -4
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/CHANGELOG.md +0 -378
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/Gemfile +0 -10
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/LICENSE +0 -9
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/README.md +0 -192
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/Rakefile +0 -358
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/bin/compile +0 -13
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/bin/detect +0 -12
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/bin/release +0 -9
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/hatchet.json +0 -25
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/lib/language_pack.rb +0 -27
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/lib/language_pack/base.rb +0 -175
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/lib/language_pack/bundler_lockfile.rb +0 -19
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/lib/language_pack/disable_deploys.rb +0 -17
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/lib/language_pack/no_lockfile.rb +0 -16
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/lib/language_pack/rack.rb +0 -43
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/lib/language_pack/rails2.rb +0 -91
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/lib/language_pack/rails3.rb +0 -86
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/lib/language_pack/rails4.rb +0 -66
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/lib/language_pack/ruby.rb +0 -681
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/lib/language_pack/shell_helpers.rb +0 -62
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/spec/bugs_spec.rb +0 -11
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/spec/no_lockfile_spec.rb +0 -10
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/spec/rails23_spec.rb +0 -11
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/spec/rails3_spec.rb +0 -22
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/spec/rails4_spec.rb +0 -12
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/spec/rubies_spec.rb +0 -38
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/spec/spec_helper.rb +0 -35
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/support/s3/hmac +0 -79
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/support/s3/s3 +0 -223
- data/test/fixtures/buildpacks/heroku-buildpack-ruby/vendor/syck_hack.rb +0 -64
@@ -1,86 +0,0 @@
|
|
1
|
-
require "language_pack"
|
2
|
-
require "language_pack/rails2"
|
3
|
-
|
4
|
-
# Rails 3 Language Pack. This is for all Rails 3.x apps.
|
5
|
-
class LanguagePack::Rails3 < LanguagePack::Rails2
|
6
|
-
# detects if this is a Rails 3.x app
|
7
|
-
# @return [Boolean] true if it's a Rails 3.x app
|
8
|
-
def self.use?
|
9
|
-
if gemfile_lock?
|
10
|
-
rails_version = LanguagePack::Ruby.gem_version('railties')
|
11
|
-
rails_version >= Gem::Version.new('3.0.0') && rails_version < Gem::Version.new('4.0.0') if rails_version
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def name
|
16
|
-
"Ruby/Rails"
|
17
|
-
end
|
18
|
-
|
19
|
-
def default_process_types
|
20
|
-
# let's special case thin here
|
21
|
-
web_process = gem_is_bundled?("thin") ?
|
22
|
-
"bundle exec thin start -R config.ru -e $RAILS_ENV -p $PORT" :
|
23
|
-
"bundle exec rails server -p $PORT"
|
24
|
-
|
25
|
-
super.merge({
|
26
|
-
"web" => web_process,
|
27
|
-
"console" => "bundle exec rails console"
|
28
|
-
})
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def plugins
|
34
|
-
super.concat(%w( rails3_serve_static_assets )).uniq
|
35
|
-
end
|
36
|
-
|
37
|
-
# runs the tasks for the Rails 3.1 asset pipeline
|
38
|
-
def run_assets_precompile_rake_task
|
39
|
-
log("assets_precompile") do
|
40
|
-
setup_database_url_env
|
41
|
-
|
42
|
-
if rake_task_defined?("assets:precompile")
|
43
|
-
topic("Preparing app for Rails asset pipeline")
|
44
|
-
if File.exists?("public/assets/manifest.yml")
|
45
|
-
puts "Detected manifest.yml, assuming assets were compiled locally"
|
46
|
-
else
|
47
|
-
ENV["RAILS_GROUPS"] ||= "assets"
|
48
|
-
ENV["RAILS_ENV"] ||= "production"
|
49
|
-
|
50
|
-
puts "Running: rake assets:precompile"
|
51
|
-
require 'benchmark'
|
52
|
-
time = Benchmark.realtime { pipe("env PATH=$PATH:bin bundle exec rake assets:precompile 2>&1") }
|
53
|
-
|
54
|
-
if $?.success?
|
55
|
-
log "assets_precompile", :status => "success"
|
56
|
-
puts "Asset precompilation completed (#{"%.2f" % time}s)"
|
57
|
-
else
|
58
|
-
log "assets_precompile", :status => "failure"
|
59
|
-
puts "Precompiling assets failed, enabling runtime asset compilation"
|
60
|
-
install_plugin("rails31_enable_runtime_asset_compilation")
|
61
|
-
puts "Please see this article for troubleshooting help:"
|
62
|
-
puts "http://devcenter.heroku.com/articles/rails31_heroku_cedar#troubleshooting"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# setup the database url as an environment variable
|
70
|
-
def setup_database_url_env
|
71
|
-
ENV["DATABASE_URL"] ||= begin
|
72
|
-
# need to use a dummy DATABASE_URL here, so rails can load the environment
|
73
|
-
scheme =
|
74
|
-
if gem_is_bundled?("pg")
|
75
|
-
"postgres"
|
76
|
-
elsif gem_is_bundled?("mysql")
|
77
|
-
"mysql"
|
78
|
-
elsif gem_is_bundled?("mysql2")
|
79
|
-
"mysql2"
|
80
|
-
elsif gem_is_bundled?("sqlite3") || gem_is_bundled?("sqlite3-ruby")
|
81
|
-
"sqlite3"
|
82
|
-
end
|
83
|
-
"#{scheme}://user:pass@127.0.0.1/dbname"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require "language_pack"
|
2
|
-
require "language_pack/rails3"
|
3
|
-
|
4
|
-
# Rails 4 Language Pack. This is for all Rails 4.x apps.
|
5
|
-
class LanguagePack::Rails4 < LanguagePack::Rails3
|
6
|
-
# detects if this is a Rails 3.x app
|
7
|
-
# @return [Boolean] true if it's a Rails 3.x app
|
8
|
-
def self.use?
|
9
|
-
if gemfile_lock?
|
10
|
-
rails_version = LanguagePack::Ruby.gem_version('railties')
|
11
|
-
rails_version >= Gem::Version.new('4.0.0.beta') && rails_version < Gem::Version.new('5.0.0') if rails_version
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def name
|
16
|
-
"Ruby/Rails"
|
17
|
-
end
|
18
|
-
|
19
|
-
def default_process_types
|
20
|
-
web_process = gem_is_bundled?("thin") ?
|
21
|
-
"bin/rails server thin -p $PORT -e $RAILS_ENV" :
|
22
|
-
"bin/rails server -p $PORT -e $RAILS_ENV"
|
23
|
-
super.merge({
|
24
|
-
"web" => web_process,
|
25
|
-
"console" => "bin/rails console"
|
26
|
-
})
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
def plugins
|
31
|
-
[]
|
32
|
-
end
|
33
|
-
|
34
|
-
def run_assets_precompile_rake_task
|
35
|
-
log("assets_precompile") do
|
36
|
-
setup_database_url_env
|
37
|
-
|
38
|
-
if rake_task_defined?("assets:precompile")
|
39
|
-
topic("Preparing app for Rails asset pipeline")
|
40
|
-
if Dir.glob('public/assets/manifest-*.json').any?
|
41
|
-
puts "Detected manifest file, assuming assets were compiled locally"
|
42
|
-
else
|
43
|
-
ENV["RAILS_GROUPS"] ||= "assets"
|
44
|
-
ENV["RAILS_ENV"] ||= "production"
|
45
|
-
|
46
|
-
puts "Running: rake assets:precompile"
|
47
|
-
require 'benchmark'
|
48
|
-
time = Benchmark.realtime { pipe("env PATH=$PATH:bin bundle exec rake assets:precompile 2>&1") }
|
49
|
-
|
50
|
-
if $?.success?
|
51
|
-
log "assets_precompile", :status => "success"
|
52
|
-
puts "Asset precompilation completed (#{"%.2f" % time}s)"
|
53
|
-
else
|
54
|
-
log "assets_precompile", :status => "failure"
|
55
|
-
error "Precompiling assets failed."
|
56
|
-
end
|
57
|
-
end
|
58
|
-
else
|
59
|
-
puts "Error detecting the assets:precompile task"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def create_database_yml
|
65
|
-
end
|
66
|
-
end
|
@@ -1,681 +0,0 @@
|
|
1
|
-
require "tmpdir"
|
2
|
-
require "rubygems"
|
3
|
-
require "language_pack"
|
4
|
-
require "language_pack/base"
|
5
|
-
require "language_pack/bundler_lockfile"
|
6
|
-
|
7
|
-
# base Ruby Language Pack. This is for any base ruby app.
|
8
|
-
class LanguagePack::Ruby < LanguagePack::Base
|
9
|
-
include LanguagePack::BundlerLockfile
|
10
|
-
extend LanguagePack::BundlerLockfile
|
11
|
-
|
12
|
-
BUILDPACK_VERSION = "v61"
|
13
|
-
LIBYAML_VERSION = "0.1.4"
|
14
|
-
LIBYAML_PATH = "libyaml-#{LIBYAML_VERSION}"
|
15
|
-
BUNDLER_VERSION = "1.3.2"
|
16
|
-
BUNDLER_GEM_PATH = "bundler-#{BUNDLER_VERSION}"
|
17
|
-
NODE_VERSION = "0.4.7"
|
18
|
-
NODE_JS_BINARY_PATH = "node-#{NODE_VERSION}"
|
19
|
-
JVM_BASE_URL = "http://heroku-jdk.s3.amazonaws.com"
|
20
|
-
JVM_VERSION = "openjdk7-latest"
|
21
|
-
|
22
|
-
# detects if this is a valid Ruby app
|
23
|
-
# @return [Boolean] true if it's a Ruby app
|
24
|
-
def self.use?
|
25
|
-
File.exist?("Gemfile")
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.lockfile_parser
|
29
|
-
require "bundler"
|
30
|
-
Bundler::LockfileParser.new(File.read("Gemfile.lock"))
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.gem_version(name)
|
34
|
-
gem_version = nil
|
35
|
-
bootstrap_bundler do |bundler_path|
|
36
|
-
$: << "#{bundler_path}/gems/bundler-#{LanguagePack::Ruby::BUNDLER_VERSION}/lib"
|
37
|
-
gem = lockfile_parser.specs.detect {|gem| gem.name == name }
|
38
|
-
gem_version = gem.version if gem
|
39
|
-
end
|
40
|
-
|
41
|
-
gem_version
|
42
|
-
end
|
43
|
-
|
44
|
-
def name
|
45
|
-
"Ruby"
|
46
|
-
end
|
47
|
-
|
48
|
-
def default_addons
|
49
|
-
add_dev_database_addon
|
50
|
-
end
|
51
|
-
|
52
|
-
def default_config_vars
|
53
|
-
vars = {
|
54
|
-
"LANG" => "en_US.UTF-8",
|
55
|
-
"PATH" => default_path,
|
56
|
-
"GEM_PATH" => slug_vendor_base,
|
57
|
-
}
|
58
|
-
|
59
|
-
ruby_version_jruby? ? vars.merge({
|
60
|
-
"JAVA_OPTS" => default_java_opts,
|
61
|
-
"JRUBY_OPTS" => default_jruby_opts,
|
62
|
-
"JAVA_TOOL_OPTIONS" => default_java_tool_options
|
63
|
-
}) : vars
|
64
|
-
end
|
65
|
-
|
66
|
-
def default_process_types
|
67
|
-
{
|
68
|
-
"rake" => "bundle exec rake",
|
69
|
-
"console" => "bundle exec irb"
|
70
|
-
}
|
71
|
-
end
|
72
|
-
|
73
|
-
def compile
|
74
|
-
Dir.chdir(build_path)
|
75
|
-
remove_vendor_bundle
|
76
|
-
install_ruby
|
77
|
-
install_jvm
|
78
|
-
setup_language_pack_environment
|
79
|
-
setup_profiled
|
80
|
-
allow_git do
|
81
|
-
install_language_pack_gems
|
82
|
-
build_bundler
|
83
|
-
create_database_yml
|
84
|
-
install_binaries
|
85
|
-
run_assets_precompile_rake_task
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
private
|
90
|
-
|
91
|
-
# the base PATH environment variable to be used
|
92
|
-
# @return [String] the resulting PATH
|
93
|
-
def default_path
|
94
|
-
"bin:#{slug_vendor_base}/bin:/usr/local/bin:/usr/bin:/bin"
|
95
|
-
end
|
96
|
-
|
97
|
-
# the relative path to the bundler directory of gems
|
98
|
-
# @return [String] resulting path
|
99
|
-
def slug_vendor_base
|
100
|
-
if @slug_vendor_base
|
101
|
-
@slug_vendor_base
|
102
|
-
elsif @ruby_version == "ruby-1.8.7"
|
103
|
-
@slug_vendor_base = "vendor/bundle/1.8"
|
104
|
-
else
|
105
|
-
@slug_vendor_base = run(%q(ruby -e "require 'rbconfig';puts \"vendor/bundle/#{RUBY_ENGINE}/#{RbConfig::CONFIG['ruby_version']}\"")).chomp
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# the relative path to the vendored ruby directory
|
110
|
-
# @return [String] resulting path
|
111
|
-
def slug_vendor_ruby
|
112
|
-
"vendor/#{ruby_version}"
|
113
|
-
end
|
114
|
-
|
115
|
-
# the relative path to the vendored jvm
|
116
|
-
# @return [String] resulting path
|
117
|
-
def slug_vendor_jvm
|
118
|
-
"vendor/jvm"
|
119
|
-
end
|
120
|
-
|
121
|
-
# the absolute path of the build ruby to use during the buildpack
|
122
|
-
# @return [String] resulting path
|
123
|
-
def build_ruby_path
|
124
|
-
"/tmp/#{ruby_version}"
|
125
|
-
end
|
126
|
-
|
127
|
-
# fetch the ruby version from bundler
|
128
|
-
# @return [String, nil] returns the ruby version if detected or nil if none is detected
|
129
|
-
def ruby_version
|
130
|
-
return @ruby_version if @ruby_version_run
|
131
|
-
|
132
|
-
@ruby_version_run = true
|
133
|
-
|
134
|
-
bootstrap_bundler do |bundler_path|
|
135
|
-
old_system_path = "/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin"
|
136
|
-
@ruby_version = run_stdout("env PATH=#{old_system_path}:#{bundler_path}/bin GEM_PATH=#{bundler_path} bundle platform --ruby").chomp
|
137
|
-
end
|
138
|
-
|
139
|
-
if @ruby_version == "No ruby version specified" && ENV['RUBY_VERSION']
|
140
|
-
# for backwards compatibility.
|
141
|
-
# this will go away in the future
|
142
|
-
@ruby_version = ENV['RUBY_VERSION']
|
143
|
-
@ruby_version_env_var = true
|
144
|
-
elsif @ruby_version == "No ruby version specified"
|
145
|
-
@ruby_version = nil
|
146
|
-
else
|
147
|
-
@ruby_version = @ruby_version.sub('(', '').sub(')', '').split.join('-')
|
148
|
-
@ruby_version_env_var = false
|
149
|
-
end
|
150
|
-
|
151
|
-
@ruby_version
|
152
|
-
end
|
153
|
-
|
154
|
-
# determine if we're using rbx
|
155
|
-
# @return [Boolean] true if we are and false if we aren't
|
156
|
-
def ruby_version_rbx?
|
157
|
-
ruby_version ? ruby_version.match(/rbx-/) : false
|
158
|
-
end
|
159
|
-
|
160
|
-
# determine if we're using jruby
|
161
|
-
# @return [Boolean] true if we are and false if we aren't
|
162
|
-
def ruby_version_jruby?
|
163
|
-
@ruby_version_jruby ||= ruby_version ? ruby_version.match(/jruby-/) : false
|
164
|
-
end
|
165
|
-
|
166
|
-
# default JAVA_OPTS
|
167
|
-
# return [String] string of JAVA_OPTS
|
168
|
-
def default_java_opts
|
169
|
-
"-Xmx384m -Xss512k -XX:+UseCompressedOops -Dfile.encoding=UTF-8"
|
170
|
-
end
|
171
|
-
|
172
|
-
# default JRUBY_OPTS
|
173
|
-
# return [String] string of JRUBY_OPTS
|
174
|
-
def default_jruby_opts
|
175
|
-
"-Xcompile.invokedynamic=true"
|
176
|
-
end
|
177
|
-
|
178
|
-
# default JAVA_TOOL_OPTIONS
|
179
|
-
# return [String] string of JAVA_TOOL_OPTIONS
|
180
|
-
def default_java_tool_options
|
181
|
-
"-Djava.rmi.server.useCodebaseOnly=true"
|
182
|
-
end
|
183
|
-
|
184
|
-
# list the available valid ruby versions
|
185
|
-
# @note the value is memoized
|
186
|
-
# @return [Array] list of Strings of the ruby versions available
|
187
|
-
def ruby_versions
|
188
|
-
return @ruby_versions if @ruby_versions
|
189
|
-
|
190
|
-
Dir.mktmpdir("ruby_versions-") do |tmpdir|
|
191
|
-
Dir.chdir(tmpdir) do
|
192
|
-
run("curl -O #{VENDOR_URL}/ruby_versions.yml")
|
193
|
-
@ruby_versions = YAML::load_file("ruby_versions.yml")
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
@ruby_versions
|
198
|
-
end
|
199
|
-
|
200
|
-
# sets up the environment variables for the build process
|
201
|
-
def setup_language_pack_environment
|
202
|
-
setup_ruby_install_env
|
203
|
-
|
204
|
-
config_vars = default_config_vars.each do |key, value|
|
205
|
-
ENV[key] ||= value
|
206
|
-
end
|
207
|
-
ENV["GEM_HOME"] = slug_vendor_base
|
208
|
-
ENV["PATH"] = "#{ruby_install_binstub_path}:#{config_vars["PATH"]}"
|
209
|
-
end
|
210
|
-
|
211
|
-
# sets up the profile.d script for this buildpack
|
212
|
-
def setup_profiled
|
213
|
-
set_env_override "GEM_PATH", "$HOME/#{slug_vendor_base}:$GEM_PATH"
|
214
|
-
set_env_default "LANG", "en_US.UTF-8"
|
215
|
-
set_env_override "PATH", "$HOME/bin:$HOME/#{slug_vendor_base}/bin:$PATH"
|
216
|
-
|
217
|
-
if ruby_version_jruby?
|
218
|
-
set_env_default "JAVA_OPTS", default_java_opts
|
219
|
-
set_env_default "JRUBY_OPTS", default_jruby_opts
|
220
|
-
set_env_default "JAVA_TOOL_OPTIONS", default_java_tool_options
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
# determines if a build ruby is required
|
225
|
-
# @return [Boolean] true if a build ruby is required
|
226
|
-
def build_ruby?
|
227
|
-
@build_ruby ||= !ruby_version_rbx? && !ruby_version_jruby? && !%w{ruby-1.9.3 ruby-2.0.0}.include?(ruby_version)
|
228
|
-
end
|
229
|
-
|
230
|
-
# install the vendored ruby
|
231
|
-
# @return [Boolean] true if it installs the vendored ruby and false otherwise
|
232
|
-
def install_ruby
|
233
|
-
return false unless ruby_version
|
234
|
-
|
235
|
-
invalid_ruby_version_message = <<ERROR
|
236
|
-
Invalid RUBY_VERSION specified: #{ruby_version}
|
237
|
-
Valid versions: #{ruby_versions.join(", ")}
|
238
|
-
ERROR
|
239
|
-
|
240
|
-
if build_ruby?
|
241
|
-
FileUtils.mkdir_p(build_ruby_path)
|
242
|
-
Dir.chdir(build_ruby_path) do
|
243
|
-
ruby_vm = ruby_version_rbx? ? "rbx" : "ruby"
|
244
|
-
run("curl #{VENDOR_URL}/#{ruby_version.sub(ruby_vm, "#{ruby_vm}-build")}.tgz -s -o - | tar zxf -")
|
245
|
-
end
|
246
|
-
error invalid_ruby_version_message unless $?.success?
|
247
|
-
end
|
248
|
-
|
249
|
-
FileUtils.mkdir_p(slug_vendor_ruby)
|
250
|
-
Dir.chdir(slug_vendor_ruby) do
|
251
|
-
run("curl #{VENDOR_URL}/#{ruby_version}.tgz -s -o - | tar zxf -")
|
252
|
-
end
|
253
|
-
error invalid_ruby_version_message unless $?.success?
|
254
|
-
|
255
|
-
bin_dir = "bin"
|
256
|
-
FileUtils.mkdir_p bin_dir
|
257
|
-
Dir["#{slug_vendor_ruby}/bin/*"].each do |bin|
|
258
|
-
run("ln -s ../#{bin} #{bin_dir}")
|
259
|
-
end
|
260
|
-
|
261
|
-
if !@ruby_version_env_var
|
262
|
-
topic "Using Ruby version: #{ruby_version}"
|
263
|
-
else
|
264
|
-
topic "Using RUBY_VERSION: #{ruby_version}"
|
265
|
-
puts "WARNING: RUBY_VERSION support has been deprecated and will be removed entirely on August 1, 2012."
|
266
|
-
puts "See https://devcenter.heroku.com/articles/ruby-versions#selecting_a_version_of_ruby for more information."
|
267
|
-
end
|
268
|
-
|
269
|
-
true
|
270
|
-
end
|
271
|
-
|
272
|
-
# vendors JVM into the slug for JRuby
|
273
|
-
def install_jvm
|
274
|
-
if ruby_version_jruby?
|
275
|
-
topic "Installing JVM: #{JVM_VERSION}"
|
276
|
-
|
277
|
-
FileUtils.mkdir_p(slug_vendor_jvm)
|
278
|
-
Dir.chdir(slug_vendor_jvm) do
|
279
|
-
run("curl #{JVM_BASE_URL}/#{JVM_VERSION}.tar.gz -s -o - | tar xzf -")
|
280
|
-
end
|
281
|
-
|
282
|
-
bin_dir = "bin"
|
283
|
-
FileUtils.mkdir_p bin_dir
|
284
|
-
Dir["#{slug_vendor_jvm}/bin/*"].each do |bin|
|
285
|
-
run("ln -s ../#{bin} #{bin_dir}")
|
286
|
-
end
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
# find the ruby install path for its binstubs during build
|
291
|
-
# @return [String] resulting path or empty string if ruby is not vendored
|
292
|
-
def ruby_install_binstub_path
|
293
|
-
@ruby_install_binstub_path ||=
|
294
|
-
if build_ruby?
|
295
|
-
"#{build_ruby_path}/bin"
|
296
|
-
elsif ruby_version
|
297
|
-
"#{slug_vendor_ruby}/bin"
|
298
|
-
else
|
299
|
-
""
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
# setup the environment so we can use the vendored ruby
|
304
|
-
def setup_ruby_install_env
|
305
|
-
ENV["PATH"] = "#{ruby_install_binstub_path}:#{ENV["PATH"]}"
|
306
|
-
|
307
|
-
if ruby_version_jruby?
|
308
|
-
ENV['JAVA_OPTS'] = default_java_opts
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
# list of default gems to vendor into the slug
|
313
|
-
# @return [Array] resulting list of gems
|
314
|
-
def gems
|
315
|
-
[BUNDLER_GEM_PATH]
|
316
|
-
end
|
317
|
-
|
318
|
-
# installs vendored gems into the slug
|
319
|
-
def install_language_pack_gems
|
320
|
-
FileUtils.mkdir_p(slug_vendor_base)
|
321
|
-
Dir.chdir(slug_vendor_base) do |dir|
|
322
|
-
gems.each do |gem|
|
323
|
-
run("curl #{VENDOR_URL}/#{gem}.tgz -s -o - | tar xzf -")
|
324
|
-
end
|
325
|
-
Dir["bin/*"].each {|path| run("chmod 755 #{path}") }
|
326
|
-
end
|
327
|
-
end
|
328
|
-
|
329
|
-
# default set of binaries to install
|
330
|
-
# @return [Array] resulting list
|
331
|
-
def binaries
|
332
|
-
add_node_js_binary
|
333
|
-
end
|
334
|
-
|
335
|
-
# vendors binaries into the slug
|
336
|
-
def install_binaries
|
337
|
-
binaries.each {|binary| install_binary(binary) }
|
338
|
-
Dir["bin/*"].each {|path| run("chmod +x #{path}") }
|
339
|
-
end
|
340
|
-
|
341
|
-
# vendors individual binary into the slug
|
342
|
-
# @param [String] name of the binary package from S3.
|
343
|
-
# Example: https://s3.amazonaws.com/language-pack-ruby/node-0.4.7.tgz, where name is "node-0.4.7"
|
344
|
-
def install_binary(name)
|
345
|
-
bin_dir = "bin"
|
346
|
-
FileUtils.mkdir_p bin_dir
|
347
|
-
Dir.chdir(bin_dir) do |dir|
|
348
|
-
run("curl #{VENDOR_URL}/#{name}.tgz -s -o - | tar xzf -")
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
# removes a binary from the slug
|
353
|
-
# @param [String] relative path of the binary on the slug
|
354
|
-
def uninstall_binary(path)
|
355
|
-
FileUtils.rm File.join('bin', File.basename(path)), :force => true
|
356
|
-
end
|
357
|
-
|
358
|
-
# install libyaml into the LP to be referenced for psych compilation
|
359
|
-
# @param [String] tmpdir to store the libyaml files
|
360
|
-
def install_libyaml(dir)
|
361
|
-
FileUtils.mkdir_p dir
|
362
|
-
Dir.chdir(dir) do |dir|
|
363
|
-
run("curl #{VENDOR_URL}/#{LIBYAML_PATH}.tgz -s -o - | tar xzf -")
|
364
|
-
end
|
365
|
-
end
|
366
|
-
|
367
|
-
# remove `vendor/bundle` that comes from the git repo
|
368
|
-
# in case there are native ext.
|
369
|
-
# users should be using `bundle pack` instead.
|
370
|
-
# https://github.com/heroku/heroku-buildpack-ruby/issues/21
|
371
|
-
def remove_vendor_bundle
|
372
|
-
if File.exists?("vendor/bundle")
|
373
|
-
topic "WARNING: Removing `vendor/bundle`."
|
374
|
-
puts "Checking in `vendor/bundle` is not supported. Please remove this directory"
|
375
|
-
puts "and add it to your .gitignore. To vendor your gems with Bundler, use"
|
376
|
-
puts "`bundle pack` instead."
|
377
|
-
FileUtils.rm_rf("vendor/bundle")
|
378
|
-
end
|
379
|
-
end
|
380
|
-
|
381
|
-
# runs bundler to install the dependencies
|
382
|
-
def build_bundler
|
383
|
-
log("bundle") do
|
384
|
-
bundle_without = ENV["BUNDLE_WITHOUT"] || "development:test"
|
385
|
-
bundle_command = "bundle install --without #{bundle_without} --path vendor/bundle --binstubs vendor/bundle/bin"
|
386
|
-
|
387
|
-
unless File.exist?("Gemfile.lock")
|
388
|
-
error "Gemfile.lock is required. Please run \"bundle install\" locally\nand commit your Gemfile.lock."
|
389
|
-
end
|
390
|
-
|
391
|
-
if has_windows_gemfile_lock?
|
392
|
-
topic "WARNING: Removing `Gemfile.lock` because it was generated on Windows."
|
393
|
-
puts "Bundler will do a full resolve so native gems are handled properly."
|
394
|
-
puts "This may result in unexpected gem versions being used in your app."
|
395
|
-
|
396
|
-
log("bundle", "has_windows_gemfile_lock")
|
397
|
-
File.unlink("Gemfile.lock")
|
398
|
-
else
|
399
|
-
# using --deployment is preferred if we can
|
400
|
-
bundle_command += " --deployment"
|
401
|
-
cache_load ".bundle"
|
402
|
-
end
|
403
|
-
|
404
|
-
version = run_stdout("bundle version").strip
|
405
|
-
topic("Installing dependencies using #{version}")
|
406
|
-
|
407
|
-
load_bundler_cache
|
408
|
-
|
409
|
-
bundler_output = ""
|
410
|
-
Dir.mktmpdir("libyaml-") do |tmpdir|
|
411
|
-
libyaml_dir = "#{tmpdir}/#{LIBYAML_PATH}"
|
412
|
-
install_libyaml(libyaml_dir)
|
413
|
-
|
414
|
-
# need to setup compile environment for the psych gem
|
415
|
-
yaml_include = File.expand_path("#{libyaml_dir}/include")
|
416
|
-
yaml_lib = File.expand_path("#{libyaml_dir}/lib")
|
417
|
-
pwd = run("pwd").chomp
|
418
|
-
bundler_path = "#{pwd}/#{slug_vendor_base}/gems/#{BUNDLER_GEM_PATH}/lib"
|
419
|
-
# we need to set BUNDLE_CONFIG and BUNDLE_GEMFILE for
|
420
|
-
# codon since it uses bundler.
|
421
|
-
env_vars = "env BUNDLE_GEMFILE=#{pwd}/Gemfile BUNDLE_CONFIG=#{pwd}/.bundle/config CPATH=#{yaml_include}:$CPATH CPPATH=#{yaml_include}:$CPPATH LIBRARY_PATH=#{yaml_lib}:$LIBRARY_PATH RUBYOPT=\"#{syck_hack}\""
|
422
|
-
env_vars += " BUNDLER_LIB_PATH=#{bundler_path}" if ruby_version.match(/^ruby-1\.8\.7/)
|
423
|
-
puts "Running: #{bundle_command}"
|
424
|
-
bundler_output << pipe("#{env_vars} #{bundle_command} --no-clean 2>&1")
|
425
|
-
|
426
|
-
end
|
427
|
-
|
428
|
-
if $?.success?
|
429
|
-
log "bundle", :status => "success"
|
430
|
-
puts "Cleaning up the bundler cache."
|
431
|
-
pipe "bundle clean 2> /dev/null"
|
432
|
-
cache_store ".bundle"
|
433
|
-
cache_store "vendor/bundle"
|
434
|
-
|
435
|
-
# Keep gem cache out of the slug
|
436
|
-
FileUtils.rm_rf("#{slug_vendor_base}/cache")
|
437
|
-
|
438
|
-
# symlink binstubs
|
439
|
-
bin_dir = "bin"
|
440
|
-
FileUtils.mkdir_p bin_dir
|
441
|
-
Dir["#{slug_vendor_base}/bin/*"].each do |bin|
|
442
|
-
run("ln -s ../#{bin} #{bin_dir}") unless File.exist?("#{bin_dir}/#{bin}")
|
443
|
-
end
|
444
|
-
else
|
445
|
-
log "bundle", :status => "failure"
|
446
|
-
error_message = "Failed to install gems via Bundler."
|
447
|
-
if bundler_output.match(/Installing sqlite3 \([\w.]+\) with native extensions\s+Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension./)
|
448
|
-
error_message += <<ERROR
|
449
|
-
|
450
|
-
|
451
|
-
Detected sqlite3 gem which is not supported on Heroku.
|
452
|
-
http://devcenter.heroku.com/articles/how-do-i-use-sqlite3-for-development
|
453
|
-
ERROR
|
454
|
-
end
|
455
|
-
|
456
|
-
error error_message
|
457
|
-
end
|
458
|
-
end
|
459
|
-
end
|
460
|
-
|
461
|
-
# RUBYOPT line that requires syck_hack file
|
462
|
-
# @return [String] require string if needed or else an empty string
|
463
|
-
def syck_hack
|
464
|
-
syck_hack_file = File.expand_path(File.join(File.dirname(__FILE__), "../../vendor/syck_hack"))
|
465
|
-
ruby_version = run_stdout('ruby -e "puts RUBY_VERSION"').chomp
|
466
|
-
# < 1.9.3 includes syck, so we need to use the syck hack
|
467
|
-
if Gem::Version.new(ruby_version) < Gem::Version.new("1.9.3")
|
468
|
-
"-r#{syck_hack_file}"
|
469
|
-
else
|
470
|
-
""
|
471
|
-
end
|
472
|
-
end
|
473
|
-
|
474
|
-
# writes ERB based database.yml for Rails. The database.yml uses the DATABASE_URL from the environment during runtime.
|
475
|
-
def create_database_yml
|
476
|
-
log("create_database_yml") do
|
477
|
-
return unless File.directory?("config")
|
478
|
-
topic("Writing config/database.yml to read from DATABASE_URL")
|
479
|
-
File.open("config/database.yml", "w") do |file|
|
480
|
-
file.puts <<-DATABASE_YML
|
481
|
-
<%
|
482
|
-
|
483
|
-
require 'cgi'
|
484
|
-
require 'uri'
|
485
|
-
|
486
|
-
begin
|
487
|
-
uri = URI.parse(ENV["DATABASE_URL"])
|
488
|
-
rescue URI::InvalidURIError
|
489
|
-
raise "Invalid DATABASE_URL"
|
490
|
-
end
|
491
|
-
|
492
|
-
raise "No RACK_ENV or RAILS_ENV found" unless ENV["RAILS_ENV"] || ENV["RACK_ENV"]
|
493
|
-
|
494
|
-
def attribute(name, value, force_string = false)
|
495
|
-
if value
|
496
|
-
value_string =
|
497
|
-
if force_string
|
498
|
-
'"' + value + '"'
|
499
|
-
else
|
500
|
-
value
|
501
|
-
end
|
502
|
-
"\#{name}: \#{value_string}"
|
503
|
-
else
|
504
|
-
""
|
505
|
-
end
|
506
|
-
end
|
507
|
-
|
508
|
-
adapter = uri.scheme
|
509
|
-
adapter = "postgresql" if adapter == "postgres"
|
510
|
-
|
511
|
-
database = (uri.path || "").split("/")[1]
|
512
|
-
|
513
|
-
username = uri.user
|
514
|
-
password = uri.password
|
515
|
-
|
516
|
-
host = uri.host
|
517
|
-
port = uri.port
|
518
|
-
|
519
|
-
params = CGI.parse(uri.query || "")
|
520
|
-
|
521
|
-
%>
|
522
|
-
|
523
|
-
<%= ENV["RAILS_ENV"] || ENV["RACK_ENV"] %>:
|
524
|
-
<%= attribute "adapter", adapter %>
|
525
|
-
<%= attribute "database", database %>
|
526
|
-
<%= attribute "username", username %>
|
527
|
-
<%= attribute "password", password, true %>
|
528
|
-
<%= attribute "host", host %>
|
529
|
-
<%= attribute "port", port %>
|
530
|
-
|
531
|
-
<% params.each do |key, value| %>
|
532
|
-
<%= key %>: <%= value.first %>
|
533
|
-
<% end %>
|
534
|
-
DATABASE_YML
|
535
|
-
end
|
536
|
-
end
|
537
|
-
end
|
538
|
-
|
539
|
-
# add bundler to the load path
|
540
|
-
# @note it sets a flag, so the path can only be loaded once
|
541
|
-
def add_bundler_to_load_path
|
542
|
-
return if @bundler_loadpath
|
543
|
-
$: << File.expand_path(Dir["#{slug_vendor_base}/gems/bundler*/lib"].first)
|
544
|
-
@bundler_loadpath = true
|
545
|
-
end
|
546
|
-
|
547
|
-
# detects whether the Gemfile.lock contains the Windows platform
|
548
|
-
# @return [Boolean] true if the Gemfile.lock was created on Windows
|
549
|
-
def has_windows_gemfile_lock?
|
550
|
-
lockfile_parser.platforms.detect do |platform|
|
551
|
-
/mingw|mswin/.match(platform.os) if platform.is_a?(Gem::Platform)
|
552
|
-
end
|
553
|
-
end
|
554
|
-
|
555
|
-
# detects if a gem is in the bundle.
|
556
|
-
# @param [String] name of the gem in question
|
557
|
-
# @return [String, nil] if it finds the gem, it will return the line from bundle show or nil if nothing is found.
|
558
|
-
def gem_is_bundled?(gem)
|
559
|
-
@bundler_gems ||= lockfile_parser.specs.map(&:name)
|
560
|
-
@bundler_gems.include?(gem)
|
561
|
-
end
|
562
|
-
|
563
|
-
# setup the lockfile parser
|
564
|
-
# @return [Bundler::LockfileParser] a Bundler::LockfileParser
|
565
|
-
def lockfile_parser
|
566
|
-
add_bundler_to_load_path
|
567
|
-
@lockfile_parser ||= LanguagePack::Ruby.lockfile_parser
|
568
|
-
end
|
569
|
-
|
570
|
-
# detects if a rake task is defined in the app
|
571
|
-
# @param [String] the task in question
|
572
|
-
# @return [Boolean] true if the rake task is defined in the app
|
573
|
-
def rake_task_defined?(task)
|
574
|
-
run("env PATH=$PATH bundle exec rake #{task} --dry-run") && $?.success?
|
575
|
-
end
|
576
|
-
|
577
|
-
# executes the block with GIT_DIR environment variable removed since it can mess with the current working directory git thinks it's in
|
578
|
-
# @param [block] block to be executed in the GIT_DIR free context
|
579
|
-
def allow_git(&blk)
|
580
|
-
git_dir = ENV.delete("GIT_DIR") # can mess with bundler
|
581
|
-
blk.call
|
582
|
-
ENV["GIT_DIR"] = git_dir
|
583
|
-
end
|
584
|
-
|
585
|
-
# decides if we need to enable the dev database addon
|
586
|
-
# @return [Array] the database addon if the pg gem is detected or an empty Array if it isn't.
|
587
|
-
def add_dev_database_addon
|
588
|
-
gem_is_bundled?("pg") ? ['heroku-postgresql:dev'] : []
|
589
|
-
end
|
590
|
-
|
591
|
-
# decides if we need to install the node.js binary
|
592
|
-
# @note execjs will blow up if no JS RUNTIME is detected and is loaded.
|
593
|
-
# @return [Array] the node.js binary path if we need it or an empty Array
|
594
|
-
def add_node_js_binary
|
595
|
-
gem_is_bundled?('execjs') ? [NODE_JS_BINARY_PATH] : []
|
596
|
-
end
|
597
|
-
|
598
|
-
def run_assets_precompile_rake_task
|
599
|
-
if rake_task_defined?("assets:precompile")
|
600
|
-
require 'benchmark'
|
601
|
-
|
602
|
-
topic "Running: rake assets:precompile"
|
603
|
-
time = Benchmark.realtime { pipe("env PATH=$PATH:bin bundle exec rake assets:precompile 2>&1") }
|
604
|
-
if $?.success?
|
605
|
-
puts "Asset precompilation completed (#{"%.2f" % time}s)"
|
606
|
-
end
|
607
|
-
end
|
608
|
-
end
|
609
|
-
|
610
|
-
def bundler_cache
|
611
|
-
"vendor/bundle"
|
612
|
-
end
|
613
|
-
|
614
|
-
def load_bundler_cache
|
615
|
-
cache_load "vendor"
|
616
|
-
|
617
|
-
full_ruby_version = run_stdout(%q(ruby -v)).chomp
|
618
|
-
rubygems_version = run_stdout(%q(gem -v)).chomp
|
619
|
-
heroku_metadata = "vendor/heroku"
|
620
|
-
old_rubygems_version = nil
|
621
|
-
ruby_version_cache = "#{heroku_metadata}/ruby_version"
|
622
|
-
buildpack_version_cache = "#{heroku_metadata}/buildpack_version"
|
623
|
-
bundler_version_cache = "#{heroku_metadata}/bundler_version"
|
624
|
-
rubygems_version_cache = "#{heroku_metadata}/rubygems_version"
|
625
|
-
|
626
|
-
old_rubygems_version = File.read(rubygems_version_cache).chomp if File.exists?(rubygems_version_cache)
|
627
|
-
|
628
|
-
# fix bug from v37 deploy
|
629
|
-
if File.exists?("vendor/ruby_version")
|
630
|
-
puts "Broken cache detected. Purging build cache."
|
631
|
-
cache_clear("vendor")
|
632
|
-
FileUtils.rm_rf("vendor/ruby_version")
|
633
|
-
purge_bundler_cache
|
634
|
-
# fix bug introduced in v38
|
635
|
-
elsif !File.exists?(buildpack_version_cache) && File.exists?(ruby_version_cache)
|
636
|
-
puts "Broken cache detected. Purging build cache."
|
637
|
-
purge_bundler_cache
|
638
|
-
elsif cache_exists?(bundler_cache) && File.exists?(ruby_version_cache) && full_ruby_version != File.read(ruby_version_cache).chomp
|
639
|
-
puts "Ruby version change detected. Clearing bundler cache."
|
640
|
-
puts "Old: #{File.read(ruby_version_cache).chomp}"
|
641
|
-
puts "New: #{full_ruby_version}"
|
642
|
-
purge_bundler_cache
|
643
|
-
end
|
644
|
-
|
645
|
-
# fix git gemspec bug from Bundler 1.3.0+ upgrade
|
646
|
-
if File.exists?(bundler_cache) && !File.exists?(bundler_version_cache) && !run("find vendor/bundle/*/*/bundler/gems/*/ -name *.gemspec").include?("No such file or directory")
|
647
|
-
puts "Old bundler cache detected. Clearing bundler cache."
|
648
|
-
purge_bundler_cache
|
649
|
-
end
|
650
|
-
|
651
|
-
# fix for https://github.com/heroku/heroku-buildpack-ruby/issues/86
|
652
|
-
if (!File.exists?(rubygems_version_cache) ||
|
653
|
-
(old_rubygems_version == "2.0.0" && old_rubygems_version != rubygems_version)) &&
|
654
|
-
File.exists?(ruby_version_cache) && File.read(ruby_version_cache).chomp.include?("ruby 2.0.0p0")
|
655
|
-
puts "Updating to rubygems #{rubygems_version}. Clearing bundler cache."
|
656
|
-
purge_bundler_cache
|
657
|
-
end
|
658
|
-
|
659
|
-
FileUtils.mkdir_p(heroku_metadata)
|
660
|
-
File.open(ruby_version_cache, 'w') do |file|
|
661
|
-
file.puts full_ruby_version
|
662
|
-
end
|
663
|
-
File.open(buildpack_version_cache, 'w') do |file|
|
664
|
-
file.puts BUILDPACK_VERSION
|
665
|
-
end
|
666
|
-
File.open(bundler_version_cache, 'w') do |file|
|
667
|
-
file.puts BUNDLER_VERSION
|
668
|
-
end
|
669
|
-
File.open(rubygems_version_cache, 'w') do |file|
|
670
|
-
file.puts rubygems_version
|
671
|
-
end
|
672
|
-
cache_store heroku_metadata
|
673
|
-
end
|
674
|
-
|
675
|
-
def purge_bundler_cache
|
676
|
-
FileUtils.rm_rf(bundler_cache)
|
677
|
-
cache_clear bundler_cache
|
678
|
-
# need to reinstall language pack gems
|
679
|
-
install_language_pack_gems
|
680
|
-
end
|
681
|
-
end
|