├── .gitignore ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── heroku_db_restore.gemspec └── lib ├── heroku_db_restore.rb ├── heroku_db_restore ├── railtie.rb └── version.rb └── tasks └── db_restore.rake /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | *.gem 11 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in heroku_db_restore.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 nrowegt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Heroku DB Restore 2 | 3 | A (for now) very opinionated gem makes it super easy to take a backup of a Heroku Postgres database, download it, and restore it. 4 | 5 | This gem looks for two Environment Variables, each representing an app in either `staging` or `production` environments. 6 | 7 | 1. HEROKU_APPNAME_PRODUCTION=my-heroku-app 8 | 2. HEROKU_APPNAME_STAGING=my-heroku-app-staging 9 | 10 | Set these in your `.env` file, or however you manage environment variables in your app. We recommend `dotenv-rails`. 11 | 12 | ## Installation 13 | 14 | Add this line to your application's Gemfile: 15 | 16 | ```ruby 17 | gem 'heroku_db_restore', group: :development # No need to include this on production or staging 18 | ``` 19 | 20 | And then execute: 21 | 22 | $ bundle 23 | 24 | Or install it yourself as: 25 | 26 | $ gem install heroku_db_restore 27 | 28 | ## Usage 29 | To see an updated list of tasks and descriptions: 30 | `bin/rake -T | grep db:restore` 31 | 32 | ~~~bash 33 | rake db:restore # Pull Down a copy of the database from the specified heroku environment 34 | rake db:restore:from_local_dump # Restore from local dump file (defaults to '/tmp/latest.dump' - specify with DUMP_FILE Environmental Variable) 35 | rake db:restore:local # Erase local development and test database and restore from the local dump file 36 | rake db:restore:production # Restore a local copy of Heroku's Production Environment database 37 | rake db:restore:staging # Restore a local copy of Heroku's Staging Environment database 38 | ~~~ 39 | 40 | 41 | ## Contributing 42 | 43 | Bug reports and pull requests are welcome on GitHub at https://github.com/railsagency/heroku_db_restore. 44 | 45 | 46 | ## License 47 | 48 | The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). 49 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | 3 | task :default => :spec 4 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "heroku_db_restore" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | IRB.start 15 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /heroku_db_restore.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'heroku_db_restore/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "heroku_db_restore" 8 | spec.version = HerokuDbRestore::VERSION 9 | spec.authors = ["nrowegt", "danielricecodes"] 10 | spec.email = ["nrowegt@gmail.com", "daniel.rice@ldstudios.co"] 11 | 12 | spec.summary = "Helpful Heroku Deploy Rake Tasks" 13 | spec.description = "Tasks to run appllication db_restores and db restores for heroku:pg databases" 14 | spec.homepage = "https://github.com/ldstudios/heroku_db_restore" 15 | spec.license = "MIT" 16 | 17 | # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' 18 | # to allow pushing to a single host or delete this section to allow pushing to any host. 19 | if spec.respond_to?(:metadata) 20 | spec.metadata['allowed_push_host'] = "https://rubygems.org" 21 | else 22 | raise "RubyGems 2.0 or newer is required to protect against " \ 23 | "public gem pushes." 24 | end 25 | 26 | spec.files = `git ls-files -z`.split("\x0").reject do |f| 27 | f.match(%r{^(test|spec|features)/}) 28 | end 29 | spec.bindir = "exe" 30 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 31 | spec.require_paths = ["lib"] 32 | 33 | spec.add_development_dependency "bundler", "~> 1.13" 34 | spec.add_development_dependency "rake", "~> 10.0" 35 | end 36 | -------------------------------------------------------------------------------- /lib/heroku_db_restore.rb: -------------------------------------------------------------------------------- 1 | require "heroku_db_restore/version" 2 | require "heroku_db_restore/railtie" if defined?(Rails) 3 | 4 | module HerokuDbRestore 5 | # TODO DRY rake tasks by moving repeated code here 6 | end 7 | -------------------------------------------------------------------------------- /lib/heroku_db_restore/railtie.rb: -------------------------------------------------------------------------------- 1 | class HerokuDbRestore::Railtie < Rails::Railtie 2 | rake_tasks do 3 | load 'tasks/db_restore.rake' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/heroku_db_restore/version.rb: -------------------------------------------------------------------------------- 1 | module HerokuDbRestore 2 | VERSION = "0.0.7" 3 | end 4 | -------------------------------------------------------------------------------- /lib/tasks/db_restore.rake: -------------------------------------------------------------------------------- 1 | namespace :db do 2 | desc 'Pull Down a copy of the database from the specified heroku environment' 3 | task :restore do 4 | env = ENV['ENV'] 5 | 6 | abort "Please specify ENV=production or ENV=staging" unless env 7 | app = app_name_from_environment(env) 8 | 9 | if ENV['LATEST'] #if this is here, then create a fresh backup, if not grab whichever is the latest 10 | sh "heroku pg:backups:capture --app #{app}" 11 | end 12 | 13 | sh "heroku pg:backups:download --output=tmp/latest.dump --app #{app}" 14 | 15 | #ensures there are no extra tables or views 16 | Rake::Task["db:restore:local"].invoke 17 | end 18 | 19 | namespace :restore do 20 | desc "Restore a local copy of Heroku's Staging Environment database" 21 | task :staging do 22 | ENV['ENV'] = "staging" 23 | Rake::Task["db:restore"].invoke 24 | end 25 | 26 | desc "Restore a local copy of Heroku's Production Environment database" 27 | task :production do 28 | ENV['ENV'] = "production" 29 | Rake::Task["db:restore"].invoke 30 | end 31 | 32 | desc "Erase local development and test database and restore from the local dump file." 33 | task :local do 34 | ENV['DISABLE_DATABASE_ENVIRONMENT_CHECK'] = '1' 35 | #ensures there are no extra tables or views 36 | Rake::Task["db:drop"].invoke 37 | Rake::Task["db:create"].invoke 38 | 39 | Rake::Task["db:restore:from_local_dump"].invoke 40 | #migrate the database, remove sensitive information, and setup tests 41 | Rake::Task["db:migrate"].invoke 42 | Rake::Task["db:test:prepare"].invoke 43 | end 44 | 45 | desc "Restore from local dump file (defaults to '/tmp/latest.dump' - specify with DUMP_FILE Environmental Variable)" 46 | task :from_local_dump do 47 | dump_file_location = (ENV['DUMP_FILE'] || "tmp/latest.dump") 48 | #in backticks so that pg_restore warnings dont exit this routine 49 | `DISABLE_DATABASE_ENVIRONMENT_CHECK=1 PGPASSWORD="#{local_database_password}" pg_restore --verbose --clean --no-acl --no-owner -h #{local_database_host} -d #{local_database_name} -p #{local_database_port} -U #{local_database_user} #{dump_file_location}` 50 | end 51 | end 52 | end 53 | 54 | def local_database_host 55 | Rails.configuration.database_configuration[Rails.env]["host"] 56 | end 57 | 58 | def local_database_name 59 | Rails.configuration.database_configuration[Rails.env]["database"] 60 | end 61 | 62 | def local_database_port 63 | Rails.configuration.database_configuration[Rails.env]["port"] 64 | end 65 | 66 | def local_database_user 67 | Rails.configuration.database_configuration[Rails.env]["username"] 68 | end 69 | 70 | def local_database_password 71 | Rails.configuration.database_configuration[Rails.env]["password"] 72 | end 73 | 74 | def app_name_from_environment(env) 75 | case env.downcase 76 | when "production" 77 | ENV['HEROKU_APPNAME_PRODUCTION'] || "#{Rails.application.class.parent_name.underscore.gsub('_','-')}" 78 | when "staging" 79 | ENV['HEROKU_APPNAME_STAGING'] || "#{Rails.application.class.parent_name.underscore.gsub('_','-')}-staging" 80 | end 81 | end 82 | --------------------------------------------------------------------------------