openfeature-sdk 0.6.4 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.release-please-manifest.json +1 -1
- data/.ruby-version +1 -1
- data/.tool-versions +1 -1
- data/.yardopts +5 -0
- data/CHANGELOG.md +20 -0
- data/CLAUDE.md +4 -1
- data/CONTRIBUTING.md +15 -1
- data/Gemfile +17 -2
- data/Gemfile.lock +98 -67
- data/README.md +24 -8
- data/Rakefile +14 -0
- data/SECURITY.md +10 -0
- data/Steepfile +7 -0
- data/examples/basic_usage.rb +22 -0
- data/examples/custom_provider.rb +56 -0
- data/examples/rails_integration.rb +60 -0
- data/lib/open_feature/sdk/api.rb +1 -0
- data/lib/open_feature/sdk/client.rb +2 -3
- data/lib/open_feature/sdk/configuration.rb +26 -13
- data/lib/open_feature/sdk/evaluation_error.rb +28 -0
- data/lib/open_feature/sdk/hooks/hook_executor.rb +5 -5
- data/lib/open_feature/sdk/hooks/logging_hook.rb +1 -2
- data/lib/open_feature/sdk/provider/in_memory_provider.rb +24 -0
- data/lib/open_feature/sdk/provider_event.rb +5 -1
- data/lib/open_feature/sdk/provider_state_registry.rb +2 -2
- data/lib/open_feature/sdk/version.rb +1 -1
- data/openfeature-sdk.gemspec +34 -0
- data/rbs_collection.lock.yaml +292 -0
- data/rbs_collection.yaml +14 -0
- data/renovate.json +1 -1
- data/sig/open_feature/sdk/api.rbs +35 -0
- data/sig/open_feature/sdk/client.rbs +49 -0
- data/sig/open_feature/sdk/client_metadata.rbs +11 -0
- data/sig/open_feature/sdk/configuration.rbs +44 -0
- data/sig/open_feature/sdk/evaluation_context.rbs +19 -0
- data/sig/open_feature/sdk/evaluation_context_builder.rbs +7 -0
- data/sig/open_feature/sdk/evaluation_details.rbs +19 -0
- data/sig/open_feature/sdk/evaluation_error.rbs +11 -0
- data/sig/open_feature/sdk/event_dispatcher.rbs +24 -0
- data/sig/open_feature/sdk/hooks/hints.rbs +30 -0
- data/sig/open_feature/sdk/hooks/hook.rbs +19 -0
- data/sig/open_feature/sdk/hooks/hook_context.rbs +18 -0
- data/sig/open_feature/sdk/hooks/hook_executor.rbs +20 -0
- data/sig/open_feature/sdk/hooks/logging_hook.rbs +25 -0
- data/sig/open_feature/sdk/provider/error_code.rbs +16 -0
- data/sig/open_feature/sdk/provider/event_emitter.rbs +16 -0
- data/sig/open_feature/sdk/provider/in_memory_provider.rbs +46 -0
- data/sig/open_feature/sdk/provider/no_op_provider.rbs +25 -0
- data/sig/open_feature/sdk/provider/provider_metadata.rbs +11 -0
- data/sig/open_feature/sdk/provider/reason.rbs +17 -0
- data/sig/open_feature/sdk/provider/resolution_details.rbs +19 -0
- data/sig/open_feature/sdk/provider.rbs +24 -0
- data/sig/open_feature/sdk/provider_event.rbs +14 -0
- data/sig/open_feature/sdk/provider_initialization_error.rbs +11 -0
- data/sig/open_feature/sdk/provider_state.rbs +13 -0
- data/sig/open_feature/sdk/provider_state_registry.rbs +22 -0
- data/sig/open_feature/sdk/telemetry.rbs +29 -0
- data/sig/open_feature/sdk/thread_local_transaction_context_propagator.rbs +12 -0
- data/sig/open_feature/sdk/tracking_event_details.rbs +10 -0
- data/sig/open_feature/sdk/transaction_context_propagator.rbs +11 -0
- data/sig/open_feature/sdk/version.rbs +5 -0
- data/sig/open_feature/sdk.rbs +22 -0
- metadata +54 -140
- data/.simplecov +0 -12
- data/docs/plans/2026-03-07-telemetry-utility-design.md +0 -98
- data/docs/plans/2026-03-07-telemetry-utility-plan.md +0 -578
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Example: OpenFeature integration with Ruby on Rails
|
|
4
|
+
#
|
|
5
|
+
# This file demonstrates how you might integrate OpenFeature into a Rails app.
|
|
6
|
+
# It is not runnable standalone — it shows patterns for use in a Rails context.
|
|
7
|
+
|
|
8
|
+
# config/initializers/openfeature.rb
|
|
9
|
+
#
|
|
10
|
+
# OpenFeature::SDK.configure do |config|
|
|
11
|
+
# config.set_provider(YourProvider.new)
|
|
12
|
+
#
|
|
13
|
+
# # Set global context with server-level info
|
|
14
|
+
# config.evaluation_context = OpenFeature::SDK::EvaluationContext.new(
|
|
15
|
+
# "environment" => Rails.env,
|
|
16
|
+
# "service" => "my-rails-app"
|
|
17
|
+
# )
|
|
18
|
+
#
|
|
19
|
+
# # Use thread-local transaction context for per-request data
|
|
20
|
+
# config.set_transaction_context_propagator(
|
|
21
|
+
# OpenFeature::SDK::ThreadLocalTransactionContextPropagator.new
|
|
22
|
+
# )
|
|
23
|
+
# end
|
|
24
|
+
|
|
25
|
+
# app/middleware/openfeature_context_middleware.rb
|
|
26
|
+
#
|
|
27
|
+
# class OpenFeatureContextMiddleware
|
|
28
|
+
# def initialize(app)
|
|
29
|
+
# @app = app
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# def call(env)
|
|
33
|
+
# request = ActionDispatch::Request.new(env)
|
|
34
|
+
# OpenFeature::SDK.set_transaction_context(
|
|
35
|
+
# OpenFeature::SDK::EvaluationContext.new(
|
|
36
|
+
# targeting_key: request.session[:user_id]&.to_s,
|
|
37
|
+
# "ip" => request.remote_ip,
|
|
38
|
+
# "user_agent" => request.user_agent
|
|
39
|
+
# )
|
|
40
|
+
# )
|
|
41
|
+
# @app.call(env)
|
|
42
|
+
# ensure
|
|
43
|
+
# # Clear context to prevent leakage in threaded servers (e.g. Puma)
|
|
44
|
+
# OpenFeature::SDK.set_transaction_context(nil)
|
|
45
|
+
# end
|
|
46
|
+
# end
|
|
47
|
+
|
|
48
|
+
# app/controllers/application_controller.rb
|
|
49
|
+
#
|
|
50
|
+
# class ApplicationController < ActionController::Base
|
|
51
|
+
# private
|
|
52
|
+
#
|
|
53
|
+
# def feature_client
|
|
54
|
+
# @feature_client ||= OpenFeature::SDK.build_client(domain: "web")
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
57
|
+
# def feature_enabled?(flag_key)
|
|
58
|
+
# feature_client.fetch_boolean_value(flag_key: flag_key, default_value: false)
|
|
59
|
+
# end
|
|
60
|
+
# end
|
data/lib/open_feature/sdk/api.rb
CHANGED
|
@@ -7,6 +7,7 @@ require_relative "configuration"
|
|
|
7
7
|
require_relative "evaluation_context"
|
|
8
8
|
require_relative "evaluation_context_builder"
|
|
9
9
|
require_relative "evaluation_details"
|
|
10
|
+
require_relative "evaluation_error"
|
|
10
11
|
require_relative "client_metadata"
|
|
11
12
|
require_relative "hooks"
|
|
12
13
|
require_relative "client"
|
|
@@ -80,7 +80,7 @@ module OpenFeature
|
|
|
80
80
|
provider_hooks = @provider.respond_to?(:hooks) ? Array(@provider.hooks) : []
|
|
81
81
|
ordered_hooks = [*OpenFeature::SDK.hooks, *@hooks, *invocation_hooks, *provider_hooks]
|
|
82
82
|
|
|
83
|
-
#
|
|
83
|
+
# Short-circuit NOT_READY/FATAL providers (required by evaluation_v2.feature)
|
|
84
84
|
short_circuit_code = nil
|
|
85
85
|
if OpenFeature::SDK.configuration.provider_tracked?(@provider)
|
|
86
86
|
short_circuit_code = short_circuit_error_code(provider_status)
|
|
@@ -102,7 +102,7 @@ module OpenFeature
|
|
|
102
102
|
rescue => e
|
|
103
103
|
resolution = Provider::ResolutionDetails.new(
|
|
104
104
|
value: default_value,
|
|
105
|
-
error_code:
|
|
105
|
+
error_code: EvaluationError.code_for(e),
|
|
106
106
|
reason: Provider::Reason::ERROR,
|
|
107
107
|
error_message: e.message
|
|
108
108
|
)
|
|
@@ -130,7 +130,6 @@ module OpenFeature
|
|
|
130
130
|
executor = Hooks::HookExecutor.new(logger: OpenFeature::SDK.configuration.logger)
|
|
131
131
|
|
|
132
132
|
if short_circuit_code
|
|
133
|
-
# Spec 1.7.6 + 1.7.7: short-circuit must still run error hooks and finally hooks
|
|
134
133
|
resolution = Provider::ResolutionDetails.new(
|
|
135
134
|
value: default_value,
|
|
136
135
|
error_code: short_circuit_code,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "timeout"
|
|
4
3
|
require_relative "api"
|
|
5
4
|
require_relative "provider_initialization_error"
|
|
5
|
+
require_relative "evaluation_error"
|
|
6
6
|
require_relative "event_dispatcher"
|
|
7
7
|
require_relative "provider_event"
|
|
8
8
|
require_relative "provider_state_registry"
|
|
@@ -89,11 +89,17 @@ module OpenFeature
|
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
def shutdown
|
|
92
|
-
|
|
92
|
+
# Unbind before shutting down so events that arrive mid-shutdown are dropped
|
|
93
|
+
providers_to_shutdown = @provider_mutex.synchronize do
|
|
94
|
+
bound = @providers.values.uniq(&:object_id)
|
|
95
|
+
@providers = {}
|
|
96
|
+
bound
|
|
97
|
+
end
|
|
93
98
|
|
|
94
99
|
providers_to_shutdown.each do |prov|
|
|
95
|
-
# Spec 1.7.
|
|
100
|
+
# Spec 1.7.6: Set provider state to NOT_READY before shutdown
|
|
96
101
|
@provider_state_registry.set_initial_state(prov, ProviderState::NOT_READY)
|
|
102
|
+
prov.send(:detach) if prov.is_a?(Provider::EventEmitter)
|
|
97
103
|
prov.shutdown if prov.respond_to?(:shutdown)
|
|
98
104
|
rescue => e
|
|
99
105
|
@logger&.warn("Error shutting down provider #{prov&.class&.name || "unknown"}: #{e.message}")
|
|
@@ -145,9 +151,11 @@ module OpenFeature
|
|
|
145
151
|
|
|
146
152
|
# Spec 1.1.2.3: Only shutdown old provider if it's no longer bound to any domain
|
|
147
153
|
if old_provider && !old_provider.equal?(provider)
|
|
148
|
-
|
|
149
|
-
needs_shutdown
|
|
150
|
-
|
|
154
|
+
needs_shutdown = !provider_bound?(old_provider)
|
|
155
|
+
if needs_shutdown
|
|
156
|
+
@provider_state_registry.remove_provider(old_provider)
|
|
157
|
+
old_provider.send(:detach) if old_provider.is_a?(Provider::EventEmitter)
|
|
158
|
+
end
|
|
151
159
|
end
|
|
152
160
|
end
|
|
153
161
|
|
|
@@ -187,12 +195,8 @@ module OpenFeature
|
|
|
187
195
|
|
|
188
196
|
dispatch_provider_event(provider, ProviderEvent::PROVIDER_READY)
|
|
189
197
|
rescue => e
|
|
190
|
-
# Spec 1.7.
|
|
191
|
-
error_code =
|
|
192
|
-
e.error_code
|
|
193
|
-
else
|
|
194
|
-
Provider::ErrorCode::GENERAL
|
|
195
|
-
end
|
|
198
|
+
# Spec 1.7.5: PROVIDER_FATAL from init makes the provider FATAL
|
|
199
|
+
error_code = EvaluationError.code_for(e)
|
|
196
200
|
|
|
197
201
|
dispatch_provider_event(provider, ProviderEvent::PROVIDER_ERROR,
|
|
198
202
|
error_code: error_code,
|
|
@@ -209,7 +213,12 @@ module OpenFeature
|
|
|
209
213
|
end
|
|
210
214
|
|
|
211
215
|
def dispatch_provider_event(provider, event_type, details = {})
|
|
212
|
-
|
|
216
|
+
# Under the replacement lock, so a late event can't re-track a replaced or shut-down provider
|
|
217
|
+
@provider_mutex.synchronize do
|
|
218
|
+
return unless provider_bound?(provider)
|
|
219
|
+
|
|
220
|
+
@provider_state_registry.update_state_from_event(provider, event_type, details)
|
|
221
|
+
end
|
|
213
222
|
|
|
214
223
|
provider_name = extract_provider_name(provider)
|
|
215
224
|
|
|
@@ -222,6 +231,10 @@ module OpenFeature
|
|
|
222
231
|
|
|
223
232
|
private
|
|
224
233
|
|
|
234
|
+
def provider_bound?(provider)
|
|
235
|
+
@providers.each_value.any? { |p| p.equal?(provider) }
|
|
236
|
+
end
|
|
237
|
+
|
|
225
238
|
def extract_provider_name(provider)
|
|
226
239
|
provider.respond_to?(:metadata) ? provider.metadata.name : provider.class.name
|
|
227
240
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "provider/error_code"
|
|
4
|
+
|
|
5
|
+
module OpenFeature
|
|
6
|
+
module SDK
|
|
7
|
+
# Raised by a provider to signal an evaluation error with an OpenFeature
|
|
8
|
+
# error code (spec 2.2.7). Any exception responding to +error_code+ is
|
|
9
|
+
# honored the same way.
|
|
10
|
+
class EvaluationError < StandardError
|
|
11
|
+
# @return [String] the OpenFeature error code
|
|
12
|
+
attr_reader :error_code
|
|
13
|
+
|
|
14
|
+
def initialize(message = nil, error_code: Provider::ErrorCode::GENERAL)
|
|
15
|
+
super(message || error_code)
|
|
16
|
+
@error_code = error_code
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# The error code carried by +exception+, or GENERAL when it has none.
|
|
20
|
+
# Rescues a failing reader so callers inside a rescue block never raise (spec 1.4.10).
|
|
21
|
+
def self.code_for(exception)
|
|
22
|
+
(exception.respond_to?(:error_code) && exception.error_code) || Provider::ErrorCode::GENERAL
|
|
23
|
+
rescue
|
|
24
|
+
Provider::ErrorCode::GENERAL
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -18,15 +18,15 @@ module OpenFeature
|
|
|
18
18
|
@logger = logger
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
# Runs error hooks and finally hooks for a short-circuit evaluation
|
|
22
|
-
#
|
|
21
|
+
# Runs error hooks and finally hooks for a short-circuit evaluation.
|
|
22
|
+
# Before hooks and after hooks are NOT run.
|
|
23
23
|
#
|
|
24
24
|
# @param ordered_hooks [Array] hooks in before-order
|
|
25
25
|
# @param hook_context [HookContext] the hook context
|
|
26
26
|
# @param hints [Hints] hook hints
|
|
27
27
|
# @param evaluation_details [EvaluationDetails] the short-circuit result
|
|
28
28
|
def run_short_circuit(ordered_hooks:, hook_context:, hints:, evaluation_details:)
|
|
29
|
-
error =
|
|
29
|
+
error = EvaluationError.new(evaluation_details.error_message, error_code: evaluation_details.error_code)
|
|
30
30
|
run_error_hooks(ordered_hooks, hook_context, error, hints)
|
|
31
31
|
ensure
|
|
32
32
|
run_finally_hooks(ordered_hooks, hook_context, evaluation_details, hints)
|
|
@@ -49,7 +49,7 @@ module OpenFeature
|
|
|
49
49
|
# Spec 4.3.6: If evaluation resulted in an error (e.g. FLAG_NOT_FOUND,
|
|
50
50
|
# TYPE_MISMATCH), run error hooks instead of after hooks.
|
|
51
51
|
if evaluation_details.error_code
|
|
52
|
-
error =
|
|
52
|
+
error = EvaluationError.new(evaluation_details.error_message, error_code: evaluation_details.error_code)
|
|
53
53
|
run_error_hooks(ordered_hooks, hook_context, error, hints)
|
|
54
54
|
else
|
|
55
55
|
run_after_hooks(ordered_hooks, hook_context, evaluation_details, hints)
|
|
@@ -61,7 +61,7 @@ module OpenFeature
|
|
|
61
61
|
flag_key: hook_context.flag_key,
|
|
62
62
|
resolution_details: Provider::ResolutionDetails.new(
|
|
63
63
|
value: hook_context.default_value,
|
|
64
|
-
error_code:
|
|
64
|
+
error_code: EvaluationError.code_for(e),
|
|
65
65
|
reason: Provider::Reason::ERROR,
|
|
66
66
|
error_message: e.message
|
|
67
67
|
)
|
|
@@ -49,8 +49,7 @@ module OpenFeature
|
|
|
49
49
|
|
|
50
50
|
def build_error_message(hook_context, exception)
|
|
51
51
|
parts = base_parts("error", hook_context)
|
|
52
|
-
|
|
53
|
-
parts << "error_code=#{sanitize(error_code)}"
|
|
52
|
+
parts << "error_code=#{sanitize(EvaluationError.code_for(exception))}"
|
|
54
53
|
parts << "error_message=#{sanitize(exception.message)}"
|
|
55
54
|
parts << "evaluation_context=#{format_context(hook_context.evaluation_context)}" if @include_evaluation_context
|
|
56
55
|
parts.join(" ")
|
|
@@ -8,6 +8,10 @@ module OpenFeature
|
|
|
8
8
|
|
|
9
9
|
NAME = "In-memory Provider"
|
|
10
10
|
|
|
11
|
+
# A flag with named variants. +context_evaluator+ receives the evaluation
|
|
12
|
+
# context and returns a variant key; anything else falls back to +default_variant+.
|
|
13
|
+
Flag = Struct.new(:variants, :default_variant, :context_evaluator, :flag_metadata, :disabled, keyword_init: true)
|
|
14
|
+
|
|
11
15
|
attr_reader :metadata
|
|
12
16
|
|
|
13
17
|
def initialize(flags = {})
|
|
@@ -70,6 +74,8 @@ module OpenFeature
|
|
|
70
74
|
return ResolutionDetails.new(value: default_value, error_code: ErrorCode::FLAG_NOT_FOUND, reason: Reason::ERROR)
|
|
71
75
|
end
|
|
72
76
|
|
|
77
|
+
return resolve_variant_flag(raw_value, default_value, evaluation_context) if raw_value.is_a?(Flag)
|
|
78
|
+
|
|
73
79
|
if raw_value.respond_to?(:call)
|
|
74
80
|
value = raw_value.call(evaluation_context)
|
|
75
81
|
ResolutionDetails.new(value: value, reason: Reason::TARGETING_MATCH)
|
|
@@ -78,6 +84,24 @@ module OpenFeature
|
|
|
78
84
|
end
|
|
79
85
|
end
|
|
80
86
|
|
|
87
|
+
def resolve_variant_flag(flag, default_value, evaluation_context)
|
|
88
|
+
flag_metadata = flag.flag_metadata
|
|
89
|
+
return ResolutionDetails.new(value: default_value, reason: Reason::DISABLED, flag_metadata:) if flag.disabled
|
|
90
|
+
|
|
91
|
+
variants = flag.variants.to_h
|
|
92
|
+
unless variants.key?(flag.default_variant)
|
|
93
|
+
return ResolutionDetails.new(value: default_value, error_code: ErrorCode::PARSE_ERROR, reason: Reason::ERROR, flag_metadata:)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
matched = flag.context_evaluator&.call(evaluation_context)
|
|
97
|
+
if variants.key?(matched)
|
|
98
|
+
return ResolutionDetails.new(value: variants[matched], variant: matched, reason: Reason::TARGETING_MATCH, flag_metadata:)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
reason = flag.context_evaluator ? Reason::DEFAULT : Reason::STATIC
|
|
102
|
+
ResolutionDetails.new(value: variants[flag.default_variant], variant: flag.default_variant, reason:, flag_metadata:)
|
|
103
|
+
end
|
|
104
|
+
|
|
81
105
|
def emit_provider_changed(flag_keys)
|
|
82
106
|
return unless configuration_attached?
|
|
83
107
|
|
|
@@ -13,12 +13,16 @@ module OpenFeature
|
|
|
13
13
|
PROVIDER_ERROR = "PROVIDER_ERROR"
|
|
14
14
|
PROVIDER_CONFIGURATION_CHANGED = "PROVIDER_CONFIGURATION_CHANGED"
|
|
15
15
|
PROVIDER_STALE = "PROVIDER_STALE"
|
|
16
|
+
PROVIDER_RECONCILING = "PROVIDER_RECONCILING"
|
|
17
|
+
PROVIDER_CONTEXT_CHANGED = "PROVIDER_CONTEXT_CHANGED"
|
|
16
18
|
|
|
17
19
|
ALL_EVENTS = [
|
|
18
20
|
PROVIDER_READY,
|
|
19
21
|
PROVIDER_ERROR,
|
|
20
22
|
PROVIDER_CONFIGURATION_CHANGED,
|
|
21
|
-
PROVIDER_STALE
|
|
23
|
+
PROVIDER_STALE,
|
|
24
|
+
PROVIDER_RECONCILING,
|
|
25
|
+
PROVIDER_CONTEXT_CHANGED
|
|
22
26
|
].freeze
|
|
23
27
|
end
|
|
24
28
|
end
|
|
@@ -91,7 +91,7 @@ module OpenFeature
|
|
|
91
91
|
|
|
92
92
|
def state_from_event(event_type, event_details = nil)
|
|
93
93
|
case event_type
|
|
94
|
-
when ProviderEvent::PROVIDER_READY
|
|
94
|
+
when ProviderEvent::PROVIDER_READY, ProviderEvent::PROVIDER_CONTEXT_CHANGED
|
|
95
95
|
ProviderState::READY
|
|
96
96
|
when ProviderEvent::PROVIDER_STALE
|
|
97
97
|
ProviderState::STALE
|
|
@@ -100,7 +100,7 @@ module OpenFeature
|
|
|
100
100
|
when ProviderEvent::PROVIDER_CONFIGURATION_CHANGED
|
|
101
101
|
nil # No state change per OpenFeature spec Requirement 5.3.5
|
|
102
102
|
else
|
|
103
|
-
nil #
|
|
103
|
+
nil # PROVIDER_RECONCILING (RECONCILING status is static-context only, spec 1.7.2.1) and unknown events
|
|
104
104
|
end
|
|
105
105
|
end
|
|
106
106
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/open_feature/sdk/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "openfeature-sdk"
|
|
7
|
+
spec.version = OpenFeature::SDK::VERSION
|
|
8
|
+
spec.authors = ["OpenFeature Authors"]
|
|
9
|
+
spec.email = ["cncf-openfeature-contributors@lists.cncf.io"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "OpenFeature SDK for Ruby"
|
|
12
|
+
spec.description = "Ruby SDK for the OpenFeature specification, an open standard for feature flag management"
|
|
13
|
+
spec.homepage = "https://github.com/open-feature/ruby-sdk"
|
|
14
|
+
spec.license = "Apache-2.0"
|
|
15
|
+
spec.required_ruby_version = ">= 3.4"
|
|
16
|
+
|
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
18
|
+
spec.metadata["source_code_uri"] = "https://github.com/open-feature/ruby-sdk"
|
|
19
|
+
spec.metadata["changelog_uri"] = "https://github.com/open-feature/ruby-sdk/blob/main/CHANGELOG.md"
|
|
20
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/open-feature/ruby-sdk/issues"
|
|
21
|
+
spec.metadata["documentation_uri"] = "https://github.com/open-feature/ruby-sdk#readme"
|
|
22
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
|
23
|
+
|
|
24
|
+
# Specify which files should be added to the gem when it is released.
|
|
25
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
26
|
+
spec.files = Dir.chdir(__dir__) do
|
|
27
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
28
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
spec.bindir = "exe"
|
|
32
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
33
|
+
spec.require_paths = ["lib"]
|
|
34
|
+
end
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
---
|
|
2
|
+
path: ".gem_rbs_collection"
|
|
3
|
+
gems:
|
|
4
|
+
- name: activesupport
|
|
5
|
+
version: '7.0'
|
|
6
|
+
source:
|
|
7
|
+
type: git
|
|
8
|
+
name: ruby/gem_rbs_collection
|
|
9
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
10
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
11
|
+
repo_dir: gems
|
|
12
|
+
- name: ast
|
|
13
|
+
version: '2.4'
|
|
14
|
+
source:
|
|
15
|
+
type: git
|
|
16
|
+
name: ruby/gem_rbs_collection
|
|
17
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
18
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
19
|
+
repo_dir: gems
|
|
20
|
+
- name: base64
|
|
21
|
+
version: 0.3.0
|
|
22
|
+
source:
|
|
23
|
+
type: rubygems
|
|
24
|
+
- name: bigdecimal
|
|
25
|
+
version: '4.0'
|
|
26
|
+
source:
|
|
27
|
+
type: git
|
|
28
|
+
name: ruby/gem_rbs_collection
|
|
29
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
30
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
31
|
+
repo_dir: gems
|
|
32
|
+
- name: concurrent-ruby
|
|
33
|
+
version: '1.1'
|
|
34
|
+
source:
|
|
35
|
+
type: git
|
|
36
|
+
name: ruby/gem_rbs_collection
|
|
37
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
38
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
39
|
+
repo_dir: gems
|
|
40
|
+
- name: connection_pool
|
|
41
|
+
version: '2.4'
|
|
42
|
+
source:
|
|
43
|
+
type: git
|
|
44
|
+
name: ruby/gem_rbs_collection
|
|
45
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
46
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
47
|
+
repo_dir: gems
|
|
48
|
+
- name: csv
|
|
49
|
+
version: '3.3'
|
|
50
|
+
source:
|
|
51
|
+
type: git
|
|
52
|
+
name: ruby/gem_rbs_collection
|
|
53
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
54
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
55
|
+
repo_dir: gems
|
|
56
|
+
- name: date
|
|
57
|
+
version: '0'
|
|
58
|
+
source:
|
|
59
|
+
type: stdlib
|
|
60
|
+
- name: dbm
|
|
61
|
+
version: '0'
|
|
62
|
+
source:
|
|
63
|
+
type: stdlib
|
|
64
|
+
- name: delegate
|
|
65
|
+
version: '0'
|
|
66
|
+
source:
|
|
67
|
+
type: stdlib
|
|
68
|
+
- name: diff-lcs
|
|
69
|
+
version: '1.5'
|
|
70
|
+
source:
|
|
71
|
+
type: git
|
|
72
|
+
name: ruby/gem_rbs_collection
|
|
73
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
74
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
75
|
+
repo_dir: gems
|
|
76
|
+
- name: digest
|
|
77
|
+
version: '0'
|
|
78
|
+
source:
|
|
79
|
+
type: stdlib
|
|
80
|
+
- name: erb
|
|
81
|
+
version: '0'
|
|
82
|
+
source:
|
|
83
|
+
type: stdlib
|
|
84
|
+
- name: ffi
|
|
85
|
+
version: 1.17.3
|
|
86
|
+
source:
|
|
87
|
+
type: rubygems
|
|
88
|
+
- name: fileutils
|
|
89
|
+
version: '0'
|
|
90
|
+
source:
|
|
91
|
+
type: stdlib
|
|
92
|
+
- name: forwardable
|
|
93
|
+
version: '0'
|
|
94
|
+
source:
|
|
95
|
+
type: stdlib
|
|
96
|
+
- name: i18n
|
|
97
|
+
version: '1.10'
|
|
98
|
+
source:
|
|
99
|
+
type: git
|
|
100
|
+
name: ruby/gem_rbs_collection
|
|
101
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
102
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
103
|
+
repo_dir: gems
|
|
104
|
+
- name: io-console
|
|
105
|
+
version: '0'
|
|
106
|
+
source:
|
|
107
|
+
type: stdlib
|
|
108
|
+
- name: json
|
|
109
|
+
version: '0'
|
|
110
|
+
source:
|
|
111
|
+
type: stdlib
|
|
112
|
+
- name: listen
|
|
113
|
+
version: '3.9'
|
|
114
|
+
source:
|
|
115
|
+
type: git
|
|
116
|
+
name: ruby/gem_rbs_collection
|
|
117
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
118
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
119
|
+
repo_dir: gems
|
|
120
|
+
- name: logger
|
|
121
|
+
version: '0'
|
|
122
|
+
source:
|
|
123
|
+
type: stdlib
|
|
124
|
+
- name: mini_mime
|
|
125
|
+
version: '0.1'
|
|
126
|
+
source:
|
|
127
|
+
type: git
|
|
128
|
+
name: ruby/gem_rbs_collection
|
|
129
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
130
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
131
|
+
repo_dir: gems
|
|
132
|
+
- name: minitest
|
|
133
|
+
version: '5.25'
|
|
134
|
+
source:
|
|
135
|
+
type: git
|
|
136
|
+
name: ruby/gem_rbs_collection
|
|
137
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
138
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
139
|
+
repo_dir: gems
|
|
140
|
+
- name: monitor
|
|
141
|
+
version: '0'
|
|
142
|
+
source:
|
|
143
|
+
type: stdlib
|
|
144
|
+
- name: mutex_m
|
|
145
|
+
version: 0.3.0
|
|
146
|
+
source:
|
|
147
|
+
type: rubygems
|
|
148
|
+
- name: openssl
|
|
149
|
+
version: '0'
|
|
150
|
+
source:
|
|
151
|
+
type: stdlib
|
|
152
|
+
- name: optparse
|
|
153
|
+
version: '0'
|
|
154
|
+
source:
|
|
155
|
+
type: stdlib
|
|
156
|
+
- name: parallel
|
|
157
|
+
version: '1.20'
|
|
158
|
+
source:
|
|
159
|
+
type: git
|
|
160
|
+
name: ruby/gem_rbs_collection
|
|
161
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
162
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
163
|
+
repo_dir: gems
|
|
164
|
+
- name: parser
|
|
165
|
+
version: '3.2'
|
|
166
|
+
source:
|
|
167
|
+
type: git
|
|
168
|
+
name: ruby/gem_rbs_collection
|
|
169
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
170
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
171
|
+
repo_dir: gems
|
|
172
|
+
- name: pp
|
|
173
|
+
version: '0'
|
|
174
|
+
source:
|
|
175
|
+
type: stdlib
|
|
176
|
+
- name: prettyprint
|
|
177
|
+
version: '0'
|
|
178
|
+
source:
|
|
179
|
+
type: stdlib
|
|
180
|
+
- name: prism
|
|
181
|
+
version: 1.9.0
|
|
182
|
+
source:
|
|
183
|
+
type: rubygems
|
|
184
|
+
- name: pstore
|
|
185
|
+
version: '0'
|
|
186
|
+
source:
|
|
187
|
+
type: stdlib
|
|
188
|
+
- name: psych
|
|
189
|
+
version: '0'
|
|
190
|
+
source:
|
|
191
|
+
type: stdlib
|
|
192
|
+
- name: rainbow
|
|
193
|
+
version: '3.0'
|
|
194
|
+
source:
|
|
195
|
+
type: git
|
|
196
|
+
name: ruby/gem_rbs_collection
|
|
197
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
198
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
199
|
+
repo_dir: gems
|
|
200
|
+
- name: rake
|
|
201
|
+
version: '13.0'
|
|
202
|
+
source:
|
|
203
|
+
type: git
|
|
204
|
+
name: ruby/gem_rbs_collection
|
|
205
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
206
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
207
|
+
repo_dir: gems
|
|
208
|
+
- name: rbs
|
|
209
|
+
version: 3.10.3
|
|
210
|
+
source:
|
|
211
|
+
type: rubygems
|
|
212
|
+
- name: rdoc
|
|
213
|
+
version: '0'
|
|
214
|
+
source:
|
|
215
|
+
type: stdlib
|
|
216
|
+
- name: regexp_parser
|
|
217
|
+
version: '2.8'
|
|
218
|
+
source:
|
|
219
|
+
type: git
|
|
220
|
+
name: ruby/gem_rbs_collection
|
|
221
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
222
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
223
|
+
repo_dir: gems
|
|
224
|
+
- name: rubocop
|
|
225
|
+
version: '1.57'
|
|
226
|
+
source:
|
|
227
|
+
type: git
|
|
228
|
+
name: ruby/gem_rbs_collection
|
|
229
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
230
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
231
|
+
repo_dir: gems
|
|
232
|
+
- name: rubocop-ast
|
|
233
|
+
version: '1.46'
|
|
234
|
+
source:
|
|
235
|
+
type: git
|
|
236
|
+
name: ruby/gem_rbs_collection
|
|
237
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
238
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
239
|
+
repo_dir: gems
|
|
240
|
+
- name: securerandom
|
|
241
|
+
version: '0'
|
|
242
|
+
source:
|
|
243
|
+
type: stdlib
|
|
244
|
+
- name: simplecov
|
|
245
|
+
version: '0.22'
|
|
246
|
+
source:
|
|
247
|
+
type: git
|
|
248
|
+
name: ruby/gem_rbs_collection
|
|
249
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
250
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
251
|
+
repo_dir: gems
|
|
252
|
+
- name: singleton
|
|
253
|
+
version: '0'
|
|
254
|
+
source:
|
|
255
|
+
type: stdlib
|
|
256
|
+
- name: socket
|
|
257
|
+
version: '0'
|
|
258
|
+
source:
|
|
259
|
+
type: stdlib
|
|
260
|
+
- name: stringio
|
|
261
|
+
version: '0'
|
|
262
|
+
source:
|
|
263
|
+
type: stdlib
|
|
264
|
+
- name: strscan
|
|
265
|
+
version: '0'
|
|
266
|
+
source:
|
|
267
|
+
type: stdlib
|
|
268
|
+
- name: time
|
|
269
|
+
version: '0'
|
|
270
|
+
source:
|
|
271
|
+
type: stdlib
|
|
272
|
+
- name: timeout
|
|
273
|
+
version: '0'
|
|
274
|
+
source:
|
|
275
|
+
type: stdlib
|
|
276
|
+
- name: tsort
|
|
277
|
+
version: '0'
|
|
278
|
+
source:
|
|
279
|
+
type: stdlib
|
|
280
|
+
- name: tzinfo
|
|
281
|
+
version: '2.0'
|
|
282
|
+
source:
|
|
283
|
+
type: git
|
|
284
|
+
name: ruby/gem_rbs_collection
|
|
285
|
+
revision: 9bf2eebb1c54b5d6f23f2acb65d4c36f195b4783
|
|
286
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
287
|
+
repo_dir: gems
|
|
288
|
+
- name: uri
|
|
289
|
+
version: '0'
|
|
290
|
+
source:
|
|
291
|
+
type: stdlib
|
|
292
|
+
gemfile_lock_path: Gemfile.lock
|
data/rbs_collection.yaml
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
sources:
|
|
2
|
+
- type: git
|
|
3
|
+
name: ruby/gem_rbs_collection
|
|
4
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
5
|
+
revision: main
|
|
6
|
+
repo_dir: gems
|
|
7
|
+
|
|
8
|
+
path: .gem_rbs_collection
|
|
9
|
+
|
|
10
|
+
gems:
|
|
11
|
+
- name: singleton
|
|
12
|
+
- name: forwardable
|
|
13
|
+
- name: delegate
|
|
14
|
+
- name: timeout
|