Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App fails to start on Heroku-22 stack due to lack of erb executable #101

Closed
habovh opened this issue Jun 20, 2022 · 4 comments · Fixed by #103
Closed

App fails to start on Heroku-22 stack due to lack of erb executable #101

habovh opened this issue Jun 20, 2022 · 4 comments · Fixed by #103
Assignees

Comments

@habovh
Copy link

habovh commented Jun 20, 2022

We've been using this buildpack for a while now, and would like to transition from the Heroku-20 stack to the new Heroku-22 stack.

As per the heroku-22 stack documentation/release notes, Ruby is no longer included on the system level.

The Nginx buildpack uses erb to parse the Nginx configuration file, so it needs at least some parts of Ruby:

# Evaluate config to get $PORT
erb config/nginx.conf.erb > config/nginx.conf

At first I thought we could use the heroku/ruby buildpack to make up for the now-missing erb binary. However, according to the documentation, since our app doesn't actually use Ruby we also don't have a Gemfile, and the build fails because of the failed check from the Ruby buildpack.

Adding empty Gemfile & Gemfile.lock files in our repo seems like quite a hack to include Ruby buildpack, only to be able to use the Nginx buildpack. It also feels quite odd to add such a large dependency ourselves, increasing slug size as well and forcing us to also update the ruby version whenever it reaches its own EOL. For reference, our slug size when using nginx-buildpack only is 191.4M. When adding the ruby buildpack, we're at 213.9M.

Now I know our current heroku-20 stack is nowhere near its end of life (scheduled April 2025), but I'd still like to be able to do a clean update to heroku-22 when able.

Could we somehow include erb in the nginx buildpack to avoid having to installing another buildpack just for the configuration parsing? Would it make sense to create a buildpack that would only include erb to use along nginx-buildpack, if that's even doable? Is the Ruby buildpack the "correct" approach here, even for non-ruby apps, with an empty Gemfile to please the validator?

Here's an excerpt from the app logs when starting on heroku-22 with only the Nginx buildpack.

2022-06-20T08:18:47.166786+00:00 heroku[web.1]: Starting process with command `bin/start-nginx yarn start`
2022-06-20T08:18:48.098961+00:00 app[web.1]: bin/start-nginx: line 8: erb: command not found
2022-06-20T08:18:48.108720+00:00 app[web.1]: buildpack=nginx at=logs-initialized
2022-06-20T08:18:48.109129+00:00 app[web.1]: buildpack=nginx at=app-initialization
2022-06-20T08:18:48.109435+00:00 app[web.1]: buildpack=nginx at=start-app cmd=yarn start
2022-06-20T08:18:50.117432+00:00 app[web.1]: buildpack=nginx at=app-initialized
2022-06-20T08:18:50.117779+00:00 app[web.1]: buildpack=nginx at=nginx-start
2022-06-20T08:18:50.206450+00:00 app[web.1]: nginx: [emerg] no "events" section in configuration
2022-06-20T08:18:50.208053+00:00 app[web.1]: buildpack=nginx at=exit process=nginx
2022-06-20T08:18:50.372744+00:00 heroku[web.1]: State changed from starting to crashed

For people needing to get nginx buildpack work on heroku-22 asap, you can use the following Gemfile and Gemfile.lock along with the Ruby buildpack:

Gemfile:

source "https://rubygems.org"
ruby "3.1.2"

Gemfile.lock:

GEM
  remote: https://rubygems.org/
  specs:

PLATFORMS
  ruby

DEPENDENCIES

RUBY VERSION
   ruby 3.1.2p20

BUNDLED WITH
   1.17.3
@edmorley
Copy link
Member

@habovh Hi! Thank you for the report - I agree this isn't ideal at present. This repo currently has no CI (filed #102) :-(

I've started a discussion internally as to how we should proceed. I wasn't aware this buildpack used Ruby for the custom templating feature.

It seems our options are:

  1. Have the nginx buildpack vendor Ruby iff there isn't already a Ruby installed (some apps will have the Ruby buildpack anyway). Though this requires that users have the nginx buildpack after any Ruby buildpack, or they'll still get two copies unnecessarily. And for apps that weren't already using Ruby, they get a larger slug size (albeit still not exactly massive, given nginx is not that big).
  2. Swap the .erb templates for something else, as a breaking change (that's opt-in for older stacks, and mandatory for Heroku-22+).
  3. See if there is any tooling out there that can handle .erb templates that doesn't actually need Ruby (eg a bash/Go/... port).
  4. Just throw in the towel and add Ruby back to the stack image.

edmorley added a commit that referenced this issue Jun 20, 2022
The ERB templating feature of this buildpack requires that the
`erb` command (part of Ruby) be available at runtime, in order
that the nginx config templates can be rendered into a valid nginx
config.

On Heroku-22 the stack image no longer includes a system Ruby
installation, so in order for this buildpack to continue to work, a
Ruby install must be vendored by this buildpack.

If an app already uses the Ruby buildpack, and that buildpack is
ordered prior to the nginx buildpack, then this buildpack will skip
the Ruby vendoring step to save installing a redundant copy of Ruby.

Fixes #101.
GUS-W-11321729.
edmorley added a commit that referenced this issue Jun 20, 2022
The ERB templating feature of this buildpack requires that the
`erb` command (part of Ruby) be available at runtime, in order
that the nginx config templates can be rendered into a valid nginx
config.

On Heroku-22 the stack image no longer includes a system Ruby
installation, so in order for this buildpack to continue to work, a
Ruby install must be vendored by this buildpack.

If an app already uses the Ruby buildpack, and that buildpack is
ordered prior to the nginx buildpack, then this buildpack will skip
the Ruby vendoring step to save installing a redundant copy of Ruby.

Fixes #101.
GUS-W-11321729.
@habovh
Copy link
Author

habovh commented Jun 20, 2022

@edmorley thanks for the quick reply!

The buildpack would indeed benefit from CI that's for sure 😅

I think that the best short-term approach is the option 1 —just as you planned on #103. Slug size will increase in our case by about 20MB, give or take. I guess that's acceptable for the time being, as long as the slug size is not already nearing the max slug size and the vendoring does not require users to put placeholder Gemfile and Gemfile.lock files in their app. Not having used Ruby in quite some time, it was pretty much a trial-and-error approach to get these two files right to satisfy the ruby buildpack validation.

In the longer run, I could see either option 2 or 3 working fine.

In our case we're mainly using the templating feature of ERB to leverage environment variables and include their values in the generated config. Now, I know ERB can do much more than that so it might be wise to check actual use before going on another templating engine. Regarding option 3 specifically, I have no experience with ports and don't know of any, but if such a port exists and meets the standard it might be a nice lightweight and zero-effort update for users to switch to the new heroku-22 stacks.

@edmorley edmorley self-assigned this Jun 20, 2022
edmorley added a commit that referenced this issue Jun 21, 2022
The ERB templating feature of this buildpack requires that the
`erb` command (part of Ruby) be available at runtime, in order
that the nginx config templates can be rendered into a valid nginx
config.

On Heroku-22 the stack image no longer includes a system Ruby
installation, so in order for this buildpack to continue to work, a
Ruby install must be vendored by this buildpack.

If an app already uses the Ruby buildpack, and that buildpack is
ordered prior to the nginx buildpack, then this buildpack will skip
the Ruby vendoring step to save installing a redundant copy of Ruby.

Fixes #101.
GUS-W-11321729.
@edmorley
Copy link
Member

@habovh The latest published version of this buildpack will now work on Heroku-22 without the Ruby buildpack having been manually added to the app's buildpacks list. An empty Gemfile / Gemfile.lock are also no longer required in the app source.

@habovh
Copy link
Author

habovh commented Jun 21, 2022

@edmorley nice! Seems to work as expected on our end as well. Thanks for the quick reaction time! I'll be monitoring the buildpack in case you decide to go with another solution down the road.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants