lib/slugbuilder/builder.rb in slugbuilder-2.0.2 vs lib/slugbuilder/builder.rb in slugbuilder-3.0.0

- old
+ new

@@ -1,9 +1,10 @@ require 'securerandom' require 'shellwords' require 'yaml' require 'fileutils' +require 'open3' module Slugbuilder class Builder def initialize(repo:, git_ref:, stdout: $stdout) @stdout = stdout @@ -31,11 +32,11 @@ # clear environment from previous builds FileUtils.rm_rf(@env_dir) FileUtils.mkdir_p(@env_dir) @buildpacks = buildpacks - @env = env + @env = env.map { |k, v| [k.to_s, v.to_s] }.to_h @slug_file = slug_name ? "#{slug_name}.tgz" : Shellwords.escape("#{@repo.gsub('/', '.')}.#{@git_ref}.#{@git_sha}.tgz") wipe_cache if clear_cache prebuild.call(repo: @repo, git_ref: @git_ref, git_url: @git_url) if prebuild @@ -59,11 +60,11 @@ if block_given? yield(repo: @repo, git_ref: @git_ref, git_sha: @git_sha, git_url: @git_url, request_id: @request_id, stats: stats, slug: File.join(@output_dir, @slug_file)) end return true rescue => e - stitle("Failed: #{e}\n#{e.backtrace.join("\n")}") + stitle("Failed: #{e}\n") return false ensure restore_env end @@ -118,11 +119,11 @@ end def set_environment load_env_file("#{@cache_dir}/env") load_env_file("#{@build_dir}/.env") - ENV['STACK'] = 'cedar-14' + ENV['STACK'] = Slugbuilder.config.heroku_stack @request_id = SecureRandom.urlsafe_base64(32) ENV['REQUEST_ID'] = @request_id ENV['SOURCE_VERSION'] = @git_sha # write user envs to files @@ -130,11 +131,11 @@ ENV['HOME'] = @build_dir ENV['APP_DIR'] = @build_dir stitle('Build environment') - ENV.each do |k, v| + ENV.to_h.merge(@env).each do |k, v| stext("#{k}=#{v}") end end def create_dirs @@ -210,12 +211,12 @@ def run_hook(hook_name) Dir.chdir(@build_dir) do script = "#{@build_dir}/bin/#{hook_name}" if File.exists?(script) - rc = run(script) - fail "Failed to run #{script}" if rc != 0 + rc, errs = run_echo(script) + fail "#{errs.join('\n')}\nFailed to run #{script}" if rc != 0 end end end def run_buildpacks(buildpacks) @@ -235,12 +236,12 @@ end end def compile(buildpack) - rc = run_echo("#{buildpack}/bin/compile '#{@build_dir}' '#{@cache_dir}' '#{@env_dir}'") - fail "Couldn't compile application using buildpack #{buildpack}" if rc != 0 + rc, errs = run_echo("#{buildpack}/bin/compile '#{@build_dir}' '#{@cache_dir}' '#{@env_dir}'") + fail "#{errs.join('\n')}\nCouldn't compile application using buildpack #{buildpack}" if rc != 0 end def release(buildpack) # should create .release release_file = File.open("#{@build_dir}/.release", 'w') @@ -252,18 +253,19 @@ fail "Couldn't release application using buildpack #{buildpack}" if rc != 0 end def build_slug rc = 1 + errs = [] # use pigz if available compression = `which pigz` != '' ? '--use-compress-program=pigz' : '' if File.exists?("#{@build_dir}/.slugignore") - rc = run_echo("tar --exclude='.git' #{compression} -X #{@build_dir}/.slugignore -C #{@build_dir} -cf #{File.join(@output_dir, @slug_file)} .") + rc, errs = run_echo("tar --exclude='.git' #{compression} -X #{@build_dir}/.slugignore -C #{@build_dir} -cf #{File.join(@output_dir, @slug_file)} .") else - rc = run_echo("tar --exclude='.git' #{compression} -C #{@build_dir} -cf #{File.join(@output_dir, @slug_file)} .") + rc, errs = run_echo("tar --exclude='.git' #{compression} -C #{@build_dir} -cf #{File.join(@output_dir, @slug_file)} .") end - fail "Couldn't create slugfile" if rc != 0 + fail "#{errs.join('\n')}\nCouldn't create slugfile" if rc != 0 end def slug_size @slug_size = File.size(File.join(@output_dir, @slug_file)) / 1024 / 1024 stitle("Slug size is #{@slug_size} Megabytes.") @@ -327,23 +329,27 @@ yield ((Time.now - t0).to_i * 100) / 100.0 end def run(cmd) - IO.popen(cmd) do |io| - until io.eof? - data = io.gets - yield data if block_given? + Open3.popen3(cmd) do |stdin, stdout, stderr, thread| + until stdout.eof? && stderr.eof? + out = stdout.gets + err = stderr.gets + yield(out, err) if block_given? end + thread.value.exitstatus end - $?.exitstatus end def run_echo(cmd) - run(cmd) do |line| - build_output << line - @stdout.print(line) + errors = [] + status = run(cmd) do |stdout, stderr| + build_output << stdout if stdout + errors << stderr if stderr + @stdout.print(stdout) end + [status, errors] end def load_export_env(file) if File.exists?(file) exports = IO.read(file).split('export')