rails / tailwindcss-rails

Other
1.39k stars 170 forks source link

Upgrading tailwindcss-rails from 2.0.29 to 2.0.30 broke web-console #275

Closed pupeno closed 4 months ago

pupeno commented 1 year ago

I'm not sure if this is a problem in web-console or in tailwindcss-rails. I'm cross-posting it here for awareness in case it's tailwindcss-rails. I will continue debugging the problem and create a PR if I find what it is, but if you know anything, since you are more familiar with the code, please let me know. All guidance is welcome.

Full details of the issue are on https://github.com/rails/web-console/issues/326

flavorjones commented 1 year ago

cc @rmehner It seems reasonable to suspect the change in #271 might be responsible.

rmehner commented 1 year ago

@pupeno

Thanks for the report and I'm sorry that you've run into a problem. I've created a new Rails project and added rspec to it and this works without a problem. Can also not reproduce in any of our projects that are using tailwindcss-rails.

Will try to reproduce with your repo next.

rmehner commented 1 year ago

hey @pupeno,

I dug a bit deeper and haven't found out the root issue, but can reproduce with your repo. Doing RAILS_ENV=test rake spec fixes the issue for what it's worth, but need to dig deeper on the root cause.

We're not the first gem affected by this, see this issue on dotenv-rails: https://github.com/bkeepers/dotenv/issues/395#issuecomment-637196418

However, I've tried this with several of our projects that use tailwindcss-rails and rspec and none of the projects showed this behaviour, so it must be something within repeater-world that triggers this behaviour.

Sorry that I have no clear fix, but hope this helps a least a little bit.

pupeno commented 1 year ago

Oh wow, this one is a bit tricky than I expected. One of the issues for me is that the bug is being triggered when I run the tests from RubyMine, where I might not have as much control on how they are run, but I'll investigate.

Thank you so much for all the work here. I appreciate it :)

phylor commented 10 months ago

I'm having the same issue.

What I've found:

If I raise in the web-console gem (cf. https://github.com/rails/web-console/issues/326#issuecomment-1664137494), the error output is:

rails aborted!
Bundler::GemRequireError: There was an error while trying to load the gem 'web-console'.
Gem Load Error is: webconsole! Rails.env=test Rails.groups=[:default, "test"]
Backtrace for gem load error is:
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/web-console-4.2.1/lib/web-console.rb:3:in `<top (required)>'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.3.20/lib/bundler/runtime.rb:60:in `require'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.3.20/lib/bundler/runtime.rb:60:in `block (2 levels) in require'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.3.20/lib/bundler/runtime.rb:55:in `each'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.3.20/lib/bundler/runtime.rb:55:in `block in require'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.3.20/lib/bundler/runtime.rb:44:in `each'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.3.20/lib/bundler/runtime.rb:44:in `require'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.3.20/lib/bundler.rb:188:in `require'
/home/user/myproject/config/application.rb:7:in `<top (required)>'
/home/user/myproject/Rakefile:4:in `require_relative'
/home/user/myproject/Rakefile:4:in `<top (required)>'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/rake_module.rb:29:in `load'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/rake_module.rb:29:in `load_rakefile'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/application.rb:710:in `raw_load_rakefile'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/application.rb:104:in `block in load_rakefile'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/application.rb:186:in `standard_exception_handling'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/application.rb:103:in `load_rakefile'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.8/lib/rails/commands/rake/rake_command.rb:20:in `block in perform'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/rake_module.rb:59:in `with_application'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.8/lib/rails/commands/rake/rake_command.rb:18:in `perform'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.8/lib/rails/command.rb:51:in `invoke'
/home/user/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.0.8/lib/rails/commands.rb:18:in `<top (required)>'
bin/rails:4:in `require'
bin/rails:4:in `<main>'
Bundler Error Backtrace:
/home/user/myproject/config/application.rb:7:in `<top (required)>'
/home/user/myproject/Rakefile:4:in `require_relative'
/home/user/myproject/Rakefile:4:in `<top (required)>'
bin/rails:4:in `require'
bin/rails:4:in `<main>'

Caused by:
webconsole! Rails.env=test Rails.groups=[:default, "test"]
/home/user/myproject/config/application.rb:7:in `<top (required)>'
/home/user/myproject/Rakefile:4:in `require_relative'
/home/user/myproject/Rakefile:4:in `<top (required)>'
bin/rails:4:in `require'
bin/rails:4:in `<main>'

In the gem, Rails.env is test and Rails.groups is [:default, "test"].

The same happens for every gem in the development group. So I suspect that all development gems are loaded when invoking a rake task, irrelevant of the current Rails environment.

That's why it's probably not a tailwindcss-rails or web-console issue, but rather might be an issue with railties (rails/commands) or how rake is invoked.

pupeno commented 10 months ago

Where should this bug be reported then, do you know?

pupeno commented 10 months ago

I added a raise to web-console.rb and I got a bit of a different traceback:

rake aborted!
Bundler::GemRequireError: There was an error while trying to load the gem 'web-console'.
Gem Load Error is: web console is being required when it shouldn't
Backtrace for gem load error is:
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/web-console-4.2.1/lib/web-console.rb:3:in `<main>'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.12/lib/zeitwerk/kernel.rb:38:in `require'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.3.7/lib/bundler/runtime.rb:60:in `block (2 levels) in require'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.3.7/lib/bundler/runtime.rb:55:in `each'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.3.7/lib/bundler/runtime.rb:55:in `block in require'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.3.7/lib/bundler/runtime.rb:44:in `each'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.3.7/lib/bundler/runtime.rb:44:in `require'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.3.7/lib/bundler.rb:176:in `require'
/home/pupeno/repeater_world/config/application.rb:33:in `<top (required)>'
/home/pupeno/repeater_world/Rakefile:18:in `require_relative'
/home/pupeno/repeater_world/Rakefile:18:in `<top (required)>'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/rake_module.rb:29:in `load'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/rake_module.rb:29:in `load_rakefile'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/application.rb:710:in `raw_load_rakefile'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/application.rb:104:in `block in load_rakefile'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/application.rb:186:in `standard_exception_handling'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/application.rb:103:in `load_rakefile'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/application.rb:82:in `block in run'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/application.rb:186:in `standard_exception_handling'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/lib/rake/application.rb:80:in `run'
/home/pupeno/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.0.6/exe/rake:27:in `<top (required)>'
/home/pupeno/.rbenv/versions/3.2.2/bin/rake:25:in `load'
/home/pupeno/.rbenv/versions/3.2.2/bin/rake:25:in `<main>'
Bundler Error Backtrace:
/home/pupeno/repeater_world/config/application.rb:33:in `<top (required)>'
/home/pupeno/repeater_world/Rakefile:18:in `require_relative'
/home/pupeno/repeater_world/Rakefile:18:in `<top (required)>'

Caused by:
web console is being required when it shouldn't
/home/pupeno/repeater_world/config/application.rb:33:in `<top (required)>'
/home/pupeno/repeater_world/Rakefile:18:in `require_relative'
/home/pupeno/repeater_world/Rakefile:18:in `<top (required)>'
(See full trace by running task with --trace)
pupeno commented 10 months ago

RAILS_ENV=test rake spec works, so maybe bundler is loading everything on development, because that's the default, before Rails switches to test, and by then it's too late?

phylor commented 10 months ago

@pupeno Further findings after some more debugging:

  1. For me, this also happens with tailwindcss-rails 2.0.29

  2. I can't reproduce it in a new Rails project

  3. When running bin/rails spec, Rails is first loaded in the development environment. As soon as the spec rake task is loaded, Rails is re-loaded using the test environment.

  4. For me the problem is fixed by removing the following line: https://github.com/rails/tailwindcss-rails/blob/ad7edc914a33fb7e2b005135210e2e804e0abded/lib/tasks/build.rake#L24

    In my projects, all three tasks are defined: test:prepare, spec:prepare and db:test:prepare. Because tailwindcss-rails uses an if -> elsif, only test:prepare is enhanced in my tests. So if I don't enhance that, bin/rails spec works fine. Enhancing db:test:prepare is not an issue - even if I enforce the enhancing, bin/rails spec works fine. If I enforce enhancing either test:prepare or spec:prepare, bin/rails spec fails.

  5. Rake::Task.enhance supports two invocations:

    # Runs tailwindcss:build BEFORE spec:prepare
    Rake::Task["spec:prepare"].enhance(["tailwindcss:build"])
    
    # Runs tailwindcss:build AFTER spec:prepare
    Rake::Task["spec:prepare"].enhance do
      Rake::Task["tailwindcss:build"].execute
    end

    spec:prepare sets RAILS_ENV=test. By running spec:prepare before building the Tailwind assets, the load errors are fixed. I'm not yet sure why this happens though and why it matters. Running tailwindcss:build in the development environment shouldn't produce any load errors. Interestingly enough, the body of the tailwindcss:build Rake task is not executed at all. So the load error happens before invoking it.

@pupeno Could you try the following and let us know if that fixes the issue for you as well?

bundle open tailwindcss-rails
# Navigate to lib/tasks/build.rake

Replace the last if-elsif with the following:

if Rake::Task.task_defined?("test:prepare")
  Rake::Task["test:prepare"].enhance do
    Rake::Task['tailwindcss:build'].execute
  end
elsif Rake::Task.task_defined?("spec:prepare")
  Rake::Task["spec:prepare"].enhance do
    Rake::Task['tailwindcss:build'].execute
  end
elsif Rake::Task.task_defined?("db:test:prepare")
  Rake::Task["db:test:prepare"].enhance(["tailwindcss:build"])
end

Then run bin/rails spec again.

pupeno commented 10 months ago

@phylor wow, yes, that change fixes it for me.

phylor commented 10 months ago

2.0.24 is the first failing release for me. More specifically, the following change causes the exception:

https://github.com/rails/tailwindcss-rails/blob/8159bd8652bb8f545f3ad7397d59b6e4deb1c89c/lib/tasks/build.rake#L3

Before, Rails wasn't loaded:

task :watch do |_, args|

With that change, bin/rails spec runs fine again. Also without my patch from above.

I also just noticed that I get an exception when invoking the rspec generators. Instead of calling the generator, it seems to reload Rails again causing a pending migration exception (with and without the above patch). I can't reproduce that issue in a clean project, so there must be something wrong in the project. This also happens after removing tailwindcss-rails from the bundle.

@pupeno Do you have that same problem as well? Do your generators work fine? If so, this is probably an unrelated issue.

bin/rails g model Car ``` invoke active_record create db/migrate/20231104145922_create_cars.rb create app/models/car.rb invoke rspec Migrations are pending. To resolve this issue, run: bin/rails db:migrate RAILS_ENV=development You have 1 pending migration: 20231104145922_create_cars.rb While loading rails_helper an `exit` / `raise SystemExit` occurred, RSpec will now quit. Failure/Error: abort e.to_s.strip SystemExit: Migrations are pending. To resolve this issue, run: bin/rails db:migrate RAILS_ENV=development You have 1 pending migration: 20231104145922_create_cars.rb # ./spec/rails_helper.rb:53:in `abort' # ./spec/rails_helper.rb:53:in `rescue in
' # ./spec/rails_helper.rb:50:in `
' # ------------------ # --- Caused by: --- # ActiveRecord::PendingMigrationError: # # # Migrations are pending. To resolve this issue, run: # # bin/rails db:migrate RAILS_ENV=development # # You have 1 pending migration: # # 20231104145922_create_cars.rb # ./spec/rails_helper.rb:51:in `
' ```
pupeno commented 10 months ago

No, I don't seem to be having that issue:

$ bin/rails g model Car
      invoke  active_record
      create    db/migrate/20231104155727_create_cars.rb
      create    app/models/car.rb
      invoke    rspec
      create      spec/models/car_spec.rb
      invoke      factory_bot
      create        spec/factories/cars.rb
Coverage report generated for RSpec to /home/pupeno/repeater_world/coverage. 0 / 3279 LOC (0.0%) covered.
flavorjones commented 8 months ago

I'd like someone on this issue who understands what's going on, and can reproduce it, to submit a pull request, please. @phylor?

phylor commented 8 months ago

@flavorjones Unfortunately, I don't fully understand the issue.

I bisected the failing project again and I observed the following:

tailwindcss-rails version status
2.0.23 ok
2.0.24 fails
2.0.31 fails
2.0.32 ok
2.0.33 fails

Workarounds I found:

Exception on failing status ``` Web Console is activated in the test environment. This is usually a mistake. To ensure it's only activated in development mode, move it to the development group of your Gemfile: gem 'web-console', group: :development If you still want to run it in the test environment (and know what you are doing), put this in your Rails application configuration: config.web_console.development_only = false ```

Looking at the changes between 2.0.31 and 2.0.32 I'm not really sure why 2.0.32 suddenly works. Maybe the rubygems version is relevant, I couldn't yet pinpoint that though. And then I can't explain why version 2.0.33 starts to fail again.

flavorjones commented 4 months ago

Closing. If someone can help me reproduce and diagnose this, I'm happy to reopen.