Running Migration after capistrano deployment - ruby-on-rails

I am trying to learn deployment using capistrano. I want to deploy the code on a separate folder in my local machine and run migrations after deployment.
The capistrano gems used in the project are as follows
capistrano (3.4.0)
capistrano-bundler (1.1.4)
capistrano-ext (1.2.1)
capistrano-rails (1.1.3)
The application is using ruby 2.1 and rails 4.1
The deploy file is as follows
require 'capistrano/rails/migrations'
lock '3.4.0'
set :application, 'capistrano_study'
set :repo_url, 'https://github.com/xxxxxx/capistrano_study.git'
# config valid only for current version of Capistrano
set :stages, ["staging", "production"]
set :default_stage, "staging"
set :user, "prajeesh"
after "deploy:updated", "deploy:migrate"
namespace :deploy do
after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do
# Here we can do anything such as:
# within release_path do
# execute :rake, 'cache:clear'
# end
end
end
end
staging.rb file as follows.
server 'xx.x.x.xxx', user: 'prajeesh', roles: %w{app db web}, my_property: :my_value
set :deploy_to, "/home/prajeesh/Desktop/projects/capistrano_staging"
Database.yml
development:
adapter: mysql2
encoding: utf8
reconnect: false
database: cap_test_staging
pool: 5
username: root
password: xxxxx
# socket: /var/run/mysqld/mysqld.sock
staging:
adapter: mysql2
encoding: utf8
reconnect: false
database: cap_test_staging
pool: 5
username: root
password: xxxxx
When i run the command cap staging:deploy, the deployment is working fine. The issue is that the migrations are not running after deployment.
Does anyone know how to fix this?
Edit:
This is the error that i am getting.
INFO [175f4b0b] Running /usr/bin/env rake db:migrate as
prajeesh#xx.x.x.xxx
DEBUG [175f4b0b] Command: cd /home/prajeesh/Desktop/projects/capistrano_staging/current && ( RAILS_ENV=development /usr/bin/env rake db:migrate )
DEBUG [175f4b0b] rake aborted!
DEBUG [175f4b0b]
cannot load such file -- bundler/setup
If i run the command RAILS_ENV=development /usr/bin/env rake db:migrate directly from the project path, the migration is running but through capistrano it is not working.
Any help would be appreciated.

Hey you should run the below command to get it run command:
cap deploy:migrate
To get it run, you can see the documentation here
Updated for automating migration:
after "deploy:update_code", "deploy:migrate"
Into the file config/deploy.rb.

You should require capistrano/rails/migrations in your Capfile as mentioned in here. It'll do the trick.

If you're on Capistrano 3, I did
set :migration_role, :app in addition to adding require 'capistrano/rails/migrations' to my deploy.rb file.
(source: capistrano-rails docs)

Related

cannot load such file -- rspec/core/rake_task with capistrano

I'm not ruby on rails. When I launch :
cap integration deploy
I get an error :
INFO [90feb630] Running /usr/local/rvm/bin/rvm ruby-2.4.0#myproject_gemset do bundle exec rake assets:precompile as myproject#myproject-server.com
DEBUG [90feb630] Command: cd /home/myproject/myproject_rails/releases/20170703135523 && ( export RAILS_ENV="staging" RAILS_GROUPS="" ; /usr/local/rvm/bin/rvm ruby-2.4.0#myproject_gemset do bundle exec rake assets:precompile )
DEBUG [90feb630] rake aborted!
LoadError: cannot load such file -- rspec/core/rake_task
Here my capistrano config file for deploying :
set :user, 'myproject'
server 'myproject-server.com',
user: fetch(:user),
roles: %w{web app db},
ssh_options: {forward_agent: true}
set :deploy_to, "/home/#{fetch(:user)}/#{fetch(:application)}"
set :rails_env, 'staging'
set :conditionally_migrate, true
set :keep_releases, 2
set :branch, 'master'
set :app_version, '0.1'
Edit
The issue is from the file /lib/tasks/integration.rake :
require 'rspec/core/rake_task'
namespace :integration do
desc 'integration test the JSON API endpoints'
RSpec::Core::RakeTask.new(:test) do |t|
# set the RAILS_ENV such that :integration tagged
# specs are run
ENV['RAILS_ENV'] = 'test'
# only run those files in the 'integration' directory
t.pattern = './spec/integration{,/*/**}/*_spec.rb'
end
end
The gem 'rspec-core' where only installed in dev / test env.
So it was missing.
Putting
gem 'rspec-core', '~> 3.4'
Out of
group :development, :test do
Solved my issue
I needed to do gem install rspec-core

Rake db:Migrate with Nginx Capistrano

I'm running a server with Nginx, Capistrano, Rails
I made some db:migrations on my local machine and then want to push them to these changes to my server. However I can't figure out how to migrate my database on the server. How do I do this?
I've Tried
1)
cap production deploy
cap production deploy:migrate
2)
[On server - in current]
rake db:migrate
but none of these seem to work. How do I make this migration?
Capistrano File
lock '3.4.0'
require 'capistrano/sidekiq'
set :whenever_command, "bundle exec whenever"
require "whenever/capistrano"
set :application, 'myApp'
set :repo_url, 'git...'
set :keep_releases, 5
set :scm, :git
set :repository, "git..."
set :scm_passphrase, "..."
set :user, "..."
set :use_sudo, false
set :deploy_to, "/.../.../apps/appName"
namespace :deploy do
after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do
end
end
end
1) If you are using capistrano-rails you should set
set :migration_role, 'migrator' # Defaults to 'db'
2) On server you are making migration in development environment, try
RAILS_ENV=production bundle exec rails db:migrate
To run migrations with capistrano, on production.rb file which stays inside /config/deploy you have add "db" role
e.g.
roles: %w{web app db}
also capistrano migrate tasks works if there is a difference between current_path and release_path migrations. what you can do is remove migrations from inside current_path and then deploy and then migrate.

Capistrano 3, Rails 4, database configuration does not specify adapter

When I start
cap production deploy
it fails like this:
DEBUG [4ee8fa7a] Command: cd /home/deploy/myapp/releases/releases/20131025212110 && (RVM_BIN_PATH=~/.rvm/bin RAILS_ENV= ~/.rvm/bin/myapp_rake assets:precompile )
DEBUG [4ee8fa7a] rake aborted!
DEBUG [4ee8fa7a] database configuration does not specify adapter
You can see that "RAILS_ENV=" is actually empty and I'm wondering why that might be happening? I assume that this is the reason for the latter error that I don't have a database configuration.
The deploy.rb file is below:
set :application, 'myapp'
set :repo_url, 'git#github.com:developer/myapp.git'
set :branch, :master
set :deploy_to, '/home/deploy/myapp/releases'
set :scm, :git
set :devpath, "/home/deploy/myapp_development"
set :user, "deploy"
set :use_sudo, false
set :default_env, { rvm_bin_path: '~/.rvm/bin' }
set :keep_releases, 5
namespace :deploy do
desc 'Restart application'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
# Your restart mechanism here, for example:
within release_path do
execute " bundle exec thin restart -O -C config/thin/production.yml"
end
end
end
after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do
within release_path do
end
end
end
after :finishing, 'deploy:cleanup'
end
Database.yml:
production:
adapter: mysql2
encoding: utf8
database: myapp_production
pool: 5
username: user
password: pass
host: localhost
development:
adapter: mysql2
encoding: utf8
database: myapp_development
pool: 5
username: user
password: pass
host: localhost
The issue is resolved if I add
set :rails_env, "production"
to my deploy.rb, but this looks like hardcoding to me and I'm sure there's a nicer solution.
Edit: Per this pull request, it's now fixed in version 1.1.0 of capistrano-rails.
Per this Github issue, another fix is to edit your Capfile. Comment out these two lines
#require 'capistrano/rails/assets'
#require 'capistrano/rails/migrations'
and put this line in
require 'capistrano/rails'
which will correctly set your RAILS_ENV variable.
Using Cap 3 and capistrano_rails on rails 4 I was getting the same error; in the environment file(s) being deployed, I set
set :stage, :production
set :rails_env, 'production' # even though doc says only need to do this if it's different
Doc here: https://github.com/capistrano/rails
Based on Marc's answer which definitely seems to be the right one,
you can workaround this until it is fixed upstream by adding this to your config/deploy.rb in the "namespace :deploy" block:
desc 'Provision env before assets:precompile'
task :fix_bug_env do
set :rails_env, (fetch(:rails_env) || fetch(:stage))
end
before "deploy:assets:precompile", "deploy:fix_bug_env"
This will force loading the env and provisionning RAILS_ENV before assets:precompile is called.
Seems to be a bug in capistrano-rails.
There is a task (rails.rake) that sets the environment either from rails_env or stage:
namespace :deploy do
before :starting, :set_rails_env do
set :rails_env, (fetch(:rails_env) || fetch(:stage))
end
end
But this task isn't called before i.e. assets:precompile. So this:
namespace :assets do
task :precompile do
on roles :web do
within release_path do
with rails_env: fetch(:rails_env) do
execute :rake, "assets:precompile"
end
end
end
end
end
fails because rails_env is nil if it isn't set explicitly.
If I have the time to dig a little deeper I'll file a bug report.
If you're using passenger, you need to add
rails_env production;
in the in web server's (eg: nginx) .conf where you've specified values for passenger_ruby and passenger_root.
What happens if you add a file:
deploy/production.rb
With this line:
set :stage, :production

Capistrano Staging Deploy Requires Whole New Database Migration

I have Capistrano set up such that it allows me to deploy the staging version of my Ruby on Rails website to an amazon server from a git repository successfully. However, after deploying, I must run a migration on the database on the server. If I do not, any page with login forms or database-based content cannot load. When I run the migration on the server, I see every singly migration on the site being migrated, not just the most recent ones.
I know that Capistrano can maintain the previous migrations, and I thought it did that automatically. My question is, how do stop the apparent database wipe or loss which is occurring so that a migration is only needed if there are actually new migrations?
I see no unusual errors in the Capistrano output and I am a novice when it comes to Capistrano and databases. I noticed that my database.yml file has no entry for staging and I was wondering if it could be as simple as adding an entry for staging with the database set to db/development.sqlite3?
here is my deploy.rb file:
set :application, "staging"
set :scm, :git
set :repository, "."
set :deploy_via, :copy
#set :copy_cache, true
set :copy_exclude, [".git"]
set :user, "username"
set :use_sudo, false
default_run_options[:pty] = true
server "server_url", :app, :web, :db, :primary => true
set :deploy_to, "/var/www/staging"
# if you want to clean up old releases on each deploy uncomment this:
set :keep_releases, 3
after "deploy:restart", "deploy:cleanup"
# If you are using Passenger mod_rails uncomment this:
namespace :deploy do
task :start do ; end
task :stop do ; end
task :restart, :roles => :app, :except => { :no_release => true } do
run "touch #{File.join(current_path,'tmp','restart.txt')}"
end
end
And my database.yml file:
# SQLite version 3.x
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem 'sqlite3'
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
adapter: sqlite3
database: db/test.sqlite3
pool: 5
timeout: 5000
production:
adapter: sqlite3
database: db/production.sqlite3
pool: 5
timeout: 5000
Capistrano is not the one that maintains your migration number. rails does. If you want capistrano to run the migrations for you as part of deploy, add this to your config/deploy.rb
after "deploy:update_code", "deploy:migrate"
you should probably have a different location for production sqlite3 file where it will not get rewritten for every deploy, instead of db/production.sqlite3. Something like /home/user/production.sqlite3

What is a good way of Hiding mysql2 password when deploying with capistrano

So, here is my capistrano file
load 'deploy/assets'
require "bundler/capistrano"
set :application, "XXXXXX"
set :repository, "XXXXXX"
set :scm, :git # You can set :scm explicitly or Capistrano will make an intelligent guess based on known version control directory names
# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`
set :repository , "XXXXXX"
role :web, "XXXXXX" # Your HTTP server, Apache/etc
role :app, "XXXXXX" # This may be the same as your `Web` server
role :db, "XXXXXX", :primary => true # This is where Rails migrations will run
#role :db, "your slave db-server here"
set :user, 'root'
set :use_sudo, false
set :deploy_to, "/var/www/#{application}"
set :deploy_via, :remote_cache
set :normalize_asset_timestamps, false
# if you want to clean up old releases on each deploy uncomment this:
# after "deploy:restart", "deploy:cleanup"
# if you're still using the script/reaper helper you will need
# these http://github.com/rails/irs_process_scripts
# If you are using Passenger mod_rails uncomment this:
namespace :deploy do
task :start do ; end
task :stop do ; end
task :restart, :roles => :app, :except => { :no_release => true } do
run "touch #{File.join(current_path,'tmp','restart.txt')}"
end
end
Now when i run cap deploy i get an error
Access denied for user 'root'#'localhost' (using password: NO)
I am assuming thats because my database.yml file is
development:
adapter: sqlite3
database: db/development.sqlite3
pool: 5
timeout: 5000
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
adapter: sqlite3
database: db/test.sqlite3
pool: 5
timeout: 5000
production:
adapter: mysql2
encoding: utf8
database: XXXXX
username: root
password:
socket: /tmp/mysql.sock
Now since i have a public github account. I dont want to pass in my password and publish it to a github. And if I dont pass in the password i am unable to deploy the app.
What is a good way to handle this problem?
Thanks
You'll also want to make sure that your SSH system is well secured to prevent people from logging in as your Capistrano bot. I'd suggest restricting access to password-protected key pairs.
Encrypting the .yml file on the server is useless since you have to give the bot the key, which would be stored . . . on the same server. Encrypting it on your machine is probably a good idea. Capistrano can decrypt it before sending.
or
The way I have tackled this is to put the database password in a file with read permissions only for the user I run my application as. Then, in database.yml I use ERB to read the file:
production:
adapter: mysql
database: my_db
username: db_user
password: <%= begin IO.read("/home/my_deploy_user/.db") rescue "" end %>
I would recommend the following:
Move config/database.yml to config/database.yml.sample in your repo
Remove any sensitive information in config/database.yml.sample, such as passwords, and
commit the "sample" config file to your repo.
Add config/database.yml to your .gitignore file, so it cannot be committed to the repo
On your server, manually copy config/database.yml.sample to config/database.yml in your shared/ directory that Capistrano creates for you. This should be done after you run the cap deploy:setup command, which creates the top-level shared and releases directories. This should just be done once, manually, when setting up your application.
In shared/config/database.yml on the server, fill in the actual DB details, including passwords. chmod the file so it isn't readable by those who should not have access.
Add the following to your deploy script:
namespace(:customs) do
task :symlink_db, :roles => :app do
run <<-CMD
ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml
CMD
end
end
after "deploy:update_code", "customs:symlink_db"

Resources