web-dev-qa-db-ja.com

Rails 3 and Heroku:プッシュ時に自動的に "rake db:migrate"?

私はherokuのプッシュ/デプロイプロセスに多少の不満を感じています。

アプリに新しい移行を追加する場合、Herokuサーバーに移行する唯一の方法は、Herokuリモートへのプッシュを実行することです。これによりアップロードされ、アプリが再起動します。ただし、移行は実行されないため、heroku rake db:migrate --app myappを実行し、次にheroku restart --app myappを実行する必要があります。それまでの間、アプリは移行を実行しておらず、コードは移行中のフィールド/テーブルなどを参照しているため、壊れています。

展開プロセスの一部としてrake db:migrateを自動的に実行するように展開プロセスを変更する方法が必要ですが、解決できません。

Heroku cpanelで設定したものですか?コマンドラインからherokuに渡すオプションですか? gitフックですか?誰でも私をまっすぐに設定できますか?おかげで、最大

61
Max Williams

以下は、すべてをワンライナーにまとめる(およびロールバックもサポートする)レーキタスクです。

https://Gist.github.com/36287

あなたはまだ上司のデモの上に展開する可能性がありますが、少なくともgit Push そしてその rake db:migrate

29

Herokuは、これを「リリースフェーズ」機能の一部としてこれを処理できるようになりました。

releaseというプロセスをProcfileに追加できます。このプロセスは、デプロイのたびに実行されます。

レール> = 5例

release: bundle exec Rails db:migrate

レール<5例

release: bundle exec rake db:migrate

34
Max Woolf

この単純なコマンドチェーンソリューションについてはどうですか。

git Push heroku master && heroku run rake db:migrate

最初の移行が正常に終了するとすぐに、移行が自動的に実行されます。通常、1-2秒以下の遅延です。

32
Cristian

カスタムビルドパック を作成し、Herokuでrake db:migrate展開時に自動的に。これはHerokuのデフォルトRuby buildpackのフォークですが、rake db:migrateタスクが追加されました。

アプリで使用するには、次のようにします。

heroku config:set BUILDPACK_URL=https://github.com/dtao/rake-db-migrate-buildpack

また、機能するためには、user-env-compileHeroku Labs機能を有効にする必要があることに注意してください。その方法は次のとおりです。

heroku labs:enable user-env-compile

そして、これがこれが機能するという私の証拠です:

rake db:migrate on Heroku deployment

14
Dan Tao

おそらく、スキーマコミット(移行など)のコミットとコードコミット(モデル、検証など)を分離してみてください。

(以下は、移行の変更が破壊的ではないと想定していることに注意してください。これは、ユースケースのほとんどをカバーしていることを示しているためです。)

展開プロセスは次のようになります。

  1. スキーマの変更をHerokuにプッシュする
  2. 移行する
  3. アプリケーションコードをHerokuにプッシュする

これはもちろん最適な形ではありませんが、説明した状況でのダウンタイムを回避するための効果的な方法です。動的フィールドのコードをアプリが受信するまでに、DBは既に移行されています。

(もちろん、最も簡単な解決策は、上司が昼食に出ている間にプッシュして移行することです;-D)

そうしないと、スキーマの変更が自動的に実行された場合でも、移行が実行される直前にリクエストが通過するリスクがあります。

9
David Sulc

私のようなグーグルの人々のためだけに、ここで簡単な解決策を提供したいと思います。

Rails 4を使用しており、単純なRakeタスクをherokuへのデプロイに追加する必要がありました。githubの[herokuにデプロイ]ボタンを使用しているため、 "heroku run ...」展開直後。

私がやったこと:I 標準のRakeタスク 'assets:clean'を拡張 herokuへのデプロイ中に自動的に実行されます。タスクは引き続き正常に実行されますが、最後に自分のものを添付しました。これは'enhance'メソッドで行われます。以下の例では、db:migrateを追加します。これはおそらくほとんどの人が望むものだからです。

# in lib/tasks/assets_clean_enhance.rake
Rake::Task['assets:clean'].enhance do
  Rake::Task['db:migrate'].invoke
end

これは完璧な解決策ではないことを認めます。しかし、heroku Ruby Buildpackはまだ他の方法をサポートしていません。そして、自分のビルドバックを書くことは、とても単純なことのためにちょっとやり過ぎに見えました。

5
Kari

SmartMigrate buildpack を作成しました。これは、新しい移行が検出されるたびにRubyビルドの後にビルドを保留することを警告する単純なHerokuビルドパックです。このビルドパックはマルチパックの一部です先行するRuby buildpack。

ここで他のソリューションに敬意を払って、このビルドパックにはそれらよりも3つの利点があります。

  1. メンテナンスモードは不要
  2. 時代遅れのRubyは、最後に移行を挿入するだけのbuildpackフォークを必要としません
  3. 常に移行を実行する必要はありません。最後の展開以降に新しい移行が検出された場合にのみ警告が表示されます
2
hammady

レーキタスクを使用してアプリをメンテナンスモードにし、プッシュ、移行、メンテナンスモードからアプリを移動します。

2
Aditya Sanghi

David Sulcのアプローチは、アプリが壊れた状態にある間、リクエストが通過しないようにする唯一のアプローチだと思います。

これは少し苦痛ですが、状況によっては必要になる場合があります。

彼が述べたように、データベースの移行は非破壊的である必要があります。

ただし、明らかなアプローチ( 'git Push heroku {revnum}')は、残りのコードの前に移行をチェックインすることに依存しているため、移行とスキーマの変更を残りのコードの前にプッシュすることは困難です。

まだ行っていない場合でも、一時的なブランチを使用してこれを行うことができます。

  • 最近herokuにプッシュしたgitリビジョンに基づいてブランチを作成します。

    git branch <branchname> <revnum-or-tag>
    
  • そのブランチをチェックしてください:

    git checkout <branchname>
    
  • Db移行のコミットに移行のみが含まれ、コードの変更が含まれていない場合、データベースの変更を含むコミットを選択します。

    git cherry-pick <revnum1> <revnum2>...
    
  • コードの変更も含むリビジョンでdbの変更をコミットした場合、「git cherry-pick -n」を使用できますが、これは自動的にコミットしません。 'git reset HEAD'を使用して、コミットされる予定のセットからdbの変更ではないファイルを削除します。dbの変更のみを取得したら、それらをコミットします一時的なブランチ。

    git cherry-pick -n <revnum1> <revnum2>...
    git reset HEAD <everything that's modified except db/>
    git status
    ... check that everything looks ok ...
    git commit
    
  • この一時的なブランチをherokuにプッシュします(ダウンタイムを回避することがこれらのフープをジャンプすることの全体的なポイントであるため、ステージングアプリに問題がないことを確認します)

    git Push heroku <branchname>:master
    
  • 移行を実行する

    heroku run rake db:migrate
    
  • この時点で、 'master'をherokuにプッシュするだけでコードの変更を取得できると考えるかもしれません。ただし、早送りマージではないため、できません。続行する方法は、「master」の残りを一時的なブランチにマージし、それをマスターにマージして、2つのブランチのコミット履歴を再結合することです。

    git checkout <branchname>
    git merge master
    git diff <branchname> master
    ... shouldn't show any differences, but just check to be careful ...
    git checkout master
    git merge <branchname>
    
  • これで、通常どおりmasterをherokuにプッシュできます。これにより、コードの残りの変更が反映されます。

最後から2番目のステップでは、masterを{branchname}にマージする必要があるかどうか100%確信できません。そのようにすることで、「早送り」マージが確実に行われ、herokuにプッシュしたときにgitが幸せになりますが、{branchname}をそのステップなしでマスターにマージするだけで同じ結果が得られる可能性があります。

もちろん、「マスター」を使用していない場合は、上記の関連する場所で適切なブランチ名に置き換えてください。

1
sheltond

しばらくの間、展開ツールとして heroku_san gemを使用しています。これは、Push +移行のための小さくて焦点の合った素敵なツールです。他の機能(コンソールなど)へのアクセスを簡単にする他のrakeコマンドを追加します。データベースの移行を覚える必要がないことに加えて、私のお気に入りの機能はHeroku構成ファイルです。したがって、すべてのサーバー(運用、ステージング、playground4、shirley)に好きな名前を付けて、まっすぐに保管できます。

0
slothbear