Skip to content
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

For Rails apps, only run migrations and restart after deploy if migrations pending #154

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

lyahdav
Copy link

@lyahdav lyahdav commented Jul 24, 2013

This only works for postgresql setups. Fixes #5.

@lyahdav
Copy link
Author

lyahdav commented Jul 24, 2013

I should add, the reason I implemented this as a memoized function on the Stage class is so that it can easily be used in the before_deploy and after_deploy hooks. We need this on a Heroku project where we enable maintenance mode and do a couple other things in the before_deploy if there are pending migrations. Then in the after_deploy we clean up (disable maintenance mode) if there were pending migrations.

@jturkel
Copy link

jturkel commented Aug 8, 2013

This is an awesome feature and one I would find really useful too! I'm not sure why but the psql command in your pull request didn't work for me. This worked for me (basically just copied what the heroku toolbelt was doing):

def remote_migrations
  database_uri = URI.parse(long_config['DATABASE_URL'])
  begin
    ENV['PGPASSWORD'] = database_uri.password
    ENV['PGSSLMODE']  = 'require'
    psql_cmd = "psql -U #{database_uri.user} -h #{database_uri.host} " \
        "-p #{database_uri.port || 5432} #{database_uri.path[1..-1]}"
    `#{psql_cmd} -Atc "SELECT * FROM schema_migrations;"`.split.map(&:to_i)
  ensure
    ENV.delete('PGPASSWORD')
    ENV.delete('PGSSLMODE')
  end
end

This approach has the added benefit of being slightly more secure since the database password isn't included in the psql command line.

Another thing I found useful was basing the state of required migrations on the migration source code rather than the state of my local database (which can occasionally get out of sync when switching between branches). With the approach the change looks more like this (leaving out your checking for Rails and Postgres for brevity):

# Returns true if the remote DB has pending migrations and false if not.
def has_pending_migrations
  @has_pending_migrations ||= (local_migrations - remote_migrations).present?
end

private

# returns an array of schema migration versions in the local source directory
def local_migrations
  ActiveRecord::Migrator.migrations(ActiveRecord::Migrator.migrations_paths).map(&:version)
end

I'm curious to hear your thoughts on this approach.

@lyahdav
Copy link
Author

lyahdav commented Aug 20, 2013

Sorry for taking long to respond. I like your changes. I'll work on making those changes now.

Liron Yahdav added 2 commits January 20, 2014 18:26
… are pending migrations. This only works for postgresql setups.
…olbelt does. Get local migrations from source code rather than local database state.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Should not restart if migrate does nothing
2 participants