-
Notifications
You must be signed in to change notification settings - Fork 269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deploy new applications with db:schema:load #118
Comments
Just ran into this myself. Didn't notice before because I hadn't deployed any old applications on new servers lately. I think it's debatable whether it should attempt P.S. @Odaeus, hello old friend. 😉 |
Hello James! I ended up adding the following to my deploy.rb: namespace :deploy do
namespace :db do
desc "Load the database schema if needed"
task load: [:set_rails_env] do
on primary :db do
if not test(%Q[[ -e "#{shared_path.join(".schema_loaded")}" ]])
within release_path do
with rails_env: fetch(:rails_env) do
execute :rake, "db:schema:load"
execute :touch, shared_path.join(".schema_loaded")
end
end
end
end
end
end
before "deploy:migrate", "deploy:db:load"
end I agree it should be a manual task with the option of making it automatic, given that it could cause issues with a production database. My example above uses a hidden file as a guard to make sure it only runs once. |
Just saw this: https://stackoverflow.com/questions/35821777/rails-how-to-set-up-dbschemaload-for-initial-deploy-with-capistrano Which made me look for this issue. My thoughts:
For any case where the database has no schema version information, it is probably more correct to run schema (or structure) load instead of running migrations. I'm not sure how we might go about finding out whether the database has had the schema loaded yet, but it would ideal to query this and decide based on that which method to run. If someone wants to flesh out conceptually how this might be done, I can possibly take a crack at a PR. |
Typically (in my experience) the user that is running the Rails app is a non-privileged user that does not have permission to create databases. The initial step of creating the database is thus done outside of the Capistrano deploy, which probably explains why this not entirely straightforward. Personally, I try to make sure migrations always work back to the beginning because you never know when you might need to restore an old database backup and migrate it. But, I completely understand that I'm in the minority and |
I'm not sure either. My usual case is that the database already exists, but is completely empty. It would probably be ideal to be able to run |
Maybe you could do a trick like:
And put that inside a Capistrano |
⬆️ That's an expensive test because it needs to load the Rails environment, so never mind. |
We could modify the implementation of the Then, we have a special rake task,
And then do something similar for This is solution is a bit out of the ordinary, though; I can't think of another Capistrano plugin that uses additional task names on the command line preceding Another option would be to make a special Or use an environment variable:
I dunno, none of these approaches feels exactly right. |
Brainstorming here: What if in Capistrano proper, a task called This would then be documented as such. Does this sound any better? |
You still need the variable trick, though, which doesn't feel particularly elegant: before "deploy:first_time", "rails:first_time" do
set :rails_load_schema, true
end
before "db:migrate", "db:load_schema" do
if fetch(:rails_load_schema)
# rake db:schema:load
end
end |
Could you add a task in a task? before "deploy:first_time", "rails:first_time" do
before "db:migrate", "db:setup"
end
task "db:setup" do
# rake db:schema:load
end I haven't tried this. |
Perhaps slightly better: This is sort of like the special |
Yes, I think that would work, too. |
Just checking in, any formal solution/tasks within Capistrano for this? Having to ssh into server to load schama for cold starts on old apps does not seem right. |
No, not to my knowledge. |
In the way-back machine, Capistrano had a "deploy:cold". In Capistrano 3.10.1, I definitely wouldn't like every deploy to consider wiping the database and then skip it based on a semaphor file. That feels way too dangerous to me. |
You could run
And then in your task "deploy:db:load" do
on primary :db do
within release_path do
with rails_env: fetch(:rails_env) do
execute :rake, "db:schema:load"
end
end
end
end
before "deploy:migrate", "deploy:db:load" if ENV["COLD"] Maybe? |
Edit: I definitely wouldn't like every deploy to consider wiping the database and then skip it |
I think all what we need here is to call Anyway, this issue should be resolved. It is an official rails tasks for Capistrano. Having the first deploy always to be failed (because database is not created) and going to the server to manually type Or at least add to the README info about the assuming fail at the first deploy, so the Capistrano newbies will not be so scared when it's happen. |
I find that |
Right now I don't want to automate It's OK that capistrano-rails leaves some things up to the individual developer. For example, we can't provide a
Agreed. @vifreefly would you be interested in opening a PR for that? |
@mattbrictson Thanks, I see your point. In this case, we can probably add another task This task will not be executed by default, but anyone (if it's ok for them) will be able to simply add the hook |
About Maybe |
Don't describe required extensions in migrations? |
Ok, what is a right way then? |
Ouch. Pardon me. It really was a question. It probably sounded a little glib. Excuse me. And also this is a little orthoganal to the thread. Maybe we should take it offline? Now I've read the doc for the extension you referenced and see that they suggest exactly that, using a migration. Indeed, on a fresh install, those The right way? Wow. Would it be great if the structure dump captured those? Assuming they don't (and that might not be possible as it might not be standardized). Would it serve to work it into the database install and provisioning of the DB box? The doc does go on to say that the extension installation methods vary across OS's. Please excuse me for a. pouncing on that and b. diverting this thread. The rails guide advice quoted in the original issue description: I think it's solid advice. |
Hi, |
@mulaiko you have solutions in the thread which you can adapt. Here is my current version, using an explicit # adapted from https://gist.github.com/wacaw/657744af41dcf4963646
namespace :deploy do
desc "Load the initial schema - it will WIPE your database, use with care"
task :db_schema_load do
on roles(:db) do
puts <<~WARN
************************** WARNING ***************************
If you type [YES], rake db:schema:load will WIPE your database
any other input will cancel the operation.
**************************************************************
WARN
ask :answer, "Are you sure you want to WIPE your database?: "
if fetch(:answer) == 'YES'
within release_path do
with rails_env: fetch(:rails_env) do
execute :rake, 'db:schema:load'
end
end
else
puts "Cancelled."
exit
end
end
end
end
if ENV["RUN_DB_SCHEMA_LOAD"] == '1'
before "deploy:migrate", "deploy:db_schema_load"
end Hope this helps! |
This needed when deploying to a server for the first time or when you want to wipe out a database. The issue I'm fixing is this. Things have evolved and in https://github.com/coopdevs/timeoverflow-provisioning we no longer set things up to enable PostgreSQL extensions such as `pg_trgm`. Because Capistrano runs `db:migrate` when deploying very old migrations like `db/migrate/00000000000002_setup_pg_trgm.rb` don't work anymore. I prefer to make this step explicit in the code and with some context rather than having to do this manually in the server and let the dev in charge figure it out every time. Apparently, from capistrano/rails#118 I see this is a known issue for which there's no provided solution. I copied a solution proposed by a capistrano/rails member so should be good. Just run it as follows: ``` $ bundle exec cap staging deploy COLD=1 ```
This needed when deploying to a server for the first time or when you want to wipe out a database. The issue I'm fixing is this. Things have evolved and in https://github.com/coopdevs/timeoverflow-provisioning we no longer set things up to enable PostgreSQL extensions such as `pg_trgm`. Because Capistrano runs `db:migrate` when deploying very old migrations like `db/migrate/00000000000002_setup_pg_trgm.rb` don't work anymore. I prefer to make this step explicit in the code and with some context rather than having to do this manually in the server and let the dev in charge figure it out every time. Apparently, from capistrano/rails#118 I see this is a known issue for which there's no provided solution. I copied a solution proposed by a capistrano/rails member so should be good. Just run it as follows: ``` $ bundle exec cap staging deploy COLD=1 ```
I had to change the line to this in production: |
Hello,
I see that someone requested this feature for a different reason and it was denied. I don't understand the reason for dismissal, as the source of truth for the database schema is the
/db/schema.rb
or/db/structure.sql
file. Migrations are only designed to manage changes to the database and it seems a waste to run the entire migration history when deploying a new application. Also it should be possible to delete old migrations if an application has a great many.Any chance you would reconsider this position?
The text was updated successfully, but these errors were encountered: