29 May 2013

RefineryCMS 2.x app on Heroku Cedar Stack

This cheatsheet will show you the steps and changes I take to get a RefineryCMS 2.x / Rails 3.2.x app started on Heroku's awesome Cedar Stack. All new Heroku projects should be started on Cedar (not Bamboo) because this is where the burgeoning power of Heroku is taking place. Cedar gives you much more flexibility and power in specifying what your gems and execution stack.

How to

Follow RefineryCMS 2.0 download & install instructions.
Cedar requires you to use foreman (and thin) to run the project locally on your dev machine. That means the following addition to Gemfile (plus a couple of extras; make sure you have heroku):
   gem 'thin'
   gem 'fog'
 group :development  do
   gem  'foreman'
   gem  'erubis'
   gem  'heroku'
You'll need to create a Procfile in the project directory. Heroku requires this as well, so it needs to be part of the git repository. There's just one line in the file:
web: bundle exec rails server thin start -R config.ru -p $PORT -e $RACK_ENV/$RAILS_ENV
And I find it helpful to have a ./.foreman config file (in your project directory) to specify the port for the server (otherwise on my machine it defaults to port=5000). Again, just one line in the file:
port: 3000
To test your app locally, instead of $ rails s do the following:
$ foreman start
Once you've verified that everything is running correctly locally proceed to the next steps.
Make sure git has been set up and you've committed all your changes.
Now you're ready to create a new cedar stack on heroku. Make sure your heroku CLI is the latest version. In this example, I'm creating a heroku app called "kikapu".
$ heroku apps:create --stack cedar kikapu
Creating kikapu... done, stack is cedar
http://kikapu.herokuapp.com/ | git@heroku.com:kikapu.git
Git remote heroku added
$ git push heroku

Compiling assets locally for heroku

If you rely on heroku to precompile assets at time of slug generation, you'll run into a sticky error:
-----> Preparing Rails asset pipeline
       Running: rake assets:precompile
       ERROR: Unable to connect to memcached
       Precompiling assets failed, enabling runtime asset compilation
       Injecting rails31_enable_runtime_asset_compilation
It appears that Rails 3.2 now automatically does an ActiveRecord cache clear which forces a DB connection attempt during App initialization which is the cause of this failure (see the heroku article below for further details). Forturnately, there is a work-around which is to manually precompile assets; instructions given below.
(The following section has been taken directly from the hard-to-find heroku troubleshooting article: http://devcenter.heroku.com/articles/rails3x-asset-pipeline-cedar)
"If a public/assets/manifest.yml is detected in your app, Heroku will assume you are handling asset compilation yourself and will not attempt to compile your assets. To compile your assets locally, run the assets:precompile task locally on your app. Make sure to use the production environment so that the production version of your assets are generated."
You'll need to slightly change your Gemfile, and move
gem 'sass-rails',   '~> 3.2.3'
out from within the group :assets do .. end section, because we have to compile the assets in production environment and sass-rails won't be there. We need it because it contains the all-important image-url() method which we use within our stylesheet.sass to get the correct url to the image assets (see Rails Asset Pipeline Guide).
$ RAILS_ENV=production bundle exec rake assets:precompile
"A public/assets directory will be created. Inside this directory you’ll find a manifest.yml which includes the md5sums of the compiled assets. Adding public/assets to your git repository will make it available to Heroku.
$ git add public/assets
$ git commit -m "vendor compiled assets"
"Now when pushing, the output should show that your locally compiled assets were detected:"
-----> Preparing Rails asset pipeline
       Detected manifest.yml, assuming assets were compiled locally
Next on heroku, do the following:
$ heroku run rake db:create
$ heroku run rake db:migrate
$ heroku run rake db:seed
Then you can checkout your site at (fill in y our project name for project, below):

Enabling S3 resource storage

Since Heroku doesn't have local persistence (for images or other attached resources), you'll need to set up S3 on amazon and then add config variables to heroku for your app. Refinery core is already to use these new settings.
heroku config:add S3_BUCKET=my_bucket S3_KEY=AXXXXXXXXXXXXCA S3_SECRET=8ikjhgjkhgkjgkjggjkkgh062

Deprecation Warnings at Heroku

You'll get the following deprecation warning when running rake tasks on your app at heroku. Even if you don't have plugins, Heroku has installed a few vendor/plugins into your slug, which is the cause behind this deprecation.
DEPRECATION WARNING: You have Rails 2.3-style plugins in vendor/plugins! 
Support for these plugins will be removed in Rails 4.0. 
Move them out and bundle them in your Gemfile, or fold them in to your app 
as lib/myplugin/* and config/initializers/myplugin.rb. 
See the release notes for more on this: