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

Mention we won't install a version of nodejs unless a package.json is found #295

Open
schneems opened this issue Jun 17, 2024 · 0 comments

Comments

@schneems
Copy link
Contributor

In heroku/jruby-getting-started#26 it was reported that the jruby getting started guide did not work "out of the box" with the ruby CNB because it was missing a package.json. However it works with the classic buildpack:

$ ls
Gemfile			Procfile.windows	app			db			public
Gemfile.lock		README.md		config			lib			test
Procfile		Rakefile		config.ru		log			vendor
⛄️ 3.3.1 🚀 /tmp/150ca2015abd0c42ade576ee15691dc6/jruby-getting-started (main)
$ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean
⛄️ 3.3.1 🚀 /tmp/150ca2015abd0c42ade576ee15691dc6/jruby-getting-started (main)
$ heroku create
Creating app... done, ⬢ serene-badlands-65663
https://serene-badlands-65663-2a3a8da4d325.herokuapp.com/ | https://git.heroku.com/serene-badlands-65663.git
⛄️ 3.3.1 🚀 /tmp/150ca2015abd0c42ade576ee15691dc6/jruby-getting-started (main)
$ git push heroku main
Enumerating objects: 316, done.
Counting objects: 100% (316/316), done.
Delta compression using up to 12 threads
Compressing objects: 100% (193/193), done.
Writing objects: 100% (316/316), 71.12 KiB | 35.56 MiB/s, done.
Total 316 (delta 99), reused 315 (delta 99), pack-reused 0
remote: Resolving deltas: 100% (99/99), done.
remote: Updated 89 paths from 5cbf940
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-22 stack
remote: -----> Determining which buildpack to use for this app
remote: -----> Ruby app detected
remote:
remote:        ## Warning: Your app needs java
remote:
remote:        The Ruby buildpack determined your app needs java installed
remote:        we recommend you add the jvm buildpack to your application:
remote:
remote:          $ heroku buildpacks:add heroku/jvm --index=1
remote:
remote: -----> Installing Java
remote:
remote: -----> Downloading Buildpack: heroku/jvm
remote: -----> Detected Framework: JVM Common
remote:
remote:  !     WARNING: No OpenJDK version specified
remote:        Your application does not explicitly specify an OpenJDK
remote:        version. OpenJDK 1.8 will be installed.
remote:
remote:        This default version will change at some point. Your
remote:        application might fail to build with the new version. We
remote:        recommend explicitly setting the required OpenJDK version for
remote:        your application.
remote:
remote:        To set the OpenJDK version, add or edit the system.properties
remote:        file in the root directory of your application to contain:
remote:
remote:        java.runtime.version = 1.8
remote:
remote:
remote: -----> Installing OpenJDK 1.8... done
remote: -----> Installing bundler 2.4.22
remote: -----> Removing BUNDLED WITH version in the Gemfile.lock
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-3.1.0-jruby-9.4.1.0
remote: -----> Installing dependencies using bundler 2.4.22
remote:        Running: BUNDLE_WITHOUT='development:test' BUNDLE_PATH=vendor/bundle BUNDLE_BIN=vendor/bundle/bin BUNDLE_DEPLOYMENT=1 bundle install -j4
remote:        Fetching gem metadata from https://rubygems.org/.........
remote:        Fetching rake 13.0.6
remote:        Installing rake 13.0.6
remote:        Fetching minitest 5.18.0
remote:        Fetching builder 3.2.4
# ...
remote:        Installing sass-rails 6.0.0
remote:        Bundle complete! 13 Gemfile dependencies, 74 gems now installed.
remote:        Gems in the groups 'development' and 'test' were not installed.
remote:        Bundled gems are installed into `./vendor/bundle`
remote:        Bundle completed (87.92s)
remote:        Cleaning up the bundler cache.
remote:
remote: ###### WARNING:
remote:
remote:        Installing a default version (20.9.0) of Node.js.
remote:        This version is not pinned and can change over time, causing unexpected failures.
remote:
remote:        Heroku recommends placing the `heroku/nodejs` buildpack in front of
remote:        `heroku/ruby` to install a specific version of node:
remote:
remote:        https://devcenter.heroku.com/articles/ruby-support#node-js-support
remote:
remote: -----> Installing node-v20.9.0-linux-x64
remote: -----> Detecting rake tasks
remote: -----> Preparing app for Rails asset pipeline
remote:        Running: rake assets:precompile

The reason for this is that the two buildpacks have different behavior. And when there's a difference in behavior it should be called out in https://github.com/heroku/buildpacks-ruby/blob/main/docs/upgrading.md which it isn't.

Difference

The CNB ONLY looks for a package.json to install a node version and then relies on the node buildpack to install it.

When node support was added to the classic buildpack, a heroku/nodejs buildpack didn't exist. The asset pipeline (aka sprockets) needed A version of node so the ruby buildpack detected when execjs gem is present and installs node https://github.com/heroku/heroku-buildpack-ruby/blob/168cb5d556f154e4eba57c797d04b18a4d8b354c/lib/language_pack/ruby.rb#L944-L946. So the reason this works on classic is that it detects that jruby has execjs and it installs a version of node.

Besides documenting this difference we could try to bring the classic behavior closer to the CNB. by using the compile_buildpack_v2 bash function to install the nodejs buildpack when a package.json is present similar to how java is installed https://github.com/heroku/heroku-buildpack-ruby/blob/168cb5d556f154e4eba57c797d04b18a4d8b354c/bin/compile#L18-L33. This is a riskier change.

Improve the experience

In heroku/jruby-getting-started#26 the error was confusing. The message said

[builder]     ExecJS::RuntimeUnavailable: Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes.

However it was unclear what the user should do to install a node runtime. The buildpack should "just work" ™️ .

We should replicate the logic in the detect phase and re-play what we're not doing. I.e. something like "Skipping nodejs install (no package.json found)`. So if the user searches the logs for "node" they'll find that breadcrumb.

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

No branches or pull requests

1 participant