Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,22 @@ jobs:
path: '*.gem'

test:
name: Test (${{ matrix.ruby-version }})
runs-on: ubuntu-24.04
name: Test (${{ matrix.ruby-version }}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
permissions:
contents: read
strategy:
fail-fast: false
matrix:
# following https://docs.stripe.com/sdks/versioning?lang=ruby#stripe-sdk-language-version-support-policy
ruby-version: [2.7, '3.0', 3.1, 3.2, 3.3, 3.4, jruby-9.4.7.0, truffleruby-25.0.0]
os:
- ubuntu-24.04
# https://docs.stripe.com/sdks/versioning?lang=ruby#stripe-sdk-language-version-support-policy
# https://endoflife.date/ruby
ruby-version: ['2.7', '3.0', '3.1', '3.2', '3.3', '3.4', jruby-9.4.7.0, truffleruby-25.0.0]
include:
- os: windows-latest
# use any modern-ish version
ruby-version: '3.4'
steps:
- uses: extractions/setup-just@v2
- uses: actions/checkout@v3
Expand All @@ -62,7 +70,15 @@ jobs:
ruby-version: ${{ matrix.ruby-version }}
- uses: stripe/openapi/actions/stripe-mock@master
- name: test
run: just test typecheck
run: just test
env:
GITHUB_TOKEN: ${{ secrets.github_token }}
# Use IP instead of 'localhost' to avoid slow DNS resolution on Windows
STRIPE_MOCK_HOST: ${{ runner.os == 'Windows' && '127.0.0.1' || 'localhost' }}
- name: typecheck
# sorbet doesn't support windows
if: runner.os != 'Windows'
run: just typecheck
env:
GITHUB_TOKEN: ${{ secrets.github_token }}

Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ This release changes the pinned API version to 2026-06-24.preview.
* Add support for event notification `V2MoneyManagementOutboundTransferUnderReviewEvent` with related object `V2::MoneyManagement::OutboundTransfer`
* ⚠️ Remove support for event notifications `V2CoreAccountIncludingConfigurationStorerCapabilityStatusUpdatedEvent` and `V2CoreAccountIncludingConfigurationStorerUpdatedEvent` with related object `V2::Core::Account`

## 19.3.1 - 2026-07-15
* [#1902](https://github.com/stripe/stripe-ruby/pull/1902) Replace source hash with Telemetry UUID
* [#1901](https://github.com/stripe/stripe-ruby/pull/1901) Make Error fields generated

## 19.3.0 - 2026-06-24
This release changes the pinned API version to 2026-06-24.dahlia.

Expand Down
2 changes: 1 addition & 1 deletion CODEGEN_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6012b623b1c09ad54d466947da04511a042ee45a
eb1b3cc8c677e4b226561dfa74138352a6624190
6 changes: 4 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ group :development do
# The latest version of rubocop is only compatible with Ruby 2.7+
gem "rubocop", "1.75.2" if RUBY_VERSION >= "2.7"

gem "sorbet"
gem "tapioca"
unless RUBY_PLATFORM =~ /mingw|mswin/
gem "sorbet"
gem "tapioca"
end

platforms :mri do
gem "byebug"
Expand Down
2 changes: 1 addition & 1 deletion OPENAPI_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v2324
v2344
2 changes: 2 additions & 0 deletions lib/stripe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
require "net/http"
require "openssl"
require "rbconfig"
require "fileutils"
require "securerandom"
require "set"
require "socket"
Expand Down Expand Up @@ -36,6 +37,7 @@
require "stripe/request_params"
require "stripe/stripe_context"
require "stripe/util"
require "stripe/telemetry_id"
require "stripe/connection_manager"
require "stripe/multipart_encoder"
require "stripe/api_requestor"
Expand Down
29 changes: 2 additions & 27 deletions lib/stripe/api_requestor.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# frozen_string_literal: true

require "digest"
require "socket"
require "stripe/instrumentation"

Expand Down Expand Up @@ -1104,31 +1103,6 @@ def dup_from_response_headers(headers)
# in so that we can generate a rich user agent header to help debug
# integrations.
class SystemProfiler
UNAME_HASH = begin
parts = []
parts << if RUBY_PLATFORM.match?(/mswin|mingw|cygwin/)
begin
`ver 2>NUL`.strip
rescue StandardError
""
end
else
begin
`uname -a 2>/dev/null`.strip
rescue StandardError
""
end
end
parts << begin
Socket.gethostname
rescue StandardError
""
end
Digest::MD5.hexdigest(parts.join(" "))
rescue StandardError
""
end

AI_AGENTS = [
# aiAgents: The beginning of the section generated from our OpenAPI spec
%w[ANTIGRAVITY_CLI_ALIAS antigravity],
Expand Down Expand Up @@ -1166,7 +1140,8 @@ def self.user_agent

if Stripe.enable_telemetry?
ua[:platform] = RUBY_PLATFORM
ua[:source] = UNAME_HASH unless UNAME_HASH.empty?
tid = TelemetryId.get
ua[:telemetry_id] = tid if tid
end

ai_agent = detect_ai_agent
Expand Down
65 changes: 65 additions & 0 deletions lib/stripe/telemetry_id.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

module Stripe
module TelemetryId
@cached_id = nil
@loaded = false

def self.config_dir
if Gem.win_platform?
appdata = ENV.fetch("APPDATA", nil)
return nil unless appdata && !appdata.empty?

::File.join(appdata, "Stripe")
else
xdg = ENV.fetch("XDG_CONFIG_HOME", nil)
if xdg && !xdg.empty?
::File.join(xdg, "stripe")
else
::File.expand_path("~/.config/stripe")
end
end
rescue ArgumentError
nil
end

def self.get
return @cached_id if @loaded

dir = config_dir
return nil unless dir

file_path = ::File.join(dir, "telemetry_id")

begin
content = ::File.read(file_path).strip
unless content.empty?
@cached_id = content
return @cached_id
end
rescue SystemCallError
# File doesn't exist or can't be read
end

new_id = SecureRandom.hex(16)

begin
::FileUtils.mkdir_p(dir)
::File.write(file_path, new_id)
rescue SystemCallError
return nil
end

@cached_id = new_id
@cached_id
ensure
@loaded = true
end

# For testing only
def self.reset!
@cached_id = nil
@loaded = false
end
end
end
32 changes: 16 additions & 16 deletions test/stripe/api_requestor_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -902,8 +902,8 @@ class RequestorTest < Test::Unit::TestCase
client.send(request_method, :post, "/v1/charges", :api,
&@read_body_chunk_block)
end
assert_equal "#{APIRequestor::ERROR_MESSAGE_CONNECTION % Stripe::DEFAULT_API_BASE} Request was retried 2 times.\n\n(Network error: Connection refused)",
e.message
assert_match(/Request was retried 2 times\.\n\n\(Network error: .*refused/i,
e.message)
end

should "handle error response with unknown value" do
Expand Down Expand Up @@ -1800,29 +1800,29 @@ class SystemProfilerTest < Test::Unit::TestCase
Stripe.enable_telemetry = false
end

should "omit source when UNAME_HASH is empty" do
original = APIRequestor::SystemProfiler::UNAME_HASH
APIRequestor::SystemProfiler.send(:remove_const, :UNAME_HASH)
APIRequestor::SystemProfiler.const_set(:UNAME_HASH, "")
should "include telemetry_id when telemetry is enabled" do
Stripe.enable_telemetry = true
TelemetryId.stubs(:get).returns("abc123def456")
ua = APIRequestor::SystemProfiler.user_agent
refute ua.key?(:source)
assert_equal "abc123def456", ua[:telemetry_id]
ensure
APIRequestor::SystemProfiler.send(:remove_const, :UNAME_HASH)
APIRequestor::SystemProfiler.const_set(:UNAME_HASH, original)
Stripe.enable_telemetry = false
end

should "include source when UNAME_HASH is non-empty" do
original = APIRequestor::SystemProfiler::UNAME_HASH
APIRequestor::SystemProfiler.send(:remove_const, :UNAME_HASH)
APIRequestor::SystemProfiler.const_set(:UNAME_HASH, "abc123")
should "omit telemetry_id when telemetry is disabled" do
Stripe.enable_telemetry = false
ua = APIRequestor::SystemProfiler.user_agent
refute ua.key?(:telemetry_id)
ensure
Stripe.enable_telemetry = false
end

should "omit telemetry_id when TelemetryId.get returns nil" do
Stripe.enable_telemetry = true
TelemetryId.stubs(:get).returns(nil)
ua = APIRequestor::SystemProfiler.user_agent
assert_equal "abc123", ua[:source]
refute ua.key?(:telemetry_id)
ensure
APIRequestor::SystemProfiler.send(:remove_const, :UNAME_HASH)
APIRequestor::SystemProfiler.const_set(:UNAME_HASH, original)
Stripe.enable_telemetry = false
end
end
Expand Down
Loading
Loading