Show Rakefile errors in Ruby deploys

Change effective on 05 December 2013

Add debug output to deploys using the Ruby build pack. There is no change in deploy functionality. To better understand this change it helps to look at prior behavior.

Previous behavior

Previously the Ruby buildpack did not have a way to detect if there were errors in a Rakefile. It would detects if a task is available by executing the task with —dry-run e.g.:

$ rake assets:precompile --dry-run

This task can return a non zero status if the assets:precompile task does not exist or if there is an error in the Rakefile. Two common cause of errors in the Rakefile are referencing a dependency not available in production such as rspec or expecting an environment variable to be present. As we have no way of knowing which reason the command failed, we previously assumed it was because the task was not defined. The deploy would continue and we would not attempt to run rake assets:precompile.

The previous behavior caused confusion when a developer accidentally introduced an error into their Rakefile, causing their assets to not longer compile. In addition, they would see no debug output in the push and their app (minus the assets) would successfully deploy.

Current behavior

This fix changes the detection behavior by separating out the verification of a valid Rakefile and the presence of tasks. Now if we detect that there is an error in the Rakefile we will emit the error and the backtrace for debugging purposes. When this happens we will not cancel the build, instead it will continue and the assets:precompile task will be skipped unless you manually cancel the build (CTRL+C). This change preserves the prior behavior but adds debugging information and clarity around why your app is no longer compiling assets.

The decision to not error out when we find a Rakefile with an exception may be curious but this is done for compatibility reasons. The same build pack supports all Ruby deploys, not just Rails deploys. There are currently developers who do not intend for Heroku to run Rake tasks on their app and to them continuing with a deploy is the desired behavior. Changing this behavior would break their deploys.

If someone’s Rakefile is valid, and we detect assets:precompile we will run it. If the assets:precompile exists but the command fails we cancel the build. This is to prevent apps that require assets (almost all that have assets:precompile declared) from going into production with non-functioning assets.

The error

If you have an error in your Rakefile, you will see an output similar to this:

Could not detect rake tasks
ensure you can run `$ bundle exec rake -P` against your app with no environment variables present
and using the production group of your Gemfile.
This may be intentional, if you expected rake tasks to be run
cancel the build (CTRL+C) and fix the error then commit the fix:
#...

To be clear, although you will see a backtrace your application will continue to deploy. You can stop it manually by running CTRL+C