⚠️ Drop support for Ruby < 2.6 & clarify version policy (#1684)

* update version requirements

* linting

* Fix linting

* add ci comment

* remove unused block
This commit is contained in:
David Brownman 2025-09-30 10:25:42 -07:00 committed by GitHub
parent 3919242336
commit fd4368dbb8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 118 additions and 136 deletions

View File

@ -46,7 +46,8 @@ jobs:
runs-on: ubuntu-22.04
strategy:
matrix:
ruby-version: [2.3, 2.4, 2.5, 2.6, 2.7, '3.0', 3.1, 3.2, 3.3, 3.4, jruby-9.4.0.0, truffleruby-head]
# following https://docs.stripe.com/sdks/versioning?server=ruby#stripe-sdk-language-version-support-policy
ruby-version: [2.6, 2.7, '3.0', 3.1, 3.2, 3.3, 3.4, jruby-9.4.0.0, truffleruby-head]
steps:
- uses: extractions/setup-just@v2
- uses: actions/checkout@v3

View File

@ -2,7 +2,8 @@ inherit_from: .rubocop_todo.yml
AllCops:
DisplayCopNames: true
TargetRubyVersion: 2.3
TargetRubyVersion: 2.6
SuggestExtensions: false
Layout/CaseIndentation:
EnforcedStyle: end
@ -72,14 +73,6 @@ Metrics/MethodLength:
- initialize
- inner_class_types
# TODO(xavdid): remove this once the first `basil` release is out
Naming/MethodName:
# these endpoints are removed soon so we pulled their overrides, meaning their names are wrong
# that won't make it out to users, but it's breaking linting/formatting in the meantime
Exclude:
- "lib/stripe/services/invoice_service.rb"
- "lib/stripe/resources/invoice.rb"
Metrics/ModuleLength:
Enabled: false
@ -122,6 +115,9 @@ Style/HashTransformKeys:
Style/HashTransformValues:
Enabled: true
Exclude:
# RUN_DEVSDK-1956
- "lib/stripe/api_requestor.rb"
Style/NumericPredicate:
Enabled: false
@ -266,6 +262,9 @@ Style/MapCompactWithConditionalBlock: # new in 1.30
Enabled: true
Style/MapToHash: # new in 1.24
Enabled: true
Exclude:
# RUN_DEVSDK-1956
- "lib/stripe/api_requestor.rb"
Style/MapToSet: # new in 1.42
Enabled: true
Style/MinMaxComparison: # new in 1.42

View File

@ -37,7 +37,9 @@ gem build stripe.gemspec
### Requirements
- Ruby 2.3+.
Per our [Language Version Support Policy](https://docs.stripe.com/sdks/versioning?server=ruby#stripe-sdk-language-version-support-policy), we currently support **Ruby 2.6+**.
Support for Ruby 2.6 and 2.7 is deprecated and will be removed in upcoming major versions. Read more and see the full schedule in the docs: https://docs.stripe.com/sdks/versioning?server=ruby#stripe-sdk-language-version-support-policy
### Bundler
@ -55,8 +57,7 @@ gem 'stripe'
## Usage
The library needs to be configured with your account's secret key which is
available in your [Stripe Dashboard][api-keys]. Set `Stripe.api_key` to its
value:
available in your [Stripe Dashboard][api-keys]. Initialize a new client with your API key:
```ruby
require 'stripe'

View File

@ -572,8 +572,10 @@ module Stripe
headers["Content-Type"] = content_type
# `#to_s` any complex objects like files and the like to build output
# that's more condusive to logging.
# that's more conducive to logging.
flattened_params =
# https://go/j/RUN_DEVSDK-1956 - this is probably a bug
# once fixed, you can remove the exclusions referencing this ticket in .rubocop.yml
flattened_params.map { |k, v| [k, v.is_a?(String) ? v : v.to_s] }.to_h
elsif api_mode == :v2

View File

@ -132,9 +132,7 @@ module Stripe
# Get options that are copyable from StripeObject to StripeObject
def self.copyable(req_opts)
req_opts.select do |k, _v|
RequestOptions::OPTS_COPYABLE.include?(k)
end
req_opts.slice(*RequestOptions::OPTS_COPYABLE)
end
end
end

View File

@ -43,7 +43,7 @@ module Stripe
connect_base: connect_base,
meter_events_base: meter_events_base,
client_id: client_id,
}.reject { |_k, v| v.nil? }
}.compact
config = StripeConfiguration.client_init(config_opts)
@requestor = APIRequestor.new(config)

View File

@ -45,12 +45,7 @@ module Stripe
imported_options = USER_CONFIGURABLE_GLOBAL_OPTIONS - StripeClient::CLIENT_OPTIONS
client_config = StripeConfiguration.setup do |instance|
imported_options.each do |key|
begin
instance.public_send("#{key}=", global_config.public_send(key)) if global_config.respond_to?(key)
rescue NotImplementedError => e
# In Ruby <= 2.5, we can't set write_timeout on Net::HTTP, log an error and continue
Util.log_error("Failed to set #{key} on client configuration: #{e}")
end
instance.public_send("#{key}=", global_config.public_send(key)) if global_config.respond_to?(key)
end
end
client_config.reverse_duplicate_merge(config_opts)

View File

@ -202,13 +202,13 @@ module Stripe
value.respond_to?(:to_hash) ? value.to_hash : value
end
@values.each_with_object({}) do |(key, value), acc|
acc[key] = case value
when Array
value.map(&maybe_to_hash)
else
maybe_to_hash.call(value)
end
@values.transform_values do |value|
case value
when Array
value.map(&maybe_to_hash)
else
maybe_to_hash.call(value)
end
end
end
@ -273,7 +273,7 @@ module Stripe
# a `nil` that makes it out of `#serialize_params_value` signals an empty
# value that we shouldn't appear in the serialized form of the object
update_hash.reject! { |_, v| v.nil? }
update_hash.compact!
update_hash
end

View File

@ -328,7 +328,7 @@ module Stripe
def self.valid_variable_name?(key)
return false if key.empty? || key[0] !~ LEGAL_FIRST_CHARACTER
key[1..-1].chars.all? { |char| char =~ LEGAL_VARIABLE_CHARACTER }
key[1..].chars.all? { |char| char =~ LEGAL_VARIABLE_CHARACTER }
end
def self.check_string_argument!(key)
@ -428,7 +428,7 @@ module Stripe
private_class_method :level_name
def self.log_internal(message, data = {}, color:, level:, logger:, out:)
data_str = data.reject { |_k, v| v.nil? }
data_str = data.compact
.map do |(k, v)|
format("%<key>s=%<value>s",
key: colorize(k, color, logger.nil? && !out.nil? && out.isatty),

View File

@ -7,7 +7,7 @@ require "stripe/version"
Gem::Specification.new do |s|
s.name = "stripe"
s.version = Stripe::VERSION
s.required_ruby_version = ">= 2.3.0"
s.required_ruby_version = ">= 2.6.0"
s.summary = "Ruby bindings for the Stripe API"
s.description = "Stripe is the easiest way to accept payments online. " \
"See https://stripe.com for details."

View File

@ -728,18 +728,16 @@ module Stripe
context "Stripe-Account header" do
should "use a globally set header" do
begin
old = Stripe.stripe_account
Stripe.stripe_account = "acct_1234"
old = Stripe.stripe_account
Stripe.stripe_account = "acct_1234"
stub_request(:post, "#{Stripe::DEFAULT_API_BASE}/v1/account")
.with(headers: { "Stripe-Account" => Stripe.stripe_account })
.to_return(body: JSON.generate(object: "account"))
stub_request(:post, "#{Stripe::DEFAULT_API_BASE}/v1/account")
.with(headers: { "Stripe-Account" => Stripe.stripe_account })
.to_return(body: JSON.generate(object: "account"))
Stripe::Account.create
ensure
Stripe.stripe_account = old
end
Stripe::Account.create
ensure
Stripe.stripe_account = old
end
should "use a local request set header" do
@ -798,41 +796,39 @@ module Stripe
context "app_info" do
should "send app_info if set" do
begin
old = Stripe.app_info
Stripe.set_app_info(
"MyAwesomePlugin",
partner_id: "partner_1234",
url: "https://myawesomeplugin.info",
version: "1.2.34"
)
old = Stripe.app_info
Stripe.set_app_info(
"MyAwesomePlugin",
partner_id: "partner_1234",
url: "https://myawesomeplugin.info",
version: "1.2.34"
)
stub_request(:post, "#{Stripe::DEFAULT_API_BASE}/v1/account")
.with do |req|
assert_equal \
"Stripe/v1 RubyBindings/#{Stripe::VERSION} " \
"MyAwesomePlugin/1.2.34 (https://myawesomeplugin.info)",
req.headers["User-Agent"]
stub_request(:post, "#{Stripe::DEFAULT_API_BASE}/v1/account")
.with do |req|
assert_equal \
"Stripe/v1 RubyBindings/#{Stripe::VERSION} " \
"MyAwesomePlugin/1.2.34 (https://myawesomeplugin.info)",
req.headers["User-Agent"]
data = JSON.parse(req.headers["X-Stripe-Client-User-Agent"],
symbolize_names: true)
data = JSON.parse(req.headers["X-Stripe-Client-User-Agent"],
symbolize_names: true)
assert_equal({
name: "MyAwesomePlugin",
partner_id: "partner_1234",
url: "https://myawesomeplugin.info",
version: "1.2.34",
}, data[:application])
assert_equal({
name: "MyAwesomePlugin",
partner_id: "partner_1234",
url: "https://myawesomeplugin.info",
version: "1.2.34",
}, data[:application])
true
end.to_return(body: JSON.generate(object: "account"))
true
end.to_return(body: JSON.generate(object: "account"))
client = APIRequestor.new("sk_test_123")
client.send(request_method, :post, "/v1/account", :api,
&@read_body_chunk_block)
ensure
Stripe.app_info = old
end
client = APIRequestor.new("sk_test_123")
client.send(request_method, :post, "/v1/account", :api,
&@read_body_chunk_block)
ensure
Stripe.app_info = old
end
end
@ -1361,17 +1357,15 @@ module Stripe
end
should "reset local thread state after a call" do
begin
APIRequestor.current_thread_context.active_requestor = :api_requestor
APIRequestor.current_thread_context.active_requestor = :api_requestor
client = APIRequestor.new("sk_test_123")
client.request { 0 }
client = APIRequestor.new("sk_test_123")
client.request { 0 }
assert_equal :api_requestor,
APIRequestor.current_thread_context.active_requestor
ensure
APIRequestor.current_thread_context.active_requestor = nil
end
assert_equal :api_requestor,
APIRequestor.current_thread_context.active_requestor
ensure
APIRequestor.current_thread_context.active_requestor = nil
end
should "correctly return last responses despite multiple clients" do
@ -1468,25 +1462,23 @@ module Stripe
context "#proxy" do
should "run the request through the proxy" do
begin
APIRequestor.clear_all_connection_managers
APIRequestor.clear_all_connection_managers
Stripe.proxy = "http://user:pass@localhost:8080"
Stripe.proxy = "http://user:pass@localhost:8080"
client = APIRequestor.new("sk_test_123")
client.request { 0 }
client = APIRequestor.new("sk_test_123")
client.request { 0 }
connection = Stripe::APIRequestor.default_connection_manager.connection_for(Stripe::DEFAULT_API_BASE)
connection = Stripe::APIRequestor.default_connection_manager.connection_for(Stripe::DEFAULT_API_BASE)
assert_equal "localhost", connection.proxy_address
assert_equal 8080, connection.proxy_port
assert_equal "user", connection.proxy_user
assert_equal "pass", connection.proxy_pass
ensure
Stripe.proxy = nil
assert_equal "localhost", connection.proxy_address
assert_equal 8080, connection.proxy_port
assert_equal "user", connection.proxy_user
assert_equal "pass", connection.proxy_pass
ensure
Stripe.proxy = nil
APIRequestor.clear_all_connection_managers
end
APIRequestor.clear_all_connection_managers
end
end

View File

@ -126,7 +126,7 @@ module Stripe
@client_opts[:api_key] = "client_test_123"
@client_opts[:stripe_account] = "client_acct_123"
@client_opts[:uploads_base] = "client_uploads_base.stripe.com"
@client_opts.reject! { |_k, v| v.nil? }
@client_opts.compact!
client_config = Stripe::StripeConfiguration.client_init(@client_opts)

View File

@ -159,21 +159,19 @@ module Stripe
context "#to_hash" do
should "skip calling to_hash on nil" do
begin
module NilWithToHash
def to_hash
raise "Can't call to_hash on nil"
end
module NilWithToHash
def to_hash
raise "Can't call to_hash on nil"
end
::NilClass.include NilWithToHash
hash_with_nil = { id: 3, foo: nil }
obj = StripeObject.construct_from(hash_with_nil)
expected_hash = { id: 3, foo: nil }
assert_equal expected_hash, obj.to_hash
ensure
::NilClass.send(:undef_method, :to_hash)
end
::NilClass.include NilWithToHash
hash_with_nil = { id: 3, foo: nil }
obj = StripeObject.construct_from(hash_with_nil)
expected_hash = { id: 3, foo: nil }
assert_equal expected_hash, obj.to_hash
ensure
::NilClass.send(:undef_method, :to_hash)
end
should "recursively call to_hash on its values" do

View File

@ -4,23 +4,21 @@ require File.expand_path("test_helper", __dir__)
class StripeTest < Test::Unit::TestCase
should "allow app_info to be configured" do
begin
old = Stripe.app_info
Stripe.set_app_info(
"MyAwesomePlugin",
partner_id: "partner_1234",
url: "https://myawesomeplugin.info",
version: "1.2.34"
)
assert_equal({
name: "MyAwesomePlugin",
partner_id: "partner_1234",
url: "https://myawesomeplugin.info",
version: "1.2.34",
}, Stripe.app_info)
ensure
Stripe.app_info = old
end
old = Stripe.app_info
Stripe.set_app_info(
"MyAwesomePlugin",
partner_id: "partner_1234",
url: "https://myawesomeplugin.info",
version: "1.2.34"
)
assert_equal({
name: "MyAwesomePlugin",
partner_id: "partner_1234",
url: "https://myawesomeplugin.info",
version: "1.2.34",
}, Stripe.app_info)
ensure
Stripe.app_info = old
end
context "forwardable configurations" do
@ -78,14 +76,12 @@ class StripeTest < Test::Unit::TestCase
end
should "allow enable_telemetry to be configured" do
begin
old = Stripe.enable_telemetry?
old = Stripe.enable_telemetry?
Stripe.enable_telemetry = false
assert_equal false, Stripe.enable_telemetry?
ensure
Stripe.enable_telemetry = old
end
Stripe.enable_telemetry = false
assert_equal false, Stripe.enable_telemetry?
ensure
Stripe.enable_telemetry = old
end
should "allow log_level to be configured" do