From 64eb9889917515c87b73dbb8b73df8b81343909a Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 17 Sep 2026 16:53:12 +0000 Subject: [PATCH 01/12] Render what ember-cli-rails reports about a built application The helpers derived a built application's layout for themselves: the `assets` directory, the `index.html` that refers to it, the `package.json` that names it, and whether the build is Vite-based. ember-cli-rails runs the build and reports all of it, so read it from there instead of deriving it again. This removes `EmberCli::Assets::Paths`, `Lookup`, `AssetMap` and `DirectoryAssetMap`, along with the Vite check that disagreed with the one ember-cli-rails applies, and leaves the helpers with the one job they have: turning what it reports into tags. The helpers have always required ember-cli-rails at runtime without saying so, which is why they feature-detected its development server. Declare the dependency instead, on the release that reports a built application. Co-Authored-By: Claude Opus 5 --- Gemfile | 6 - README.md | 3 + app/helpers/ember_cli_rails_assets_helper.rb | 100 ++------ ember-cli-rails-assets.gemspec | 4 +- lib/ember-cli-rails-assets.rb | 1 + lib/ember_cli/assets/asset_map.rb | 87 ------- lib/ember_cli/assets/directory_asset_map.rb | 36 --- lib/ember_cli/assets/errors.rb | 1 - lib/ember_cli/assets/lookup.rb | 49 ---- lib/ember_cli/assets/paths.rb | 38 --- lib/ember_cli/assets/url.rb | 14 -- .../ember_cli_rails_assets_helper_spec.rb | 107 ++++---- spec/lib/ember_cli/assets/asset_map_spec.rb | 235 ------------------ .../assets/directory_asset_map_spec.rb | 50 ---- spec/lib/ember_cli/assets/paths_spec.rb | 53 ---- 15 files changed, 68 insertions(+), 716 deletions(-) delete mode 100644 lib/ember_cli/assets/asset_map.rb delete mode 100644 lib/ember_cli/assets/directory_asset_map.rb delete mode 100644 lib/ember_cli/assets/lookup.rb delete mode 100644 lib/ember_cli/assets/paths.rb delete mode 100644 lib/ember_cli/assets/url.rb delete mode 100644 spec/lib/ember_cli/assets/asset_map_spec.rb delete mode 100644 spec/lib/ember_cli/assets/directory_asset_map_spec.rb delete mode 100644 spec/lib/ember_cli/assets/paths_spec.rb diff --git a/Gemfile b/Gemfile index a304e15..c939eab 100644 --- a/Gemfile +++ b/Gemfile @@ -13,12 +13,6 @@ end gem "rails", rails_constraint gem "webrick" -group :development, :test do - # The specs verify doubles against the development-server API, - # which ships with 0.13.0. - gem "ember-cli-rails", ">= 0.13.0" -end - group :test do gem "cuprite" diff --git a/README.md b/README.md index 5cde20e..bbbf7c8 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,9 @@ Then run `bundle install`: $ bundle install ``` +The helpers render what [`ember-cli-rails`][ember-cli-rails] reports about a +built application, so they require `ember-cli-rails >= 0.15.0`. + ## Setup To configure your project to use `ember-cli-rails`, follow the instructions diff --git a/app/helpers/ember_cli_rails_assets_helper.rb b/app/helpers/ember_cli_rails_assets_helper.rb index 8ba8bdd..84b585f 100644 --- a/app/helpers/ember_cli_rails_assets_helper.rb +++ b/app/helpers/ember_cli_rails_assets_helper.rb @@ -1,22 +1,17 @@ require "ember_cli/assets/errors" -require "ember_cli/assets/lookup" -require "ember_cli/assets/paths" -require "ember_cli/assets/url" module EmberCliRailsAssetsHelper def include_ember_script_tags(name, prepend: "") app = EmberCli[name] app.build - if dev_server?(app) - dev_server_ember_script_tags(app) + if app.dev_server? || app.vite? + # Vite-based applications boot from the tags declared in their + # `index.html`, which ember-cli-rails extracts for us. + safe_join(app.startup_tags(prepend: prepend).map(&:html_safe), "\n") else - paths = EmberCli::Assets::Paths.new(app) - - if paths.vite? - vite_ember_script_tags(paths, prepend) - else - classic_ember_script_tags(app, prepend) + tags_for(app.javascript_assets(prepend: prepend)) do |src| + %{} end end end @@ -25,9 +20,7 @@ def include_ember_stylesheet_tags(name, prepend: "") app = EmberCli[name] app.build - paths = EmberCli::Assets::Paths.new(app) - - if dev_server?(app) || paths.vite? + if app.dev_server? || app.vite? raise EmberCli::Assets::NotSupportedError, <<~MSG `include_ember_stylesheet_tags` does not support Vite-based applications (`ember-cli >= 6.8`). @@ -37,80 +30,19 @@ def include_ember_stylesheet_tags(name, prepend: "") MSG end - assets = EmberCli::Assets::Lookup.new(app) - - assets.stylesheet_assets. - map { |src| mount_asset(src, prepend) }. - map { |src| %{}.html_safe }. - inject(&:+) + tags_for(app.stylesheet_assets(prepend: prepend)) do |href| + %{} + end end private - # Whether ember-cli-rails serves the application from Vite's development - # server. Older ember-cli-rails releases have no development server, so - # feature-detect the reader. - def dev_server?(app) - app.respond_to?(:dev_server?) && app.dev_server? - end - - # The application is served by Vite's development server, so read - # `index.html` from the server instead of a build directory, and rewrite - # its root-relative URLs to absolute URLs on the server — the same way - # ember-cli-rails serves the document itself. `app.build` has already - # booted the server. - def dev_server_ember_script_tags(app) - vite_startup_tags(app.dev_server.index_html, prefix: app.dev_server.origin) - end - - # Classic builds ship a fixed set of scripts (vendor and app) resolved - # through the asset map, so emit a plain script tag per JavaScript asset - # with `prepend` joined onto each path. - def classic_ember_script_tags(app, prepend) - assets = EmberCli::Assets::Lookup.new(app) - - assets.javascript_assets. - map { |src| mount_asset(src, prepend) }. - map { |src| %{}.html_safe }. + # Classic (Broccoli-based) builds ship a fixed set of assets, which + # ember-cli-rails reports already mounted onto `prepend`, so emit a plain + # tag per asset. + def tags_for(assets) + assets. + map { |asset| yield(asset).html_safe }. inject(&:+) end - - # `prepend` mounts the build's assets onto a path (or another host), so it only applies to the URLs that point into the build. - # Assets hosted elsewhere (a CDN, a font service) are already absolute. - def mount_asset(src, prepend) - if EmberCli::Assets::Url.remote?(src) - src - else - [prepend, src].join - end - end - - # Vite builds boot from ES modules declared in dist/index.html, so extract - # the tags required for startup (including the config meta tag and - # stylesheets) and remap root-absolute paths onto the mount point. - def vite_ember_script_tags(paths, prepend) - vite_startup_tags(paths.index_html.read, prefix: prepend.to_s.chomp("/")) - end - - # Extracts the tags a Vite-based application needs to boot from an - # `index.html` document, with `prefix` joined onto every root-relative - # URL. Protocol-relative URLs (`//`) are left alone. - def vite_startup_tags(html, prefix:) - document = Nokogiri::HTML5(html) - - tags = document.css( - 'meta[name$="/config/environment"], link[rel="stylesheet"], link[rel="modulepreload"], script' - ).map do |tag| - %w(href src).each do |attribute| - value = tag[attribute] - - if value&.start_with?("/") && !value.start_with?("//") - tag[attribute] = "#{prefix}#{value}" - end - end - tag.to_html.html_safe - end - - safe_join(tags, "\n") - end end diff --git a/ember-cli-rails-assets.gemspec b/ember-cli-rails-assets.gemspec index e518aff..d01cf14 100644 --- a/ember-cli-rails-assets.gemspec +++ b/ember-cli-rails-assets.gemspec @@ -16,5 +16,7 @@ Gem::Specification.new do |s| s.files = Dir["{app,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"] - s.add_dependency 'nokogiri' + # The helpers render what ember-cli-rails reports about a built + # application, so they require the release that reports it. + s.add_dependency "ember-cli-rails", ">= 0.15.0" end diff --git a/lib/ember-cli-rails-assets.rb b/lib/ember-cli-rails-assets.rb index 853c81a..5ca453c 100644 --- a/lib/ember-cli-rails-assets.rb +++ b/lib/ember-cli-rails-assets.rb @@ -1,3 +1,4 @@ +require "ember-cli-rails" require "ember_cli/assets/engine" module EmberCli diff --git a/lib/ember_cli/assets/asset_map.rb b/lib/ember_cli/assets/asset_map.rb deleted file mode 100644 index f1e8b5b..0000000 --- a/lib/ember_cli/assets/asset_map.rb +++ /dev/null @@ -1,87 +0,0 @@ -require 'nokogiri' -require "ember_cli/assets/errors" -require "ember_cli/assets/url" - -module EmberCli - module Assets - class AssetMap - def initialize(name:, asset_map:, index_html:) - @name = name - @asset_map = asset_map - @index_html = index_html - end - - def javascripts - assert_asset_map! - - document.css('script').filter_map { |script| asset_for(script['src']) } - end - - def stylesheets - assert_asset_map! - - document.css('link[rel="stylesheet"]').filter_map { |link| asset_for(link['href']) } - end - - private - - attr_reader :name, :asset_map, :index_html - - def document - @document ||= Nokogiri::HTML(index_html.read) - end - - # Assets hosted outside the build (a CDN, a font service) have no entry in the asset map, so their URL is emitted untouched. - # A tag without a URL (an inline ` - - - - - - - - - - HTML - dev_server = instance_double( - EmberCli::DevServer, - index_html: index_html, - origin: "http://127.0.0.1:4200", - ) - app = instance_double( - EmberCli::App, - build: true, + it "emits the startup tags ember-cli-rails read from the server" do + app = build_app( dev_server?: true, - dev_server: dev_server, + startup_tags: [ + %{}, + %{}, + ], ) - allow(EmberCli).to receive(:[]).with(:frontend).and_return(app) tags = helper.include_ember_script_tags(:frontend) expect(app).to have_received(:build) + expect(app).to have_received(:startup_tags).with(prepend: "") expect(tags).to include(%{src="http://127.0.0.1:4200/@vite/client"}) - expect(tags).to include(%{src="http://127.0.0.1:4200/@embroider/virtual/vendor.js"}) - expect(tags).to include(%{href="http://127.0.0.1:4200/@embroider/virtual/app.css"}) - expect(tags).to include(%{name="my-app/config/environment"}) - expect(tags).to include(%{src="https://cdn.example.com/analytics.js"}) - expect(tags).to include(%{src="//cdn.example.com/protocol-relative.js"}) + expect(tags).to include(%{href="http://127.0.0.1:4200/app.css"}) + end + end + + context "when the application is built with Vite" do + it "emits the startup tags with the mount point joined onto them" do + app = build_app( + vite?: true, + startup_tags: [%{}], + ) + + tags = helper.include_ember_script_tags(:frontend, prepend: "/admin") + + expect(app).to have_received(:startup_tags).with(prepend: "/admin") + expect(tags).to include(%{src="/admin/app.js"}) end end context "when the application is a classic build" do - it "mounts the build's scripts onto `prepend`, leaving the ones hosted elsewhere untouched" do - app = instance_double(EmberCli::App, build: true, dev_server?: false) - paths = instance_double(EmberCli::Assets::Paths, vite?: false) - lookup = instance_double( - EmberCli::Assets::Lookup, + it "emits the scripts as ember-cli-rails reports them, mounted onto `prepend`" do + app = build_app( javascript_assets: [ - "assets/vendor-abc123.js", + "http://example.com/assets/vendor-abc123.js", "https://cdn.example.com/analytics.js", "//cdn.example.com/protocol-relative.js", ], ) - allow(EmberCli).to receive(:[]).with(:frontend).and_return(app) - allow(EmberCli::Assets::Paths). - to receive(:new).with(app).and_return(paths) - allow(EmberCli::Assets::Lookup). - to receive(:new).with(app).and_return(lookup) tags = helper.include_ember_script_tags(:frontend, prepend: "http://example.com/") + expect(app).to have_received(:javascript_assets). + with(prepend: "http://example.com/") expect(tags).to include(%{src="http://example.com/assets/vendor-abc123.js"}) expect(tags).to include(%{src="https://cdn.example.com/analytics.js"}) expect(tags).to include(%{src="//cdn.example.com/protocol-relative.js"}) @@ -73,11 +59,7 @@ describe "#include_ember_stylesheet_tags" do context "when the application is served by Vite's development server" do it "raises an error pointing at `include_ember_script_tags`" do - app = instance_double(EmberCli::App, build: true, dev_server?: true) - paths = instance_double(EmberCli::Assets::Paths) - allow(EmberCli).to receive(:[]).with(:frontend).and_return(app) - allow(EmberCli::Assets::Paths). - to receive(:new).with(app).and_return(paths) + build_app(dev_server?: true) expect { helper.include_ember_stylesheet_tags(:frontend) }.to raise_error( EmberCli::Assets::NotSupportedError, @@ -88,11 +70,7 @@ context "when the application is built with Vite" do it "raises an error pointing at `include_ember_script_tags`" do - app = instance_double(EmberCli::App, build: true, dev_server?: false) - paths = instance_double(EmberCli::Assets::Paths, vite?: true) - allow(EmberCli).to receive(:[]).with(:frontend).and_return(app) - allow(EmberCli::Assets::Paths). - to receive(:new).with(app).and_return(paths) + build_app(vite?: true) expect { helper.include_ember_stylesheet_tags(:frontend) }.to raise_error( EmberCli::Assets::NotSupportedError, @@ -102,29 +80,34 @@ end context "when the application is a classic build" do - it "mounts the build's stylesheets onto `prepend`, leaving the ones hosted elsewhere untouched" do - app = instance_double(EmberCli::App, build: true, dev_server?: false) - paths = instance_double(EmberCli::Assets::Paths, vite?: false) - lookup = instance_double( - EmberCli::Assets::Lookup, + it "emits the stylesheets as ember-cli-rails reports them, mounted onto `prepend`" do + app = build_app( stylesheet_assets: [ - "assets/vendor-abc123.css", + "http://example.com/assets/vendor-abc123.css", "https://fonts.example.com/css?family=Frontend", "//fonts.example.com/protocol-relative.css", ], ) - allow(EmberCli).to receive(:[]).with(:frontend).and_return(app) - allow(EmberCli::Assets::Paths). - to receive(:new).with(app).and_return(paths) - allow(EmberCli::Assets::Lookup). - to receive(:new).with(app).and_return(lookup) tags = helper.include_ember_stylesheet_tags(:frontend, prepend: "http://example.com/") + expect(app).to have_received(:build) + expect(app).to have_received(:stylesheet_assets). + with(prepend: "http://example.com/") expect(tags).to include(%{href="http://example.com/assets/vendor-abc123.css"}) expect(tags).to include(%{href="https://fonts.example.com/css?family=Frontend"}) expect(tags).to include(%{href="//fonts.example.com/protocol-relative.css"}) end end end + + def build_app(**stubs) + app = instance_double( + EmberCli::App, + **{ build: true, dev_server?: false, vite?: false }.merge(stubs), + ) + allow(EmberCli).to receive(:[]).with(:frontend).and_return(app) + + app + end end diff --git a/spec/lib/ember_cli/assets/asset_map_spec.rb b/spec/lib/ember_cli/assets/asset_map_spec.rb deleted file mode 100644 index 5f7df1e..0000000 --- a/spec/lib/ember_cli/assets/asset_map_spec.rb +++ /dev/null @@ -1,235 +0,0 @@ -require "ember_cli/assets/asset_map" - -describe EmberCli::Assets::AssetMap do - describe "#javascripts" do - it "includes the most recent javascript build artifacts" do - asset_map = { - "assets" => { - "not-a-match" => nil, - "bar.js" => "bar-abc123.js", - "vendor.js" => "vendor-abc123.js", - }, - "prepend" => "foo/", - } - index_html = StringIO.new(<<~HTML) - - - - - - - HTML - assets = build_assets(name: "bar", asset_map: asset_map, index_html: index_html) - - javascripts = assets.javascripts - - expect(javascripts).to match_array([ - "foo/bar-abc123.js", - "foo/vendor-abc123.js", - ]) - end - - it "passes scripts hosted outside the build through untouched" do - asset_map = { - "assets" => { - "bar.js" => "bar-abc123.js", - }, - "prepend" => "foo/", - } - index_html = StringIO.new(<<~HTML) - - - - - - - - HTML - assets = build_assets(name: "bar", asset_map: asset_map, index_html: index_html) - - javascripts = assets.javascripts - - expect(javascripts).to match_array([ - "https://cdn.example.com/analytics.js", - "//cdn.example.com/protocol-relative.js", - "foo/bar-abc123.js", - ]) - end - - it "ignores scripts without a `src`" do - asset_map = { - "assets" => { - "bar.js" => "bar-abc123.js", - }, - "prepend" => "foo/", - } - index_html = StringIO.new(<<~HTML) - - - - - - - HTML - assets = build_assets(name: "bar", asset_map: asset_map, index_html: index_html) - - javascripts = assets.javascripts - - expect(javascripts).to match_array(["foo/bar-abc123.js"]) - end - - context "when the asset_map is empty" do - it "raises a BuildError" do - assets = build_assets(asset_map: {}, name: "bar", index_html: StringIO.new) - - expect { assets.javascripts }.to raise_build_error - end - end - end - - describe "#stylesheets" do - it "includes the most recent stylesheet build artifacts" do - asset_map = { - "assets" => { - "not-a-match" => nil, - "bar.css" => "bar-abc123.css", - "vendor.css" => "vendor-abc123.css", - }, - "prepend" => "foo/", - } - index_html = StringIO.new(<<~HTML) - - - - - - - HTML - assets = build_assets(name: "bar", asset_map: asset_map, index_html: index_html) - - stylesheets = assets.stylesheets - - expect(stylesheets).to match_array([ - "foo/bar-abc123.css", - "foo/vendor-abc123.css", - ]) - end - - it "passes stylesheets hosted outside the build through untouched" do - asset_map = { - "assets" => { - "bar.css" => "bar-abc123.css", - }, - "prepend" => "foo/", - } - index_html = StringIO.new(<<~HTML) - - - - - - - - HTML - assets = build_assets(name: "bar", asset_map: asset_map, index_html: index_html) - - stylesheets = assets.stylesheets - - expect(stylesheets).to match_array([ - "https://fonts.example.com/css?family=Bar", - "//fonts.example.com/protocol-relative.css", - "foo/bar-abc123.css", - ]) - end - - it "includes the stylesheets nested in the build" do - asset_map = { - "assets" => { - "bar.css" => "bar-abc123.css", - "font-awesome/css/font-awesome.min.css" => "font-awesome/css/font-awesome.min.css", - }, - "prepend" => "foo/", - } - index_html = StringIO.new(<<~HTML) - - - - - - - HTML - assets = build_assets(name: "bar", asset_map: asset_map, index_html: index_html) - - stylesheets = assets.stylesheets - - expect(stylesheets).to match_array([ - "foo/font-awesome/css/font-awesome.min.css", - "foo/bar-abc123.css", - ]) - end - - it "resolves the stylesheets referenced through a `rootURL`" do - asset_map = { - "assets" => { - "bar.css" => "bar-abc123.css", - "font-awesome/css/font-awesome.min.css" => "font-awesome/css/font-awesome.min.css", - }, - "prepend" => "foo/", - } - index_html = StringIO.new(<<~HTML) - - - - - - - HTML - assets = build_assets(name: "bar", asset_map: asset_map, index_html: index_html) - - stylesheets = assets.stylesheets - - expect(stylesheets).to match_array([ - "foo/font-awesome/css/font-awesome.min.css", - "foo/bar-abc123.css", - ]) - end - - it "prefers the asset whose path matches over one that only shares its basename" do - asset_map = { - "assets" => { - "app.css" => "app.css", - "font-awesome/css/app.css" => "font-awesome/css/app.css", - }, - "prepend" => "foo/", - } - index_html = StringIO.new(<<~HTML) - - - - - - HTML - assets = build_assets(name: "bar", asset_map: asset_map, index_html: index_html) - - stylesheets = assets.stylesheets - - expect(stylesheets).to eq(["foo/font-awesome/css/app.css"]) - end - - context "when the asset_map is empty" do - it "raises a BuildError" do - assets = build_assets(asset_map: {}, name: "bar", index_html: StringIO.new) - - expect { assets.stylesheets }.to raise_build_error - end - end - end -end - -def raise_build_error - raise_error(EmberCli::Assets::BuildError) -end - -def build_assets(asset_map: {}, **options) - EmberCli::Assets::AssetMap.new(**options.merge(asset_map: asset_map)) -end diff --git a/spec/lib/ember_cli/assets/directory_asset_map_spec.rb b/spec/lib/ember_cli/assets/directory_asset_map_spec.rb deleted file mode 100644 index 051e680..0000000 --- a/spec/lib/ember_cli/assets/directory_asset_map_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -require "tmpdir" -require "pathname" -require "fileutils" -require "ember_cli/assets/directory_asset_map" - -describe EmberCli::Assets::DirectoryAssetMap do - describe "#to_h" do - it "represents the directory" do - create_file("first") - create_file("second") - create_file("third") - - directory_manifest = build_directory_asset_map(directory).to_h - - expect(directory_manifest["prepend"]).to eq("assets/") - expect(directory_manifest["assets"]).to match a_hash_including( - "first" => "first", - "second" => "second", - "third" => "third", - ) - end - - it "represents the files nested in the directory by their path within it" do - create_file("font-awesome/css/font-awesome.min.css") - - directory_manifest = build_directory_asset_map(directory).to_h - - expect(directory_manifest["assets"]).to match a_hash_including( - "font-awesome/css/font-awesome.min.css" => "font-awesome/css/font-awesome.min.css", - ) - end - end - - def build_directory_asset_map(directory) - EmberCli::Assets::DirectoryAssetMap.new(directory) - end - - def create_file(name) - path = directory.join(name) - - FileUtils.mkdir_p(path.dirname) - FileUtils.touch(path) - - File.new(path) - end - - def directory - @directory ||= Pathname(Dir.mktmpdir) - end -end diff --git a/spec/lib/ember_cli/assets/paths_spec.rb b/spec/lib/ember_cli/assets/paths_spec.rb deleted file mode 100644 index fca8763..0000000 --- a/spec/lib/ember_cli/assets/paths_spec.rb +++ /dev/null @@ -1,53 +0,0 @@ -require "ember_cli/assets/paths" -require "fileutils" -require "pathname" -require "tmpdir" - -describe EmberCli::Assets::Paths do - describe "#package_json" do - it "is a child of EmberCli::App#root_path" do - app = build_app - paths = EmberCli::Assets::Paths.new(app) - - expect(paths.package_json).to eq app.root_path.join("package.json") - end - end - - describe "#assets" do - it "is a child of EmberCli::App#dist_path" do - app = build_app - paths = EmberCli::Assets::Paths.new(app) - - expect(paths.assets).to eq app.dist_path.join("assets") - end - end - - describe "#asset_map" do - it "globs the EmberCli::App#dist_path directory for an `asset_map.json`" do - app = build_app - paths = EmberCli::Assets::Paths.new(app) - asset_map = app.dist_path.join("assets", "assetMap-abc123.json") - create_file(asset_map) - - expect(paths.asset_map).to exist - expect(paths.asset_map).to eq(asset_map) - end - end - - def build_app - root_path = Pathname.new(Dir.mktmpdir) - - double( - root_path: root_path, - dist_path: root_path.join("dist").tap(&:mkpath), - ) - end - - def create_file(path) - path.parent.mkpath - - FileUtils.touch(path) - - path - end -end From 045faedd214b48d5675bf1facad429fcc465a325 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 17 Sep 2026 16:56:14 +0000 Subject: [PATCH 02/12] Resolve ember-cli-rails from the branch that adds the API The declared dependency names a release that does not exist yet, so CI cannot resolve it. Point the Gemfile at the branch adding the API until that release is published. Co-Authored-By: Claude Opus 5 --- Gemfile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Gemfile b/Gemfile index c939eab..182309a 100644 --- a/Gemfile +++ b/Gemfile @@ -24,3 +24,9 @@ group :test do gem "rspec-rails" end end + +# The helpers render an API that ember-cli-rails has not released yet, so +# resolve it from the branch that adds it. +# Remove this once that release is published; the gemspec constraint takes +# over from there. +gem "ember-cli-rails", github: "tricknotes/ember-cli-rails", branch: "claude/intelligent-goodall-foai0r" From e5039776ea057e32ace0e755384b702b12078c1e Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 17 Sep 2026 17:01:56 +0000 Subject: [PATCH 03/12] Depend on ember-cli-rails without naming a release yet The constraint named a release that does not exist. Name it once the release that reports a built application is published. Co-Authored-By: Claude Opus 5 --- README.md | 2 +- ember-cli-rails-assets.gemspec | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bbbf7c8..4ef6643 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ $ bundle install ``` The helpers render what [`ember-cli-rails`][ember-cli-rails] reports about a -built application, so they require `ember-cli-rails >= 0.15.0`. +built application, so they require the release of it that reports that. ## Setup diff --git a/ember-cli-rails-assets.gemspec b/ember-cli-rails-assets.gemspec index d01cf14..227d02d 100644 --- a/ember-cli-rails-assets.gemspec +++ b/ember-cli-rails-assets.gemspec @@ -16,7 +16,8 @@ Gem::Specification.new do |s| s.files = Dir["{app,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"] - # The helpers render what ember-cli-rails reports about a built - # application, so they require the release that reports it. - s.add_dependency "ember-cli-rails", ">= 0.15.0" + # The helpers render what ember-cli-rails reports about a built application. + # Constrain this to the release that reports it once that release is + # published. + s.add_dependency "ember-cli-rails" end From d38a22329ea67b13f22a93fcf13fdbc1a7a8df36 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 17 Sep 2026 17:05:00 +0000 Subject: [PATCH 04/12] Default the doubled readers with keyword arguments Later keywords win, so the caller's stubs override the defaults without building a Hash to merge. Co-Authored-By: Claude Opus 5 --- spec/helpers/ember_cli_rails_assets_helper_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/helpers/ember_cli_rails_assets_helper_spec.rb b/spec/helpers/ember_cli_rails_assets_helper_spec.rb index feba0a8..1b28fc5 100644 --- a/spec/helpers/ember_cli_rails_assets_helper_spec.rb +++ b/spec/helpers/ember_cli_rails_assets_helper_spec.rb @@ -104,7 +104,7 @@ def build_app(**stubs) app = instance_double( EmberCli::App, - **{ build: true, dev_server?: false, vite?: false }.merge(stubs), + build: true, dev_server?: false, vite?: false, **stubs, ) allow(EmberCli).to receive(:[]).with(:frontend).and_return(app) From 49a174752960967a1730da24b35840384c89ca32 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 18 Sep 2026 00:49:23 +0000 Subject: [PATCH 05/12] Record the move in the CHANGELOG Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a5dcbf..e3181fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +main +------ + +* Render what `ember-cli-rails` reports about a built application instead of deriving it here. This removes `EmberCli::Assets::Paths`, `EmberCli::Assets::Lookup`, `EmberCli::Assets::AssetMap`, `EmberCli::Assets::DirectoryAssetMap` and `EmberCli::Assets::Url`, and a missing or unresolvable asset now raises `EmberCli::BuildError` rather than `EmberCli::Assets::BuildError` +* Declare the dependency on `ember-cli-rails`, which the helpers have always needed at runtime. `ember-cli-rails` no longer depends on this gem, so an application that renders the helpers adds both to its `Gemfile` + 0.9.2 ------ From 5fdb41ca5afc9d27442767aec522c3160b22769a Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 18 Sep 2026 01:58:05 +0000 Subject: [PATCH 06/12] Drop the comments that restate the code Co-Authored-By: Claude Opus 5 --- app/helpers/ember_cli_rails_assets_helper.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/helpers/ember_cli_rails_assets_helper.rb b/app/helpers/ember_cli_rails_assets_helper.rb index 84b585f..eecd82c 100644 --- a/app/helpers/ember_cli_rails_assets_helper.rb +++ b/app/helpers/ember_cli_rails_assets_helper.rb @@ -6,8 +6,6 @@ def include_ember_script_tags(name, prepend: "") app.build if app.dev_server? || app.vite? - # Vite-based applications boot from the tags declared in their - # `index.html`, which ember-cli-rails extracts for us. safe_join(app.startup_tags(prepend: prepend).map(&:html_safe), "\n") else tags_for(app.javascript_assets(prepend: prepend)) do |src| @@ -37,9 +35,6 @@ def include_ember_stylesheet_tags(name, prepend: "") private - # Classic (Broccoli-based) builds ship a fixed set of assets, which - # ember-cli-rails reports already mounted onto `prepend`, so emit a plain - # tag per asset. def tags_for(assets) assets. map { |asset| yield(asset).html_safe }. From db9d6b5fdbea63c523c80b367b1cfbaf55efea77 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 26 Sep 2026 02:41:43 +0000 Subject: [PATCH 07/12] Exercise the helpers against a Vite build The feature suite built only a classic application, and left the Vite path of `include_ember_script_tags` to a scenario in ember-cli-rails that no longer renders the helpers. Nothing booted a Vite build from them any more. `EMBER_BUILD=vite` builds the dummy application from the Vite-based blueprint instead, and one CI job runs the feature suite against it. The views call `include_ember_stylesheet_tags` for a classic build only, as a Vite build refuses it. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 9 ++++-- bin/setup | 30 ++++++++++++++----- bin/setup_ember | 7 ++++- .../app/views/application/index.html.erb | 4 ++- .../app/views/application/relative.html.erb | 4 ++- 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2903b6a..bb02996 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ on: jobs: build: # Named explicitly so that `experimental` stays out of the job name. - name: "build (${{ matrix.ruby }}, ${{ matrix.rails }})" + name: "build (${{ matrix.ruby }}, ${{ matrix.rails }}${{ matrix.ember && format(', {0}', matrix.ember) || '' }})" runs-on: "ubuntu-latest" # Jobs normally finish in about 3 minutes, so cap hung runs well short @@ -31,6 +31,10 @@ jobs: rails: "8.0" - ruby: "4.0" rails: "8.1" + - ruby: "4.0" + rails: "8.1" + ember: "vite" + node: "22.x" - ruby: "3.4" rails: "main" experimental: true @@ -38,6 +42,7 @@ jobs: env: RAILS_ENV: test RAILS_VERSION: "${{ matrix.rails }}" + EMBER_BUILD: "${{ matrix.ember || 'classic' }}" steps: - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0 @@ -51,7 +56,7 @@ jobs: - name: Install NodeJS uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v2.5.2 with: - node-version: "20.x" + node-version: "${{ matrix.node || '20.x' }}" - name: Setup Google Chrome uses: browser-actions/setup-chrome@latest diff --git a/bin/setup b/bin/setup index 23da74a..4fa8df1 100755 --- a/bin/setup +++ b/bin/setup @@ -9,19 +9,35 @@ bundle check || bundle install # Add binstubs to PATH via export PATH=".git/safe/../../bin:$PATH" in ~/.zshenv mkdir -p .git/safe +# `classic` is pinned to the last release built by Broccoli, and `vite` to the +# Vite-based blueprint that `ember-cli >= 6.8` generates. +EMBER_BUILD="${EMBER_BUILD:-classic}" + if ! [ -d spec/dummy/my-app ]; then - # Pinned to the last release built by Broccoli: the feature suite - # exercises the classic build. The Vite path of - # `include_ember_script_tags` is exercised by ember-cli-rails' own suite. - git clone --branch v6.7.2 \ - https://github.com/kellyselden/ember-cli-output.git spec/dummy/my-app + case "$EMBER_BUILD" in + classic) + git clone --branch v6.7.2 \ + https://github.com/kellyselden/ember-cli-output.git spec/dummy/my-app + ;; + vite) + git clone --branch v7.0.0 \ + https://github.com/ember-cli/ember-new-output.git spec/dummy/my-app + ;; + *) + echo "Unsupported EMBER_BUILD '${EMBER_BUILD}'; use classic or vite" >&2 + exit 1 + ;; + esac bin/setup_ember fi root="$(pwd)" -cd ${root}/spec/dummy/my-app && - yarn add --dev ember-cli-rails-addon@rondale-sc/ember-cli-rails-addon +# `ember-cli-rails-addon` is incompatible with the Vite-based build. +if ! [ -f spec/dummy/my-app/vite.config.mjs ]; then + cd ${root}/spec/dummy/my-app && + yarn add --dev ember-cli-rails-addon@rondale-sc/ember-cli-rails-addon +fi cd ${root}/spec/dummy && bundle exec rake ember:install diff --git a/bin/setup_ember b/bin/setup_ember index 129c2d9..efc3ed6 100755 --- a/bin/setup_ember +++ b/bin/setup_ember @@ -6,6 +6,11 @@ set -e sed -i -e 's/history/hash/' spec/dummy/my-app/config/environment.js # add an image to a template -echo '' >> spec/dummy/my-app/app/templates/application.hbs +if [ -f spec/dummy/my-app/app/templates/application.gjs ]; then + sed -i -e 's|| \n|' \ + spec/dummy/my-app/app/templates/application.gjs +else + echo '' >> spec/dummy/my-app/app/templates/application.hbs +fi mkdir -p spec/dummy/my-app/public/assets cp spec/fixtures/logo.png spec/dummy/my-app/public/assets/ diff --git a/spec/dummy/app/views/application/index.html.erb b/spec/dummy/app/views/application/index.html.erb index 8d07285..4f7e45a 100644 --- a/spec/dummy/app/views/application/index.html.erb +++ b/spec/dummy/app/views/application/index.html.erb @@ -1,2 +1,4 @@ <%= include_ember_script_tags "my-app" %> -<%= include_ember_stylesheet_tags "my-app" %> +<% unless EmberCli["my-app"].vite? %> + <%= include_ember_stylesheet_tags "my-app" %> +<% end %> diff --git a/spec/dummy/app/views/application/relative.html.erb b/spec/dummy/app/views/application/relative.html.erb index 5ca1932..4786707 100644 --- a/spec/dummy/app/views/application/relative.html.erb +++ b/spec/dummy/app/views/application/relative.html.erb @@ -1,2 +1,4 @@ <%= include_ember_script_tags "my-app", prepend: root_url %> -<%= include_ember_stylesheet_tags "my-app", prepend: root_url %> +<% unless EmberCli["my-app"].vite? %> + <%= include_ember_stylesheet_tags "my-app", prepend: root_url %> +<% end %> From 3a9d2633de07d896af9b7c8d1af6a66006cf6152 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 26 Sep 2026 05:42:28 +0000 Subject: [PATCH 08/12] Read the application through EmberCli::Embedding ember-cli-rails reports what a built application boots from through `EmberCli::Embedding` instead of `EmberCli::App`, and decides whether it boots from startup tags, so the helpers no longer combine `dev_server?` and `vite?` themselves. Co-Authored-By: Claude Opus 5.5 --- app/helpers/ember_cli_rails_assets_helper.rb | 23 ++++--- .../ember_cli_rails_assets_helper_spec.rb | 67 ++++++------------- 2 files changed, 35 insertions(+), 55 deletions(-) diff --git a/app/helpers/ember_cli_rails_assets_helper.rb b/app/helpers/ember_cli_rails_assets_helper.rb index eecd82c..dc8953d 100644 --- a/app/helpers/ember_cli_rails_assets_helper.rb +++ b/app/helpers/ember_cli_rails_assets_helper.rb @@ -2,23 +2,21 @@ module EmberCliRailsAssetsHelper def include_ember_script_tags(name, prepend: "") - app = EmberCli[name] - app.build + embedding = build_ember_embedding(name) - if app.dev_server? || app.vite? - safe_join(app.startup_tags(prepend: prepend).map(&:html_safe), "\n") + if embedding.startup_tags? + safe_join(embedding.startup_tags(prepend: prepend).map(&:html_safe), "\n") else - tags_for(app.javascript_assets(prepend: prepend)) do |src| + tags_for(embedding.javascript_assets(prepend: prepend)) do |src| %{} end end end def include_ember_stylesheet_tags(name, prepend: "") - app = EmberCli[name] - app.build + embedding = build_ember_embedding(name) - if app.dev_server? || app.vite? + if embedding.startup_tags? raise EmberCli::Assets::NotSupportedError, <<~MSG `include_ember_stylesheet_tags` does not support Vite-based applications (`ember-cli >= 6.8`). @@ -28,13 +26,20 @@ def include_ember_stylesheet_tags(name, prepend: "") MSG end - tags_for(app.stylesheet_assets(prepend: prepend)) do |href| + tags_for(embedding.stylesheet_assets(prepend: prepend)) do |href| %{} end end private + def build_ember_embedding(name) + app = EmberCli[name] + app.build + + EmberCli::Embedding.new(app) + end + def tags_for(assets) assets. map { |asset| yield(asset).html_safe }. diff --git a/spec/helpers/ember_cli_rails_assets_helper_spec.rb b/spec/helpers/ember_cli_rails_assets_helper_spec.rb index 1b28fc5..194ec77 100644 --- a/spec/helpers/ember_cli_rails_assets_helper_spec.rb +++ b/spec/helpers/ember_cli_rails_assets_helper_spec.rb @@ -2,42 +2,28 @@ describe EmberCliRailsAssetsHelper do describe "#include_ember_script_tags" do - context "when the application is served by Vite's development server" do - it "emits the startup tags ember-cli-rails read from the server" do - app = build_app( - dev_server?: true, + context "when the application boots from startup tags" do + it "emits the startup tags ember-cli-rails reads, mounted onto `prepend`" do + app, embedding = build_embedding( + startup_tags?: true, startup_tags: [ - %{}, - %{}, + %{}, + %{}, ], ) - tags = helper.include_ember_script_tags(:frontend) - - expect(app).to have_received(:build) - expect(app).to have_received(:startup_tags).with(prepend: "") - expect(tags).to include(%{src="http://127.0.0.1:4200/@vite/client"}) - expect(tags).to include(%{href="http://127.0.0.1:4200/app.css"}) - end - end - - context "when the application is built with Vite" do - it "emits the startup tags with the mount point joined onto them" do - app = build_app( - vite?: true, - startup_tags: [%{}], - ) - tags = helper.include_ember_script_tags(:frontend, prepend: "/admin") - expect(app).to have_received(:startup_tags).with(prepend: "/admin") + expect(app).to have_received(:build) + expect(embedding).to have_received(:startup_tags).with(prepend: "/admin") expect(tags).to include(%{src="/admin/app.js"}) + expect(tags).to include(%{href="/admin/app.css"}) end end context "when the application is a classic build" do it "emits the scripts as ember-cli-rails reports them, mounted onto `prepend`" do - app = build_app( + app, embedding = build_embedding( javascript_assets: [ "http://example.com/assets/vendor-abc123.js", "https://cdn.example.com/analytics.js", @@ -47,7 +33,8 @@ tags = helper.include_ember_script_tags(:frontend, prepend: "http://example.com/") - expect(app).to have_received(:javascript_assets). + expect(app).to have_received(:build) + expect(embedding).to have_received(:javascript_assets). with(prepend: "http://example.com/") expect(tags).to include(%{src="http://example.com/assets/vendor-abc123.js"}) expect(tags).to include(%{src="https://cdn.example.com/analytics.js"}) @@ -57,20 +44,9 @@ end describe "#include_ember_stylesheet_tags" do - context "when the application is served by Vite's development server" do - it "raises an error pointing at `include_ember_script_tags`" do - build_app(dev_server?: true) - - expect { helper.include_ember_stylesheet_tags(:frontend) }.to raise_error( - EmberCli::Assets::NotSupportedError, - /include_ember_script_tags/, - ) - end - end - - context "when the application is built with Vite" do + context "when the application boots from startup tags" do it "raises an error pointing at `include_ember_script_tags`" do - build_app(vite?: true) + build_embedding(startup_tags?: true) expect { helper.include_ember_stylesheet_tags(:frontend) }.to raise_error( EmberCli::Assets::NotSupportedError, @@ -81,7 +57,7 @@ context "when the application is a classic build" do it "emits the stylesheets as ember-cli-rails reports them, mounted onto `prepend`" do - app = build_app( + app, embedding = build_embedding( stylesheet_assets: [ "http://example.com/assets/vendor-abc123.css", "https://fonts.example.com/css?family=Frontend", @@ -92,7 +68,7 @@ tags = helper.include_ember_stylesheet_tags(:frontend, prepend: "http://example.com/") expect(app).to have_received(:build) - expect(app).to have_received(:stylesheet_assets). + expect(embedding).to have_received(:stylesheet_assets). with(prepend: "http://example.com/") expect(tags).to include(%{href="http://example.com/assets/vendor-abc123.css"}) expect(tags).to include(%{href="https://fonts.example.com/css?family=Frontend"}) @@ -101,13 +77,12 @@ end end - def build_app(**stubs) - app = instance_double( - EmberCli::App, - build: true, dev_server?: false, vite?: false, **stubs, - ) + def build_embedding(**stubs) + app = instance_double(EmberCli::App, build: true) + embedding = instance_double(EmberCli::Embedding, startup_tags?: false, **stubs) allow(EmberCli).to receive(:[]).with(:frontend).and_return(app) + allow(EmberCli::Embedding).to receive(:new).with(app).and_return(embedding) - app + [app, embedding] end end From cf7b7744590b173ac092f809218af7d3fc917321 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 26 Sep 2026 08:05:15 +0000 Subject: [PATCH 09/12] Set up the dummy application with Vite by default `ember-cli >= 6.8` generates Vite-based applications, so `bin/setup` builds the dummy application that way unless `EMBER_BUILD=classic` asks for the Broccoli-based one. CI names the build of every job explicitly, so its jobs are unaffected. Co-Authored-By: Claude Opus 5.5 --- CONTRIBUTING.md | 5 +++++ bin/setup | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 35f28f8..02b882f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,6 +16,11 @@ After cloning the repository, execute the setup script: $ bin/setup +It builds the dummy Ember application from the Vite-based blueprint. +To build it with the classic (Broccoli-based) pipeline instead, remove `spec/dummy/my-app` if it exists and set `EMBER_BUILD`: + + $ EMBER_BUILD=classic bin/setup + Make sure the tests pass: $ bin/rake diff --git a/bin/setup b/bin/setup index 4fa8df1..4e79bb1 100755 --- a/bin/setup +++ b/bin/setup @@ -9,9 +9,8 @@ bundle check || bundle install # Add binstubs to PATH via export PATH=".git/safe/../../bin:$PATH" in ~/.zshenv mkdir -p .git/safe -# `classic` is pinned to the last release built by Broccoli, and `vite` to the -# Vite-based blueprint that `ember-cli >= 6.8` generates. -EMBER_BUILD="${EMBER_BUILD:-classic}" +# `vite` is pinned to the Vite-based blueprint that `ember-cli >= 6.8` generates, and `classic` to the last release built by Broccoli. +EMBER_BUILD="${EMBER_BUILD:-vite}" if ! [ -d spec/dummy/my-app ]; then case "$EMBER_BUILD" in From 182c9b711c8f84618f8446636bc3b3778e54b492 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 26 Sep 2026 08:08:48 +0000 Subject: [PATCH 10/12] Build the dummy application with Vite in CI by default Every Ruby and Rails combination now runs the suite against the Vite-based build, which `ember-cli >= 6.8` generates and `bin/setup` now builds by default. The classic build runs at both ends of the supported range: Ruby 3.2, Rails 7.0 and Node 20, and Ruby 4.0, Rails 8.1 and Node 22. Jobs are named after their Ruby and Rails versions as before, with `classic` added to the classic ones. Node defaults to 22, as the Vite-based blueprint needs Node 20.19 or later. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb02996..e611f7c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,8 @@ on: jobs: build: # Named explicitly so that `experimental` stays out of the job name. - name: "build (${{ matrix.ruby }}, ${{ matrix.rails }}${{ matrix.ember && format(', {0}', matrix.ember) || '' }})" + # The Vite-based build is the default, so only the classic one is named. + name: "build (${{ matrix.ruby }}, ${{ matrix.rails }}${{ matrix.ember != 'vite' && format(', {0}', matrix.ember) || '' }})" runs-on: "ubuntu-latest" # Jobs normally finish in about 3 minutes, so cap hung runs well short @@ -24,25 +25,35 @@ jobs: matrix: ruby: ["3.2", "3.3"] rails: ["7.0", "7.1", "7.2"] + # A key of the matrix itself, so that the classic builds below run alongside these rather than replacing them. + ember: ["vite"] include: - ruby: "3.3" rails: "8.0" + ember: "vite" - ruby: "3.4" rails: "8.0" - - ruby: "4.0" - rails: "8.1" + ember: "vite" - ruby: "4.0" rails: "8.1" ember: "vite" - node: "22.x" - ruby: "3.4" rails: "main" + ember: "vite" experimental: true + # The classic build at both ends of the supported range: the oldest Ruby, Rails and Node, and the newest. + - ruby: "3.2" + rails: "7.0" + ember: "classic" + node: "20.x" + - ruby: "4.0" + rails: "8.1" + ember: "classic" env: RAILS_ENV: test RAILS_VERSION: "${{ matrix.rails }}" - EMBER_BUILD: "${{ matrix.ember || 'classic' }}" + EMBER_BUILD: "${{ matrix.ember }}" steps: - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0 @@ -56,7 +67,7 @@ jobs: - name: Install NodeJS uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v2.5.2 with: - node-version: "${{ matrix.node || '20.x' }}" + node-version: "${{ matrix.node || '22.x' }}" - name: Setup Google Chrome uses: browser-actions/setup-chrome@latest From e14f827ad2171be6fc5e56b127a8c0eb4f6ab3f1 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 26 Sep 2026 15:00:19 +0000 Subject: [PATCH 11/12] Run CI on Node 26 and the Vite build on Ruby 4.0 across Rails Node defaults to 26, the newest release, while the oldest classic build stays on Node 20. The Vite build also runs Ruby 4.0 with Rails 7.2 and 8.0, the combinations ember-cli-rails itself runs on Ruby 4.0. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e611f7c..46a94d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,12 @@ jobs: - ruby: "3.4" rails: "8.0" ember: "vite" + - ruby: "4.0" + rails: "7.2" + ember: "vite" + - ruby: "4.0" + rails: "8.0" + ember: "vite" - ruby: "4.0" rails: "8.1" ember: "vite" @@ -67,7 +73,7 @@ jobs: - name: Install NodeJS uses: actions/setup-node@7c12f8017d5436eb855f1ed4399f037a36fbd9e8 # v2.5.2 with: - node-version: "${{ matrix.node || '22.x' }}" + node-version: "${{ matrix.node || '26.x' }}" - name: Setup Google Chrome uses: browser-actions/setup-chrome@latest From a6a8dc60adda45cfdd524720cbf9944c9651b57d Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 26 Sep 2026 15:00:48 +0000 Subject: [PATCH 12/12] Name what each version in a CI job name is for Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 46a94d0..338cdac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: build: # Named explicitly so that `experimental` stays out of the job name. # The Vite-based build is the default, so only the classic one is named. - name: "build (${{ matrix.ruby }}, ${{ matrix.rails }}${{ matrix.ember != 'vite' && format(', {0}', matrix.ember) || '' }})" + name: "build (Ruby ${{ matrix.ruby }}, Rails ${{ matrix.rails }}${{ matrix.ember != 'vite' && format(', {0}', matrix.ember) || '' }})" runs-on: "ubuntu-latest" # Jobs normally finish in about 3 minutes, so cap hung runs well short