diff --git a/.rubocop.yml b/.rubocop.yml index 0a0acb02..1769177e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -29,6 +29,11 @@ Layout/LineLength: Layout/MultilineMethodCallIndentation: EnforcedStyle: indented_relative_to_receiver +# Hash brace spacing is handled by prettier-ruby (@prettier/plugin-ruby), which +# breaks empty hashes onto two lines and would otherwise conflict with rubocop. +Layout/SpaceInsideHashLiteralBraces: + Enabled: false + Lint/AmbiguousBlockAssociation: AllowedMethods: [change] @@ -96,6 +101,11 @@ Style/Documentation: Style/DoubleNegation: Enabled: false +# prettier-ruby always expands empty methods to `def foo\nend`. Disable +# rubocop's preference for `def foo; end` so the two stay aligned. +Style/EmptyMethod: + Enabled: false + Style/FormatStringToken: Enabled: false diff --git a/.ruby-version b/.ruby-version index 1cf82530..7bcbb380 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.4.6 +3.4.9 diff --git a/.tool-versions b/.tool-versions index cc2bdd4b..52b82276 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -ruby 3.4.6 -nodejs 24.14.1 +ruby 3.4.9 +nodejs 24.16.0 yarn 1.22.22 diff --git a/CHANGELOG.md b/CHANGELOG.md index d7865e2e..fe7a9c9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## master +- Bump dependencies (rack 3.1.19 → 3.2.6, rake, rspec-\*, timecop, simplecov-html, diff-lcs) +- Bump Ruby to 3.4.9 (zlib CVE-2026-27820) +- Bump Node.js to 24.16.0 in `.tool-versions` +- Repair `yarn format:check`: add `syntax_tree` to the dev group (required by `@prettier/plugin-ruby` 4.x), reformat 11 spec files, and disable rubocop cops that conflict with prettier-ruby (`Layout/SpaceInsideHashLiteralBraces`, `Style/EmptyMethod`) + ## 9.0.0 **BREAKING CHANGES:** diff --git a/Gemfile b/Gemfile index 9c0b5c45..3a3f17ec 100644 --- a/Gemfile +++ b/Gemfile @@ -12,6 +12,7 @@ group :development do gem 'rubocop-performance', require: false gem 'rubocop-rake', require: false gem 'rubocop-rspec', require: false + gem 'syntax_tree', require: false end group :development, :test do diff --git a/Gemfile.lock b/Gemfile.lock index fbf95232..41252592 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -19,7 +19,7 @@ GEM debug (1.11.1) irb (~> 1.10) reline (>= 0.3.8) - diff-lcs (1.5.1) + diff-lcs (1.6.2) docile (1.4.1) erb (6.0.4) hashdiff (1.2.1) @@ -38,6 +38,7 @@ GEM racc pp (0.6.3) prettyprint + prettier_print (1.2.1) prettyprint (0.2.0) prism (1.9.0) psych (5.3.1) @@ -45,9 +46,9 @@ GEM stringio public_suffix (7.0.5) racc (1.8.1) - rack (3.1.19) + rack (3.2.6) rainbow (3.1.1) - rake (13.2.1) + rake (13.4.2) rdoc (7.2.0) erb psych (>= 4.0.0) @@ -56,19 +57,19 @@ GEM reline (0.6.3) io-console (~> 0.5) rexml (3.4.4) - rspec (3.13.0) + rspec (3.13.2) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) - rspec-core (3.13.4) + rspec-core (3.13.6) rspec-support (~> 3.13.0) rspec-expectations (3.13.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-mocks (3.13.5) + rspec-mocks (3.13.8) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-support (3.13.1) + rspec-support (3.13.7) rubocop (1.86.2) json (~> 2.3) language_server-protocol (~> 3.17.0.2) @@ -98,10 +99,12 @@ GEM docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) - simplecov-html (0.13.1) + simplecov-html (0.13.2) simplecov_json_formatter (0.1.4) stringio (3.2.0) - timecop (0.9.10) + syntax_tree (6.3.0) + prettier_print (>= 1.2.0) + timecop (0.9.11) tsort (0.2.0) unicode-display_width (3.2.0) unicode-emoji (~> 4.1) @@ -125,6 +128,7 @@ DEPENDENCIES rubocop-rake rubocop-rspec simplecov + syntax_tree timecop webmock diff --git a/castle-rb.gemspec b/castle-rb.gemspec index 77ed2767..fad325bc 100644 --- a/castle-rb.gemspec +++ b/castle-rb.gemspec @@ -28,7 +28,7 @@ Gem::Specification.new do |s| 'rubygems_mfa_required' => 'true' } - s.files = Dir['{lib}/**/*'] + ['README.md', 'LICENSE', 'CHANGELOG.md'] + s.files = Dir['{lib}/**/*'] + %w[README.md LICENSE CHANGELOG.md] s.require_paths = ['lib'] s.required_ruby_version = '>= 3.2' diff --git a/spec/integration/rails/support/home_controller.rb b/spec/integration/rails/support/home_controller.rb index 06013a4f..a7827a75 100644 --- a/spec/integration/rails/support/home_controller.rb +++ b/spec/integration/rails/support/home_controller.rb @@ -4,12 +4,7 @@ class HomeController < ActionController::Base # prepare context and call risk via the client def index1 request_context = ::Castle::Context::Prepare.call(request) - payload = { - event: '$login', - status: '$succeeded', - user: { id: '123' }, - properties: { key: 'value' } - } + payload = { event: '$login', status: '$succeeded', user: { id: '123' }, properties: { key: 'value' } } client = ::Castle::Client.new(context: request_context) client.risk(payload) @@ -18,10 +13,11 @@ def index1 # prepare payload via Payload::Prepare and call risk via the client def index2 - payload = ::Castle::Payload::Prepare.call( - { event: '$login', status: '$succeeded', user: { id: '123' }, properties: { key: 'value' } }, - request - ) + payload = + ::Castle::Payload::Prepare.call( + { event: '$login', status: '$succeeded', user: { id: '123' }, properties: { key: 'value' } }, + request + ) client = ::Castle::Client.new client.risk(payload) @@ -30,10 +26,11 @@ def index2 # prepare payload via Payload::Prepare and call Castle::API::Risk directly def index3 - payload = ::Castle::Payload::Prepare.call( - { event: '$login', status: '$succeeded', user: { id: '123' }, properties: { key: 'value' } }, - request - ) + payload = + ::Castle::Payload::Prepare.call( + { event: '$login', status: '$succeeded', user: { id: '123' }, properties: { key: 'value' } }, + request + ) Castle::API::Risk.call(payload) diff --git a/spec/lib/castle/api/filter_spec.rb b/spec/lib/castle/api/filter_spec.rb index 31c2ed33..cc4acc12 100644 --- a/spec/lib/castle/api/filter_spec.rb +++ b/spec/lib/castle/api/filter_spec.rb @@ -2,14 +2,7 @@ RSpec.describe Castle::API::Filter do describe '.call' do - let(:options) do - { - type: '$login', - status: '$attempted', - request_token: 'token', - params: { email: 'foo@bar.com' } - } - end + let(:options) { { type: '$login', status: '$attempted', request_token: 'token', params: { email: 'foo@bar.com' } } } context 'when the request fails and the failover strategy is not :throw' do before do diff --git a/spec/lib/castle/api/log_spec.rb b/spec/lib/castle/api/log_spec.rb index aabee8df..4060debb 100644 --- a/spec/lib/castle/api/log_spec.rb +++ b/spec/lib/castle/api/log_spec.rb @@ -3,12 +3,7 @@ RSpec.describe Castle::API::Log do describe '.call' do let(:options) do - { - type: '$profile_update', - status: '$succeeded', - user: { id: 'u-42' }, - context: { ip: '1.2.3.4' } - } + { type: '$profile_update', status: '$succeeded', user: { id: 'u-42' }, context: { ip: '1.2.3.4' } } end context 'when the request succeeds' do @@ -16,7 +11,9 @@ stub_request(:post, 'https://api.castle.io/v1/log').to_return( status: 201, body: '{}', - headers: { 'Content-Type' => 'application/json' } + headers: { + 'Content-Type' => 'application/json' + } ) end diff --git a/spec/lib/castle/api/risk_spec.rb b/spec/lib/castle/api/risk_spec.rb index 967c9810..1b008025 100644 --- a/spec/lib/castle/api/risk_spec.rb +++ b/spec/lib/castle/api/risk_spec.rb @@ -3,13 +3,7 @@ RSpec.describe Castle::API::Risk do describe '.call' do let(:options) do - { - type: '$login', - status: '$succeeded', - request_token: 'token', - user: { id: 'u-42' }, - context: { ip: '1.2.3.4' } - } + { type: '$login', status: '$succeeded', request_token: 'token', user: { id: 'u-42' }, context: { ip: '1.2.3.4' } } end context 'when the request succeeds' do @@ -17,7 +11,9 @@ stub_request(:post, 'https://api.castle.io/v1/risk').to_return( status: 201, body: { policy: { action: 'allow' } }.to_json, - headers: { 'Content-Type' => 'application/json' } + headers: { + 'Content-Type' => 'application/json' + } ) end diff --git a/spec/lib/castle/client_spec.rb b/spec/lib/castle/client_spec.rb index adc8c994..a1009811 100644 --- a/spec/lib/castle/client_spec.rb +++ b/spec/lib/castle/client_spec.rb @@ -44,7 +44,8 @@ stub_request(:any, /api.castle.io/).with(basic_auth: ['', 'secret']).to_return( status: response_code, body: response_body, - headers: {} + headers: { + } ) end diff --git a/spec/lib/castle/core/process_webhook_spec.rb b/spec/lib/castle/core/process_webhook_spec.rb index f2002fed..a5d25776 100644 --- a/spec/lib/castle/core/process_webhook_spec.rb +++ b/spec/lib/castle/core/process_webhook_spec.rb @@ -17,13 +17,19 @@ device_token: 'token', user_id: '', trigger: '$login.succeeded', - context: {}, - location: {}, - user_agent: {} + context: { + }, + location: { + }, + user_agent: { + } }, - user_traits: {}, - properties: {}, - policy: {} + user_traits: { + }, + properties: { + }, + policy: { + } }.to_json end diff --git a/spec/lib/castle/core/send_request_spec.rb b/spec/lib/castle/core/send_request_spec.rb index 1ff17b05..ed4cb084 100644 --- a/spec/lib/castle/core/send_request_spec.rb +++ b/spec/lib/castle/core/send_request_spec.rb @@ -57,12 +57,8 @@ context 'when post' do let(:time) { Time.now.utc.iso8601(3) } - let(:command) do - Castle::Commands::Risk.build(event: '$login.succeeded', user: { id: '1' }, name: "\xC4") - end - let(:expected_body) do - { event: '$login.succeeded', user: { id: '1' }, name: '�', context: {}, sent_at: time } - end + let(:command) { Castle::Commands::Risk.build(event: '$login.succeeded', user: { id: '1' }, name: "\xC4") } + let(:expected_body) { { event: '$login.succeeded', user: { id: '1' }, name: '�', context: {}, sent_at: time } } before { allow(Castle::Utils::GetTimestamp).to receive(:call).and_return(time) } diff --git a/spec/lib/castle/logger_spec.rb b/spec/lib/castle/logger_spec.rb index 31ab4169..49750880 100644 --- a/spec/lib/castle/logger_spec.rb +++ b/spec/lib/castle/logger_spec.rb @@ -3,7 +3,8 @@ # tmp logger for testing class TmpLogger # @param _message [String] - def info(_message); end + def info(_message) + end end RSpec.describe Castle::Logger do diff --git a/spec/lib/castle/webhooks/verify_spec.rb b/spec/lib/castle/webhooks/verify_spec.rb index 53abf24d..d6a93371 100644 --- a/spec/lib/castle/webhooks/verify_spec.rb +++ b/spec/lib/castle/webhooks/verify_spec.rb @@ -19,13 +19,19 @@ device_token: 'token', user_id: user_id, trigger: '$login.succeeded', - context: {}, - location: {}, - user_agent: {} + context: { + }, + location: { + }, + user_agent: { + } }, - user_traits: {}, - properties: {}, - policy: {} + user_traits: { + }, + properties: { + }, + policy: { + } }.to_json end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a11bea0f..21866b55 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,9 +1,7 @@ # frozen_string_literal: true require 'simplecov' -SimpleCov.start do - add_filter '/spec/' -end +SimpleCov.start { add_filter '/spec/' } require 'rubygems' require 'bundler/setup'