ruby 改进了heroku部署rake任务

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ruby 改进了heroku部署rake任务相关的知识,希望对你有一定的参考价值。

#Deploy and rollback on Heroku in staging, production, dev and test environments

require 'tempfile'

# for capturing error in 'git push'
def capture_stderr
  stderr = $stderr.dup
  Tempfile.open 'stderr-redirect' do |temp|
    $stderr.reopen temp.path, 'w+'
    yield if block_given?
    $stderr.reopen stderr
    temp.read
  end
end

%w[dev test production staging].each do |app|
  desc "Deploy to #{app}"
  task "deploy:#{app}" => %W[deploy:set_#{app}_app deploy:push deploy:restart deploy:tag]

  desc "Deploy #{app} with migrations"
  task "deploy:#{app}:migrations" => %W[deploy:set_#{app}_app deploy:push deploy:off deploy:migrate deploy:restart deploy:on deploy:tag]

  desc "Rollback #{app}"
  task "#{app}:rollback" => ["set_#{app}_app".to_sym, :off, :push_previous, :restart, :on]

  %w[logs config ps releases console scheduler init_db].each do |app_task|
    desc "#{app} #{app_task}"
    task "app:#{app}:#{app_task}" => ["deploy:set_#{app}_app", "app:#{app_task}"]
  end
end


namespace :deploy do

  PRODUCTION_APP = 'YOUR_PRODUCTION_APP_NAME_ON_HEROKU'
  STAGING_APP = 'YOUR_STAGING_APP_NAME_ON_HEROKU'
  TEST_APP = 'YOUR_TEST_APP_NAME_ON_HEROKU'
  DEV_APP = 'YOUR_DEVELOPMENT_APP_NAME_ON_HEROKU'

  # metaprogramming
  %w[dev test production staging].each do |app|
    task "set_#{app}_app" do
      # a trick to read a constant
      const_value = Object.const_get(app.upcase+'_APP')
      if !const_value || const_value.empty? || const_value == "YOUR_#{app.upcase}_APP_NAME_ON_HEROKU"
        raise "APP #{app.upcase} IS NOT SET"
      end
      APP = const_value
    end
  end

  task :push do
    git_status = `git status -v`
    abort("local branch is out of sync with github origin. please push there first") if git_status.match(/\*[^\]]+?\[ahead|behind/s) != nil
    current_branch = `git rev-parse --abbrev-ref HEAD`.chomp
    current_branch += ":master" if current_branch != "master"
    puts "Deploying #{current_branch} to #{APP} ..."
    #captured_content = capture_stderr do
    puts `git push -f git@heroku.com:#{APP}.git #{current_branch}`
    #end
    # display captured content
    #puts captured_content.to_s
    # stop furthe task chain in case of error (e.g. app name is invalid)
    #raise "EXIT" if captured_content.to_s.match(/fatal/)
  end

  task :restart do
    puts 'Restarting app servers ...'
    Bundler.with_clean_env do
      puts `heroku restart --app #{APP}`
    end
  end

  task :tag do
    release_name = "#{APP}-release-#{Time.now.utc.strftime("%Y%m%d-%H%M%S")}"
    puts "Tagging release as '#{release_name}'"
    puts `git tag -a #{release_name} -m 'Tagged release'`
    puts `git push --tags git@heroku.com:#{APP}.git`
    puts `git push --tags origin`
  end

  task :migrate do
    puts 'Running database migrations ...'
    Bundler.with_clean_env do
      puts `heroku run rake db:migrate --app #{APP}`
    end
  end

  task :off do
    puts 'Putting the app into maintenance mode ...'
    Bundler.with_clean_env do
      puts `heroku maintenance:on --app #{APP}`
    end
  end

  task :on do
    puts 'Taking the app out of maintenance mode ...'
    Bundler.with_clean_env do
      puts `heroku maintenance:off --app #{APP}`
    end
  end

  task :push_previous do
    prefix = "#{APP}-release-"
    releases = `git tag`.split("\n").select { |t| t[0..prefix.length-1] == prefix }.sort
    current_release = releases.last
    previous_release = releases[-2] if releases.length >= 2
    if previous_release
      puts "Rolling back to '#{previous_release}' ..."

      puts "Checking out '#{previous_release}' in a new branch on local git repo ..."
      puts `git checkout #{previous_release}`
      puts `git checkout -b #{previous_release}`

      puts "Removing tagged version '#{previous_release}' (now transformed in branch) ..."
      puts `git tag -d #{previous_release}`
      puts `git push git@heroku.com:#{APP}.git :refs/tags/#{previous_release}`

      puts "Pushing '#{previous_release}' to Heroku master ..."
      puts `git push git@heroku.com:#{APP}.git +#{previous_release}:master --force`

      puts "Deleting rollbacked release '#{current_release}' ..."
      puts `git tag -d #{current_release}`
      puts `git push git@heroku.com:#{APP}.git :refs/tags/#{current_release}`

      puts "Retagging release '#{previous_release}' in case to repeat this process (other rollbacks)..."
      puts `git tag -a #{previous_release} -m 'Tagged release'`
      puts `git push --tags git@heroku.com:#{APP}.git`

      puts "Turning local repo checked out on master ..."
      puts `git checkout master`
      puts 'All done!'
    else
      puts "No release tags found - can't roll back!"
      puts releases
    end
  end
end

namespace :app do
  task :logs do
    puts "tailing logs..."
    Bundler.clean_exec "heroku logs --tail --app #{APP}"
  end

  task :config do
    puts "config..."
    Bundler.with_clean_env do
      puts `heroku config --app #{APP}`
    end
  end

  task :console do
    puts "console..."
    Bundler.with_clean_env do
      sh "heroku run rails c --app #{APP}"
    end
  end

  task :scheduler do
    puts "scheduler..."
    Bundler.with_clean_env do
      sh "heroku addons:open scheduler --app #{APP}"
    end
  end

  task :ps do
    puts "running processes..."
    Bundler.with_clean_env do
      puts `heroku ps --app #{APP}`
    end
  end

  task :releases do
    puts "releases..."
    Bundler.with_clean_env do
      puts `heroku releases --app #{APP}`
    end
  end

  task :init_db do
    puts "init database"
    Bundler.with_clean_env do
      puts `heroku maintenance:on --app #{APP}`
      puts `heroku run rake db:schema:load --app #{APP}`
      puts `heroku run rake db:migrate --app #{APP}`
      puts `heroku run rake db:seed --app #{APP}`
      puts `heroku maintenance:off --app #{APP}`
    end
  end
end

以上是关于ruby 改进了heroku部署rake任务的主要内容,如果未能解决你的问题,请参考以下文章

Heroku 推送错误:“无法检测到 rake 任务”(Rails 6.1)

ruby heroku_db.rake

ruby rake_heroku_deployer.rb

部署 Rails 应用程序时无法检测到 rake 任务

使用参数在 Heroku 上运行 rake 任务并指定 Heroku 应用程序

如何将参数传递给使用 Heroku Scheduler 调用的 rake 任务?