3

I am developing an Eclipse Virgo buildpack but when I try it with Heroku and push a trivial app, detection fails:

-----> Fetching custom git buildpack... done
!     Heroku push rejected, no Cedar-supported app detected

The buildpack's detect script works fine locally in the root directory of the app:

$[...]virgo-buildpack/bin/detect .
Virgo Web

Any tips on how to debug this? I tried having the detect script write to stdout and stderr, but the output doesn't appear under "heroku logs".

I am running Mac OS X 10.8.2, Ruby 1.9.3p374, and gems 1.8.23.

Update: following the first two answers, I used a bash detect script to install the missing gem before driving a detect.rb script. I also changed the buildpack scripts to write to standard output.

The heroku push gets a lot further, but still fails. I can see the compile script exiting, but the release bash script has an echo command right at the start and this does not appear in the output.

So it seems that the release script is not being called.

The output is as follows (# indicates comments to avoid clutter):

-----> Fetching custom git buildpack... done
# detect script enter and exit
Virgo Web app detected
# compile script enter and exit
-----> Discovering process types
       Procfile declares types                                                                                                                                                                                                                                                                                                                                                                                             


                               -> (none)
# detect script enter and exit (again)
Virgo Web -> web

-----> Compiled slug size: 60.4MB
-----> Launching... !     Heroku push rejected, failure releasing code

heroku logs --tail simply shows:

2013-03-06T10:53:48+00:00 heroku[slugc]: Slug compilation started
2013-03-06T10:54:27+00:00 heroku[slugc]: Slug compilation failed: failure releasing code
glyn
  • 1,180
  • 8
  • 19

2 Answers2

2

For a custom buildpack, the detect script doesn't really need to be that complicated because users will be specifying it manually with BUILDPACK_URL anyway. A sophisticated detect script really only makes sense for the default Heroku buildpacks because they need to detect if the buildpack applies for any given app.

If you want to completely punt on detection, you can get away with something like this:

#!/usr/bin/env bash
# bin/detect <build-dir>

echo "Vergo"
exit 0

Once you get that working (and work out any issues with compile and release), you can make it a little more intelligent. For example, you could detect if a certain file pattern exists:

#!/usr/bin/env bash
# bin/detect <build-dir>
if [ -f $1/index.jsp ]; then
  echo "Vergo" && exit 0
else
  echo "no" && exit 1
fi

Also, speaking of simplicity, it looks like you are basing your buildpack on the Ruby buildpack, which is one of the most complicated ones out there. You may want to take a look at the list of third-party buildpacks to see how most are done in simple bash.

ryanbrainard
  • 5,918
  • 35
  • 41
  • Note that I need to stick with the current Ruby implementation for XML parsing and because I want to track a CloudFoundry buildpack written in Ruby that it was forked from. – glyn Mar 05 '13 at 15:36
  • I made considerable progress with your suggestion. I now install the missing gem in a bash detect script before invoking detect.rb. I've gotten as far as "failure releasing code" in slug compilation. – glyn Mar 05 '13 at 15:38
  • Similar to the advice for `detect`, try simplifying your `release` script (or remove it all together). It is expecting something like [this](https://devcenter.heroku.com/articles/buildpack-api#binrelease) that returns YAML. Also, installing gems in `detect` is a bit strange. Since its a custom buildpack, it probably doesn't really matter in practice, but `detect` should be super fast and not be making any changes to the underlying system. In fact, I don't think there are even guarantees that it will run on the same system as `compile` or `release`. – ryanbrainard Mar 05 '13 at 18:40
  • Fair points. I'm still missing any technique for seeing "behind" the opaque "failure releasing code" though. I think this would benefit all buildpack writers. – glyn Mar 06 '13 at 09:58
  • By writing to standard output, I can see the compile script exiting, but the release bash script has an echo command right at the start and this does not appear. So it seems that release is not being called. – glyn Mar 06 '13 at 10:59
  • Since the output of `release` is expected to just be a YAML file, anything you echo is going to be redirected to be part of that file as well, which is why you aren't seeing in the console. I wrote a [Buildpack Testrunner](https://github.com/ryanbrainard/heroku-buildpack-testrunner) that could help here. It will let you write tests for your buildpack and you can assert on what the expected output of the release script. As Eric answered, using `heroku run bash` can be helpful here to run your `release` script on a dyno to see the output directly. – ryanbrainard Mar 06 '13 at 16:55
  • Also, forgot to mention this and its a bit buried in the [Buildpack API doc](https://devcenter.heroku.com/articles/buildpack-api), but creating a [profile.d script](https://devcenter.heroku.com/articles/profiled) is the new alternative way for setting up the environment that previously had to be done in `bin/release`. That should hopefully let you simplify your `bin/release` to just focus on addons, if you need them. If there are no addons, you can skip `bin/release` all together. – ryanbrainard Mar 06 '13 at 23:44
  • Thanks. Presumably buildpacks should log to standard error to avoid the logging output messing up YAML etc. – glyn Mar 08 '13 at 09:38
1

Currnetly there are a few tools to make this much easier.

  1. This build pack https://github.com/kr/heroku-buildpack-inline (A build pack to help construct buildpack)

  2. heroku run bash Is your best friend.

Push your build pack on to the platform using the inline buildpack so that you can get good logging, and use heroku run bash so that you can actaully tinker with your buildpack in the environment that you will be using it in.

Eric Fode
  • 3,667
  • 2
  • 24
  • 29
  • Interesting idea, but when I push the trivial app plus the inlined buildpack, I get the same failure (Heroku push rejected, no Cedar-supported app detected). This is not surprising as heroku-buildpack-inline simply delegates to the inlined buildpack. However, heroku run bash may have turned up a useful clue - when I clone the combined app/inlined buildpack and try to run it, Ruby complains that the nokogiri gem is not installed. When I install that, the detect script runs perfectly. So I guess I need to configure the buildpack so that the necessary gems are installed by heroku. – glyn Mar 04 '13 at 14:08
  • I updated Gemfile and Gemfile.lock to ensure the nokogiri dependency is expressed, but still get the same error on pushing to heroku. – glyn Mar 04 '13 at 14:19
  • One puzzling thing is that the environment variable PORT is set under heroku run bash, but appears not to be set AFAICT when pushing to heroku drives detect/compile/release. – glyn Mar 05 '13 at 16:06
  • That is because the port is set when the dynos are deployed, not during the slug compile step. – Eric Fode Mar 06 '13 at 00:35