thatcanadian
thatcanadian

Reputation: 140

Installing a gem bundle in a python app on Heroku

I have a Python app on Heroku running with Django. The app launches and works perfectly. The first couple lines of a push look like this:

(venv)➜  djangoproject git:(development) ✗ git push
Counting objects: 33, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (21/21), done.
Writing objects: 100% (21/21), 1.96 KiB, done.
Total 21 (delta 15), reused 0 (delta 0)

-----> Heroku receiving push
-----> Python/Django app detected
...

I need to install a gem program on the dyno (specifically, Compass).

Heroku's instructions are to provide a Gemfile and Gemfile.lock in the root directory with the required gems. As soon as I provide this, however, Heroku thinks the app is a Ruby app:

(venv)➜  djangoproject git:(development) ✗ git push
Counting objects: 33, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (21/21), done.
Writing objects: 100% (21/21), 1.96 KiB, done.
Total 21 (delta 15), reused 0 (delta 0)

-----> Heroku receiving push
-----> Ruby app detected (NOTE: this is paraphrased)
...

Is there any way I can install a ruby gem while running the site as a Python/Django app?

Upvotes: 3

Views: 848

Answers (3)

andywineio
andywineio

Reputation: 610

You need to use custom buildpack that allows you to build both ruby and python dependencies.

  1. heroku config:add BUILDPACK_URL=https://github.com/mandest/heroku-buildpack-rubypython
  2. Add a Gemfile to your project Run bundle install locally (to create
  3. Gemfile.lock file) Push your Gemfile and Gemfile.lock to heroku

That should first install ruby, then run bundle install, then install python, and all deps in the requirements.txt file.

Howeve, in my case, I also wanted to run some commands using ruby libraries, namebly SASS/COMPASS. In order to do that, you have two options I think. First one, is to fork above repository and add running those commands in the build (this way they have all needed privileges rather than you running heroku run ...).

The second options is to add a Rakefile and specify those things in rake assets:precompile task.

So, in my case with Compass the Rakefile looks like:

require 'yaml'
require 'pathname'
require 'rspec/core/rake_task'
include FileUtils


namespace 'assets' do
  desc 'Updates the stylesheets generated by Sass/Compass'
  task :precompile do
    print %x(compass compile --time)
  end
end

Upvotes: 1

Shahaf
Shahaf

Reputation: 443

I ran into the same problem and this worked for me: https://github.com/ddollar/heroku-buildpack-multi

How it works:

  1. You explicitly tell Heroku that you want to use this "multi" buildpack using the "heroku config:add BUILDPACK_URL=..." command
  2. You create a .buildpacks file in your root directory that simply lists the git URLs for the various buildpacks you want to use. I used the python and ruby buildpacks.
  3. git push to Heroku and watch all buildpacks get used

It's also worth mentioning that the python buildpack has a couple of hooks that you can use to do additional custom work. If you create a bin/pre_compile file or a bin/post_compile file then those scripts will be called by the python buildpack just before/after the main compile step. So you could also use these hooks to get Ruby or other dependencies installed. But IMO it's easier to let Ruby's own buildpack install the Ruby dependencies.

Upvotes: 1

Andrew Gorcester
Andrew Gorcester

Reputation: 19973

Try explicitly selecting the python buildpack by using heroku config:add BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-python.git

It will still perform the detection process but I think (?) it will run the buildpack you've explicitly selected before or instead of attempting any others, and since you still have a python application installed, it should work.

Note that after you do the config:add you need to rebuild your slug on Heroku, which currently can ONLY be done by pushing an actual code change via git. You can make an empty git commit if you don't have any real changes to push, using git commit --allow-empty -m "Empty commit"

You can also create a new project using the --buildpack command line option.

Upvotes: 2

Related Questions