shrinerb / shrine

File Attachment toolkit for Ruby applications
https://shrinerb.com
MIT License
3.18k stars 275 forks source link

Shrine & S3 storage incompatibility with Ruby 3.0.2 #559

Closed tjozwik closed 2 years ago

tjozwik commented 2 years ago

Brief Description

After upgrading Ruby from 2.7.4 to 3.0.2, rake db:migrate task fails on Shrine S3 Storage initializer.

Expected behavior

Migrations succeeds - Shrine's initializer does not fail.

Actual behavior

It fails on shrine/storage/s3.rb:345. Complete traceback:

Run bundle exec rails db:migrate
rails aborted!
ArgumentError: wrong number of arguments (given 1, expected 0)
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/bundler/gems/shrine-6bfb2dae0a00/lib/shrine/storage/s3.rb:345:in `initialize'
/home/runner/work/project-rails/project-rails/config/initializers/shrine.rb:7:in `new'
/home/runner/work/project-rails/project-rails/config/initializers/shrine.rb:7:in `<main>'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:60:in `load'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:60:in `load'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/activesupport-6.1.4.1/lib/active_support/dependencies.rb:326:in `block in load'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/activesupport-6.1.4.1/lib/active_support/dependencies.rb:299:in `load_dependency'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/activesupport-6.1.4.1/lib/active_support/dependencies.rb:326:in `load'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/engine.rb:681:in `block in load_config_initializer'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/activesupport-6.1.4.1/lib/active_support/notifications.rb:205:in `instrument'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/engine.rb:680:in `load_config_initializer'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/engine.rb:634:in `block (2 levels) in <class:Engine>'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/engine.rb:633:in `each'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/engine.rb:633:in `block in <class:Engine>'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/initializable.rb:32:in `instance_exec'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/initializable.rb:32:in `run'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/initializable.rb:61:in `block in run_initializers'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/initializable.rb:50:in `each'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/initializable.rb:50:in `tsort_each_child'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/initializable.rb:60:in `run_initializers'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/application.rb:391:in `initialize!'
/home/runner/work/project-rails/project-rails/config/environment.rb:5:in `<main>'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/skylight-core-4.3.2/lib/skylight/core/probes.rb:118:in `require'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/zeitwerk-2.4.2/lib/zeitwerk/kernel.rb:34:in `require'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/activesupport-6.1.4.1/lib/active_support/dependencies.rb:332:in `block in require'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/activesupport-6.1.4.1/lib/active_support/dependencies.rb:299:in `load_dependency'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/activesupport-6.1.4.1/lib/active_support/dependencies.rb:332:in `require'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/application.rb:367:in `require_environment!'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/application.rb:533:in `block in run_tasks_blocks'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:281:in `block in execute'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:281:in `each'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:281:in `execute'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:219:in `block in invoke_with_call_chain'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `synchronize'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `invoke_with_call_chain'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:243:in `block in invoke_prerequisites'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:241:in `each'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:241:in `invoke_prerequisites'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:218:in `block in invoke_with_call_chain'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `synchronize'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `invoke_with_call_chain'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:243:in `block in invoke_prerequisites'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:241:in `each'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:241:in `invoke_prerequisites'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:218:in `block in invoke_with_call_chain'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `synchronize'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `invoke_with_call_chain'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:188:in `invoke'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:160:in `invoke_task'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:116:in `each'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:116:in `block in top_level'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:125:in `run_with_threads'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:110:in `top_level'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/commands/rake/rake_command.rb:24:in `block (2 levels) in perform'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:186:in `standard_exception_handling'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/commands/rake/rake_command.rb:24:in `block in perform'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/rake_module.rb:59:in `with_application'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/commands/rake/rake_command.rb:18:in `perform'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/command.rb:50:in `invoke'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/railties-6.1.4.1/lib/rails/commands.rb:18:in `<main>'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
/home/runner/work/project-rails/project-rails/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.9.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
Tasks: TOP => db:migrate => db:load_config => environment
(See full trace by running task with --trace)

Simplest self-contained example code to demonstrate issue

config/initializers/shrine.rb file:

require 'shrine'
require 'shrine/storage/file_system'
require 'shrine/storage/s3'

Shrine.storages = {
  cache: Shrine::Storage::FileSystem.new(Dir.tmpdir),
  store: Shrine::Storage::S3.new(
    # Hash with working object storage access configuration is placed there
  )
}

Shrine.plugin :signature

System configuration

Ruby version: 3.0.2 (& Rails 6.1.4.1)

Shrine version: both 3.4.0 & current repo's head (6bfb2da)

tjozwik commented 2 years ago

Ok. It's not Shrine's fault. Ruby 3.0 instroduced braking changes in positional and keyword arguments (https://makandracards.com/makandra/496481-changes-to-positional-and-keyword-args-in-ruby-3-0).

So:

store: Shrine::Storage::S3.new(
  { foo: :bar }
)

needs to be converted to:

store: Shrine::Storage::S3.new(
  **{ foo: :bar }
)