deploy database.yml with Capistrano 3 in rails app - ruby-on-rails

I have a Rails 4 app that connects to a second, external database. So I added the database credentials to my database.yml file and excluded it from version control in git. I need to deploy it when I push to Heroku using Capistrano.
I found some questions raised for this task, but they don't work for me and they were answered prior to the release of Capistrano 3.
I set up capistrano by adding:
group :development, :test do
gem 'capistrano-rails', '~> 1.1.1'
end
and
running bundle install then bundle exec cap install as it says in the install instructions.
I created a new folder in my app and copied the database.yml file there: myApp/shared/config/database.yml (not sure if this was necessary)
Finally, I created the following task in deply.rb:
after "deploy:update_code","deploy:config_symlink"
namespace :deploy do
task :config_symlink do
run "cp #{shared_path}/shared/config/database.yml #{release_path}/config/database.yml"
end
end
This didn't work and threw an error when pushed to Heroku:
/app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.1/lib/active_record/connection_adapters/connection_specification.rb:248:in `resolve_symbol_connection': 'pg_development' database is not configured. Available: ["production"] (ActiveRecord::AdapterNotSpecified)
I tried putting this task in the production.rb file as well as adding set :linked_files, %w{config/database.yml} to the development.rb file.
Can someone help me get the database.yml file into production on Heroku?

Related

"bundle exec rake" doesn't honor "without"

On a GitLab installation from source, I'm having problems running binaries such as rake. I've never seen similar problems with my own Ruby or Rails projects:
# bundle config
Set for your local app (/mnt/data/www/gitlab.bitcetera.com/source/gitlab/.bundle/config): "1"
path
Set for your local app (/mnt/data/www/gitlab.bitcetera.com/source/gitlab/.bundle/config): "vendor/bundle"
without
Set for your local app (/mnt/data/www/gitlab.bitcetera.com/source/gitlab/.bundle/config): "development:test:unicorn:mysql:kerberos:metrics"
disable_shared_gems
Set for your local app (/mnt/data/www/gitlab.bitcetera.com/source/gitlab/.bundle/config): "true"
# bundle install --deployment --without development test unicorn mysql kerberos metrics
# bundle config
The Gemfile's dependencies are satisfied
# bundle exec rake --tasks
rake aborted!
LoadError: cannot load such file -- haml_lint/rake_task
Looking at the relevant section of the Gemfile:
group :development, :test do
[...]
gem 'haml_lint', '~> 0.21.0', require: false
[...]
end
Of course the haml_lint gem is missing, after all, it's in the "development" and "test" groups only which I've excluded by "without".
Any idea what's going on here?
Figured it out, kinda daft reason: RAILS_ENV should have been set automatically yet it wasn't so of course things go awry.

Setting up secret_key_base on deploy with Capistrano 3

So I'm deploying to a Ubuntu droplet hosted on DigitalOcean a Rails 4 application running on Apache and Phusion Passenger. After deployment I've been getting 500s as a result of Rails production not finding the secret_key_base token for production. However, if I run an echo $SECRET_KEY_BASE it returns the rake secret generated by my deploy.rb.
The deploy.rb task to set that up is:
namespace :deploy do
task :start do ; end
task :stop do ; end
desc "Setup ENV variables"
task :env_vars do
on "root#xxx.xxx.xxx.xx" do
execute "export SECRET_KEY_BASE=#{`bundle exec rake secret`}"
end
end
end
before "deploy", "deploy:env_vars"
However, Rails is still not picking it up. I even ssh'd into my server and in rails console checked and ENV["SECRET_KEY_BASE"] returns the correct secret token.
I thought using Capistrano's :default_env would work, but that only seems to set up environmental variables for the deploy task, but not actually on the server. Is there any easy way to solve this solution? My fallback is to just place the secret within secrets.yml since the repo is private, but I rather not do that.
There is a gem for exactly this task:
https://github.com/capistrano-plugins/capistrano-secrets-yml
Install
Add this to Gemfile:
group :development do
gem 'capistrano', '~> 3.2.1'
gem 'capistrano-secrets-yml', '~> 1.0.0'
end
And then:
$ bundle install
Setup and usage
make sure your local config/secrets.yml is not git tracked. It should be on the disk, but gitignored.
populate production secrets in local config/secrets.yml:
production:
secret_key_base: d6ced...
add to Capfile:
require 'capistrano/secrets_yml'
create secrets.yml file on the remote server by executing this task:
$ bundle exec cap production setup
You can now proceed with other deployment tasks.
You can create a file in your server called application.yml in shared/config.
Choose any one of solution from bellow
Following code in deploy.rb will automatically symlink your application.yml
set :linked_files, %w{config/application.yml}
Or
Then symlink this application.yml with your current/config/application.yml with a simple capistrano task.
Rather than exporting env variables in deploy.rb, use dotenv to load environment variables from .env[.<staging>] into ENV when rails booting.
Follow these steps:
Add this line to the top of your Gemfile:
gem 'dotenv-rails'
Put .env.production file into the linked_file in deploy/production.rb:
set :linked_files, fetch(:linked_files, []).push('.env.production')
On the remote host, add the .env.production file in shared folder which contains this line:
SECRET_KEY_BASE=<Your secret>
Give up on environment vars and just simply read a file. Do this in secrets.yml.
production:
secret_key_base: <%= File.read('/home/me/SECRET_KEY_BASE').strip %>
Then make the secret file.
$ rake secret > ~/SECRET_KEY_BASE
Before settling on this solution I tried exporting the secret from my .bash_profile, .profile, and .bashrc (top and bottom). I also tried PermitUserEnvironment and .ssh/environment. I have no idea how an environment variable gets from "the environment" into a capistrano deployment. I ran ssh example.com printenv and saw my vars. I logged in and saw my vars. But puma started with capistrano... it always has it's own environment.

Capistrano doesn't set RAILS_ENV for bundler

In my Gemfile I specify what branch to use on a git repository based on RAILS_ENV. However when Capistrano deploys, it runs the bundle install command - and since it's run through a shell, the proper environment (staging) isn't set. It defaults to development and gives me an error stating that there's a mismatch between Gemfile.lock and what is installed.
You are trying to install in deployment mode after changing your
Gemfile. Run bundle install elsewhere and add the updated
Gemfile.lock to version control.
You have added to the Gemfile:
* source: git#bitbucket.org:MyRepository/manager-engine.git (at develop)
You have deleted from the Gemfile:
* source: git#bitbucket.org:MyRepository/manager-engine.git (at master)
You have changed in the Gemfile:
* manager from git#bitbucket.org:MyRepository/manager-engine.git (at develop) to no specified source
Gemfile:
RAILS_ENV = ENV['RAILS_ENV'] || 'development'
gem 'manager', git: "git#bitbucket.org:MyRepository/manager-engine.git", branch: "#{ [:production, :staging].include?(RAILS_ENV.to_sym) ? :master : :develop }"
i.e., use the 'develop' branch if the rails environment is anything other than 'production' or 'staging'.
deploy/staging.rb:
set :branch, :master
set :keep_releases, 2
set :stage, :staging
set :rails_env, 'staging'
set :bundle_without, [:development, :test]
set :deploy_to, '/home/useraccount/rails_deployments/staging.www'
server 'localhost', user: 'useraccount', roles: %w{web app db}
So to be the most concise:
In regular SSH terminal, to install the repository gem under the proper environment, I have to issue RAILS_ENV=staging bundle install. Otherwise, just running bundle install installs the repository from the develop branch. Since Capistrano just runs bundle install and doesn't include the RAILS_ENV, this problem is occurring. But doesn't Capistrano set :rails_env, or is that not a real system environment variable?
I guess if there's no better way...
I ended up using a method illustrated somewhere else in SO and modified it for my needs.
Modify Gemfile to contain:
# Read environment from A) Explicit set through command, B) Existence of override file's contents or C) Default to development
RAILS_ENV = ENV['RAILS_ENV'] || `cat .rails-env`.to_s.split.first || 'development'
If .rails-env contains nothing or doesn't exist, it defaults to development. Otherwise it takes the first word as the environment. To create the file from the command line, just type echo "your-environment-name-here" > .rails-env, assuming you're in the app's root directory.
You can also create the file upon every deploy with capistrano using the command above, or just create a symlink to the file and share it between deployments:
Deploy.rb:
set :linked_files, %w{ .rails-env }
So now the environment can be forced via a file in the root of your app called .rails-env. Explicit RAILS_ENV calls such as RAILS_ENV=test bundle exec ... will still work as advertised.

Gem is not checked out. Please run `bundle install` in Heroku

I have this configuration in my Gemfile:
group :test do
# ...
gem "shoulda-matchers", :git => "git://github.com/watu/shoulda-matchers.git", :branch => "do_not_load_minitest"
end
which works fine locally, but when I push to Heroku, when I try to run rake db:migrate, I get this error:
git://github.com/watu/shoulda-matchers.git (at do_not_load_minitest) is not checked out. Please run bundle install
Indeed I don't see it in the output of bundle install being run on Heroku, maybe because it's on the test group and Heroku is not installing the test group. But then, why is it complaining when I run rake db:migrate? should it run in staging env?
I tried switching to the http url and all I got is the same error with another URL:
https://github.com/watu/shoulda-matchers.git (at do_not_load_minitest) is not checked out. Please run bundle install
Moving the line outside the :test group workarounded the problem. What's the proper solution?
If you don't really need that gem (since it is in :test group), you can add this configuration to your app:
heroku config:add BUNDLE_WITHOUT="development:test" --app <your_app>

heroku rake db:migrate rake aborted! unable to open database

I am currently making my way through the Ruby on Rails tutorial over at http://ruby.railstutorial.org/ and I am trying to migrate the demo_app database to heroku.
heroku rake db:migrate
rake aborted!
unable to open database file
I have read on other stackoverflow posts that some people fixed this by entering
group :production, :staging do
gem "pg"
end
group :development, :test do
gem "sqlite3-ruby", "~> 1.3.0", :require => "sqlite3"
end
in the gemfile. I also entered it into my gemfile and then deleted my old gemfile.lock and redid my bundle install AND rake db:migrate command. I am still receiving the same error.
I am obviously brand new to ruby, rails and heroku but I understand that the problem seems to be that I am using sqlite locally and postgresql in production (on heroku). Do I now have to install this postgresql onto my machine and then RE-migrate the DB? I am afraid I will not be able to get much more out of the tutorials (or ruby on rails itself) if I cannot use heroku.
Kill it!
I was having the same problem and found no solutions. I think something we are doing in those tutorials is leading us to mangle the database.yml file that heroku generates.
I ended up destroying my heroku app
heroku destroy
and then creating a new one, pushing a fresh copy, and running
heroku create
git push heroku master
heroku rakedb:migrate
This time everything worked fine! Just make sure you have the pg gem in your gemfile for production
group :production do
gem "pg"
end
and add config/database.yml to your .gitignore file too for good measure.
or if it's working ok locally do a heroku db:push to magically put your local sqlite DB into Heroku's postgresql db.
I always work with the same DB platform locally just so I don't run into any differences (usually only when you start doing DB specific SQL) so I run Postgresql locally too.
Had the same problem... with Heroku interface... ran:
heroku rake db:migrate --trace
and found the problem to be with faker, not being found...Since 'faker' in our Gemfile is loaded in the development group, I loaded it in the production group as well.
saved Gemfile
bundle install
git add .
git commit -m "fixed faker"
git push
git heroku push
heroku rake db:migrate
heroku rake db:populate
now everything works...the QUESTION, now is what to do with 100 users on my production site?
At least I can continue with Hartl's tutorial!!

Resources