diff --git a/.rspec b/.rspec new file mode 100644 index 000000000..7aac1efb0 --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--require dead_end diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d085916c..ced65c76f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Main (unreleased) +* Applications with `package.json` now get `nodejs` installed (https://github.com/heroku/heroku-buildpack-ruby/pull/1212) +* Applications with `yarn.lock` now get `yarn` installed (https://github.com/heroku/heroku-buildpack-ruby/pull/1212) + ## v230 (10/5/2021) * Default Ruby version is now 2.7.4 (https://github.com/heroku/heroku-buildpack-ruby/pull/1193) diff --git a/Gemfile b/Gemfile index e4e202ff3..4a0adce0e 100644 --- a/Gemfile +++ b/Gemfile @@ -15,4 +15,5 @@ group :development, :test do gem 'json' gem 'ci-queue' gem 'redis' + gem 'dead_end' end diff --git a/Gemfile.lock b/Gemfile.lock index 2785827c3..ff5d66b0b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,6 +3,7 @@ GEM specs: ci-queue (0.21.0) citrus (3.0.2) + dead_end (2.0.0) diff-lcs (1.4.4) erubis (2.7.0) excon (0.85.0) @@ -51,6 +52,7 @@ PLATFORMS DEPENDENCIES ci-queue + dead_end excon heroku_hatchet json diff --git a/changelogs/unreleased/jsbundling_packagejson.md b/changelogs/unreleased/jsbundling_packagejson.md new file mode 100644 index 000000000..41f46c704 --- /dev/null +++ b/changelogs/unreleased/jsbundling_packagejson.md @@ -0,0 +1,10 @@ +## Nodejs will now be installed for Ruby applications that have a `package.json` file + +Ruby applications using the `heroku/ruby` buildpack now receive a default version of `node` installed if they have a `package.json` file in the root directory of their application. + +Prior to this change, only applications using the `webpacker` or `execjs` gem would trigger node installation logic. This change is intended to facilitate Rails 7 applications using `jsbundling-rails` without `webpacker`. + +>Note +>Applications using the `heroku/nodejs` buildpack before the `heroku/ruby` buildpack will not see a change in behavior + +For more information, see [Heroku Ruby support documentation](https://devcenter.heroku.com/articles/ruby-support#installed-binaries). diff --git a/changelogs/unreleased/jsbundling_yarnlock.md b/changelogs/unreleased/jsbundling_yarnlock.md new file mode 100644 index 000000000..2f70d329b --- /dev/null +++ b/changelogs/unreleased/jsbundling_yarnlock.md @@ -0,0 +1,10 @@ +## Yarn will now be installed for Ruby applications that have a `yarn.lock` file + +Ruby applications using the `heroku/ruby` buildpack now receive a default version of `yarn` installed if they have a `yarn.lock` file in the root directory of their application. + +Prior to this change, only applications using the `webpacker` gem would trigger node installation logic. This change is intended to facilitate Rails 7 applications using `jsbundling-rails` without `webpacker`. + +>Note +>Applications using the `heroku/nodejs` buildpack before the `heroku/ruby` buildpack will not see a change in behavior + +For more information, see [Heroku Ruby support documentation](https://devcenter.heroku.com/articles/ruby-support#installed-binaries). diff --git a/hatchet.json b/hatchet.json index 3df2fd4a2..9d4507f47 100644 --- a/hatchet.json +++ b/hatchet.json @@ -48,7 +48,8 @@ "sharpstone/active_storage_non_local", "sharpstone/active_storage_local", "sharpstone/sprockets_asset_compile_true", - "sharpstone/rails6-basic" + "sharpstone/rails6-basic", + "sharpstone/rails-jsbundling" ], "heroku": [ "heroku/ruby-getting-started" diff --git a/hatchet.lock b/hatchet.lock index d08b738af..9f7c2bf1d 100644 --- a/hatchet.lock +++ b/hatchet.lock @@ -45,16 +45,14 @@ - 18853ba7dda61745995740b4ca6f5f90bbd8afba - - "./repos/rails_versions/active_storage_non_local" - 86dddf0127043abba1cb2890590a1d38f111edbd +- - "./repos/rails_versions/rails-jsbundling" + - 6b60a3aa7eb9507865ebba6afcca150017ab66b4 - - "./repos/rails_versions/rails3_default_ruby" - a6b44db674c0d3538633989295e2cfd5e8e1ba0d - - "./repos/rails_versions/rails42_default_ruby" - dfa0f0133dafa62064968ea2efb6432f54350138 - - "./repos/rails_versions/rails4_windows_mri193" - f4c7b6209835050468bbb87827acf652b8f4d8ce -- - "./repos/rails_versions/rails5" - - 1680c5da829e03ffb9345187971a13e5109d86a6 -- - "./repos/rails_versions/rails51_webpacker" - - 75c5c4f21b1d88fc3b8edf60b3f871df3ad70208 - - "./repos/rails_versions/rails6-basic" - 6b81e0246c64c332181c22ace4ac96b57309cb85 - - "./repos/rails_versions/rails_lts_23_default_ruby" @@ -69,8 +67,6 @@ - ce976c727d9f477957c499f39f4cf9603c378103 - - "./repos/rake/bad_rakefile" - 3cb9c7bf6494c59bd25fa74c2aa4531119e12a46 -- - "./repos/rake/connect_to_database_on_first_push" - - 635e002cb5a0400092dd5e80b88c6ffb740fda02 - - "./repos/rake/default_with_rakefile" - c6e0c4db8dcccb47e11d496e17adbc2dafc80dd8 - - "./repos/rake/no_rakefile" diff --git a/lib/language_pack.rb b/lib/language_pack.rb index 23f41bbd7..a7b43b236 100644 --- a/lib/language_pack.rb +++ b/lib/language_pack.rb @@ -13,7 +13,7 @@ def self.detect(*args) Instrument.instrument 'detect' do Dir.chdir(args.first) - pack = [ NoLockfile, Rails6, Rails5, Rails42, Rails41, Rails4, Rails3, Rails2, Rack, Ruby ].detect do |klass| + pack = [ NoLockfile, Rails7, Rails6, Rails5, Rails42, Rails41, Rails4, Rails3, Rails2, Rack, Ruby ].detect do |klass| klass.use? end @@ -50,4 +50,5 @@ def self.detect(*args) require "language_pack/rails42" require "language_pack/rails5" require "language_pack/rails6" +require "language_pack/rails7" require "language_pack/no_lockfile" diff --git a/lib/language_pack/rails6.rb b/lib/language_pack/rails6.rb index 32a603e6c..89b7678d2 100644 --- a/lib/language_pack/rails6.rb +++ b/lib/language_pack/rails6.rb @@ -9,7 +9,7 @@ def self.use? rails_version = bundler.gem_version('railties') return false unless rails_version is_rails = rails_version >= Gem::Version.new('6.x') && - rails_version < Gem::Version.new('7.0.0') + rails_version < Gem::Version.new('7.a') return is_rails end end diff --git a/lib/language_pack/rails7.rb b/lib/language_pack/rails7.rb new file mode 100644 index 000000000..cd424bd31 --- /dev/null +++ b/lib/language_pack/rails7.rb @@ -0,0 +1,17 @@ +require 'securerandom' +require "language_pack" +require "language_pack/rails6" + +class LanguagePack::Rails7 < LanguagePack::Rails6 + # @return [Boolean] true if it's a Rails 7.x app + def self.use? + instrument "rails6.use" do + rails_version = bundler.gem_version('railties') + return false unless rails_version + is_rails = rails_version >= Gem::Version.new('7.a') && + rails_version < Gem::Version.new('8.0.0') + return is_rails + end + end +end + diff --git a/lib/language_pack/ruby.rb b/lib/language_pack/ruby.rb index e35ffa65e..8588a4111 100644 --- a/lib/language_pack/ruby.rb +++ b/lib/language_pack/ruby.rb @@ -1053,7 +1053,11 @@ def pg_adapters # @note execjs will blow up if no JS RUNTIME is detected and is loaded. # @return [Array] the node.js binary path if we need it or an empty Array def add_node_js_binary - if (bundler.has_gem?('execjs') || bundler.has_gem?('webpacker')) && node_not_preinstalled? + return [] if node_js_preinstalled? + + if Pathname(build_path).join("package.json").exist? || + bundler.has_gem?('execjs') || + bundler.has_gem?('webpacker') [@node_installer.binary_path] else [] @@ -1061,7 +1065,13 @@ def add_node_js_binary end def add_yarn_binary - bundler.has_gem?('webpacker') && yarn_not_preinstalled? ? [@yarn_installer.name] : [] + return [] if yarn_preinstalled? + + if Pathname(build_path).join("yarn.lock").exist? || bundler.has_gem?('webpacker') + [@yarn_installer.name] + else + [] + end end def has_yarn_binary? diff --git a/spec/cnb/basic_local_pack_spec.rb b/spec/cnb/basic_local_pack_spec.rb index 2c792be1b..5c7ffc646 100644 --- a/spec/cnb/basic_local_pack_spec.rb +++ b/spec/cnb/basic_local_pack_spec.rb @@ -115,7 +115,7 @@ def run!(cmd) expect(app.output).to match("Compiling Ruby/Rails") run_out = app.run!("ruby -v") - expect(run_out).to match("2.6.6") + expect(run_out).to match("2.7.4") end end end diff --git a/spec/hatchet/rails7_spec.rb b/spec/hatchet/rails7_spec.rb new file mode 100644 index 000000000..fdce28447 --- /dev/null +++ b/spec/hatchet/rails7_spec.rb @@ -0,0 +1,19 @@ +require_relative '../spec_helper' + +describe "Rails 6" do + it "should detect successfully" do + Hatchet::App.new('rails-jsbundling').in_directory_fork do + expect(LanguagePack::Rails6.use?).to eq(false) + expect(LanguagePack::Rails7.use?).to eq(true) + end + end + + it "works with jsbundling" do + Hatchet::Runner.new("rails-jsbundling").tap do |app| + app.deploy do + expect(app.output).to include("yarn install") + expect(app.output).to include("Asset precompilation completed") + end + end + end +end