前回、HerokuにNancyアプリをデプロイしましたが、各種設定はコマンドラインから1つずつ行いました。
ただ、やり方を忘れそうな気がしたためツールを探してみたところ、Rubyのgemで heroku_san
がありました。
fastestforward/heroku_san · GitHub
そこで、RailsやSinatraで使っている記事はあったものの、他の環境ではどんなふうに使うのだろうと試してみることにしました。
環境
- Windows7 x64
- Ruby 2.1.5
- gem
- heroku_san 4.3.2
- albacore 2.3.15
- NuGet
- FluentMigrator 1.4.0.0
- FluentMigrator.Tools 1.4.0.0
- Npgsql 2.2.3
- Heroku addon
- Heroku Postgres
- Heroku Toolbelt 3.23.1
C#アプリの作成
今回はDBのマイグレーションだけができれば良いので、Nancyではなくコンソールアプリケーションを作ります。
作業内容は以下の通りです。
- Npgsqlパッケージの追加
- NuGetパッケージの復元を有効化
- 以下のファイルをリンクとして追加し、プロパティの出力を「常に出力」へと変更
- FluentMigrator.Runner.dll
- Migrate.exe
- FluentMigratorのマイグレーションファイルを作成
作成が終わったら、ひとまずGitにコミットしておきます。
Gemのインストール
heroku_san
は開発環境で使用するgemであることに注意して、Gemfileを用意します。
source 'https://rubygems.org' ruby '2.1.5' group :development do gem 'heroku_san' end gem 'albacore'
あとはbundle install --path vendor/bundle
でインストールします。
heroku.ymlを用意
heroku:create_config
を実行するためのRakefileを用意
READMEに従ってbundle exec rake heroku:create_config
を実行してもエラーになります。
$ bundle exec rake heroku:create_config rake aborted! No Rakefile found (looking for: rakefile, Rakefile, rakefile.rb, Rakefile.rb)
そのため、Sinatraと同じようにRakefileを用意することになります。READMEのRakefileを見ると、
HerokuSan.project = HerokuSan::Project.new(config_file, :deploy => HerokuSan::Deploy::Sinatra)
とあり、Sinatraではないアプリの場合はdeployに何を指定すれば良いのか分かりませんでした。
そこで、コードを読んだところ、heroku_san/sinatra.rb at master · fastestforward/heroku_san · GitHub にある通り、Sinatraを指定してもスーパークラスのメソッドを呼んでるだけということが分かりました。
そのため、今回はスーパークラスであるHerokuSan::Deploy::Base
を指定し、以下のようなRakefileを作成しました。
require "bundler/setup" begin require "heroku_san" config_file = File.join(File.expand_path(File.dirname(__FILE__)), 'config', 'heroku.yml') HerokuSan.project = HerokuSan::Project.new(config_file, deploy: HerokuSan::Deploy::Base) load "heroku_san/tasks.rb" rescue LoadError # The gem shouldn't be installed in a production environment end
heroku.ymlを作成・編集
準備ができたので、再度、bundle exec rake heroku:create_config
を実行しますが、エラーになります。
$ bundle exec rake heroku:create_config rake aborted! Errno::ENOENT: No such file or directory @ rb_sysopen - path/to/project/config/heroku.yml ... Tasks: TOP => heroku:create_config
ディレクトリがないため、ディレクトリを作成後、再度実行します。
$ mkdir config $ bundle exec rake heroku:create_config Copied example config to "path/to/project/config/heroku.yml" Please edit "path/to/project/config/heroku.yml" with your application's settings.
無事にできたので、heroku.yml
ファイルを編集します。
今回はHerokuにRubyとMonoの環境のための環境変数BUILDPACK_URL
と、アドオンのHeroku Postgresの設定を記述します。なお、アプリ名はherokusan-fm-201501
としました。
production: app: herokusan-fm-201501 stack: cedar config: BUILDPACK_URL: "https://github.com/heroku/heroku-buildpack-multi" addons: - heroku-postgresql:hobby-dev
.gitignore
への追記
heroku.yml
ファイルは開発環境でしか使わないため、.gitignore
に記載しておきます。
Herokuアプリを作成
Herokuにログイン
$ heroku login Enter your Heroku credentials. ... Authentication successful.
これ以降は、herokuコマンドとheroku_san、どちらでも作成できます。
herokuコマンドの場合
アプリの作成と、リモートの設定をしてくれます。
$ heroku create herokusan-fm-201501 $ git remote heroku
heroku_sanを使う場合
アプリの作成とリモートの追加を行います。リモートの追加を忘れるとエラーになるので注意します。
$ bundle exec rake all heroku:create production: Created herokusan-fm-201501 $ git remote $ bundle exec rake all heroku:remotes git remote add production git@heroku.com:herokusan-fm-201501.git $ git remote production
なお、この段階では環境変数やアドオンなどは追加されていません。
$ heroku config --app herokusan-fm-201501 herokusan-fm-201501 has no config vars. $ heroku addons --app herokusan-fm-201501 herokusan-fm-201501 has no add-ons.
デプロイ前に環境変数やアドオンを追加
以下のコマンドで環境変数やアドオンを追加できますが、コマンドの実行し忘れが発生しそうです。
$ bundle exec rake all heroku:config $ bundle exec rake all heroku:addons
参考: Easily deploy to multiple environments on Heroku with heroku_san | Adventures In Coding
そのため、なにかよい方法を探してみたところ、Wikiに after_deploy
の例が載っていました。
Updating a REVISION environment variable · fastestforward/heroku_san Wiki · GitHub
同じようにしてbefore_deploy
で追加作業ができるのではないかと考え、ソースコードを見たところ、HerokuSan::Stage
にいくつか便利そうなメソッドがありました。
heroku_san/stage.rb at a36789b7f66fd3d234097714c534a762b4a2aa89 · fastestforward/heroku_san · GitHub
それを使って、before_deploy
のtaskをRakefileへ追記しました。
task :before_deploy do each_heroku_app do |stage| # push_configでは、以下の値を環境変数に設定 # ・引数なしは`heroku.yml`の内容、 # ・引数ありは引数で指定した値 stage.push_config stage.push_config(CONFIG_BY_RAKEFILE: :heroku_san_rakefile) # 例なので、無くても良い # `heroku.yml`のアドオンを追加 stage.install_addons end end
デプロイ後にFluentMigratorを実行する
Rakefileの追記
デプロイ後にFluentMigratorを忘れずに実行したいため、同様にして、after_deploy
のtaskをRakefileに追記します。
task :after_deploy do each_heroku_app do |stage| # albacoreによるFluentMigratorの実行 stage.run "rake", "db:migrate" end end
FluentMigratorを実行するRakefileの用意
以前の記事で使用したRakefileを流用し、exeファイル名などを変更します。
FluentMigrator.rake
という名前にて、path/to/project/rakelib
ディレクトリの中に保存します。
Rakeでは、rakelibディレクトリにRakefileを置いておけば、自動的にインポートするようです。
library rake - Ruby 2.1.0 リファレンスマニュアル
.buildpacks
ファイルの追加
RubyとMono用のbuildpackのURLを書いた.buildpacksを用意します。
https://github.com/friism/heroku-buildpack-mono.git https://github.com/heroku/heroku-buildpack-ruby.git
ここまででデプロイする準備ができたので、Gitにコミットします。
デプロイ
bundle exec rake production deploy
を実行してデプロイし、FluentMigratorの実行を確認します。
$ bundle exec rake production deploy ... git update-ref refs/heroku_san/deploy HEAD^{commit} ... =====> Detected Framework: .NET ... =====> Detected Framework: Ruby ... Running `rake db:migrate` attached to terminal... up, run.365 ... [+] Task completed.
アドオンなども追加されています。
$ heroku addons === herokusan-fm-201501 Configured Add-ons heroku-postgresql:hobby-dev HEROKU_POSTGRESQL_ORANGE scheduler:standard $ heroku config === herokusan-fm-201501 Config Vars BUILDPACK_URL: https://github.com/heroku/heroku-buildpack-multi CONFIG_BY_HEROKU_YML: heroku_yml CONFIG_BY_RAKEFILE: heroku_san_rakefile ...
ソースコード
GitHubに上げてあります。heroku.yml
は、heroku.example.yml
になっているため、名前を変更して使います。
thinkAmi-sandbox/heroku_san-FluentMigrator-sample · GitHub