From b249b70679dee081ea3723a5cc90766a440c7ccf Mon Sep 17 00:00:00 2001 From: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com> Date: Fri, 25 Sep 2026 15:49:55 -0700 Subject: [PATCH] feat: Add flag overrides to the contract test service The test service advertises the flag-overrides capability and accepts the overrides block of the SDK configuration: filePaths, duplicateKeysHandling, changeDetection, and pollIntervalMs map to the options of LaunchDarkly::Integrations::FileData.override_source on the FDv2 data system builder. Overrides without a data system configuration are an error. The listen gem joins the contract test bundle so that the watching change detection mode can run. The service port can be set with the PORT environment variable and still defaults to 9000. --- contract-tests/Gemfile | 3 +++ contract-tests/client_entity.rb | 22 ++++++++++++++++++++++ contract-tests/service.rb | 3 ++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/contract-tests/Gemfile b/contract-tests/Gemfile index 2cf6ac62..af66f0bc 100644 --- a/contract-tests/Gemfile +++ b/contract-tests/Gemfile @@ -8,6 +8,9 @@ gem "puma", "~> 8.0" gem "rackup", "~> 2.2" gem 'sinatra', '>= 4.1' +# The file-based override source uses the listen gem for its watching change detection mode. +gem 'listen', '~> 3.3' + gem 'rubocop', '~> 1.37', group: 'development' gem 'rubocop-performance', '~> 1.15', group: 'development' diff --git a/contract-tests/client_entity.rb b/contract-tests/client_entity.rb index 5df1f56a..8fe1ce60 100644 --- a/contract-tests/client_entity.rb +++ b/contract-tests/client_entity.rb @@ -56,7 +56,12 @@ def initialize(log, config) opts[:payload_filter_key] = data_system_config[:payloadFilter] end + # Flag overrides are an option of the FDv2 data system configuration. + data_system.overrides(build_override_source(config[:overrides])) if config[:overrides] + opts[:data_system_config] = data_system.build + elsif config[:overrides] + raise ArgumentError, "flag overrides require the data system to be configured" elsif config[:streaming] streaming = config[:streaming] opts[:stream_uri] = streaming[:baseUri] unless streaming[:baseUri].nil? @@ -365,6 +370,23 @@ def close builder end + # + # Builds the file-based override source from the `overrides` block of the contract test + # configuration. + # + # @param overrides_config [Hash] the overrides configuration + # @return [Object] a builder for LaunchDarkly::DataSystem::ConfigBuilder#overrides + # + private def build_override_source(overrides_config) + options = { paths: overrides_config[:filePaths] } + if overrides_config[:duplicateKeysHandling] + options[:duplicate_keys_handling] = overrides_config[:duplicateKeysHandling].to_sym + end + options[:change_detection] = overrides_config[:changeDetection].to_sym if overrides_config[:changeDetection] + set_optional_time_prop(overrides_config, :pollIntervalMs, options, :poll_interval) + LaunchDarkly::Integrations::FileData.override_source(options) + end + # # Builds a persistent data store from the contract test configuration. # diff --git a/contract-tests/service.rb b/contract-tests/service.rb index 779ed37d..246220a6 100644 --- a/contract-tests/service.rb +++ b/contract-tests/service.rb @@ -17,7 +17,7 @@ } set :bind, '0.0.0.0' -set :port, 9000 +set :port, (ENV['PORT'] || 9000).to_i set :logging, false clients = {} @@ -55,6 +55,7 @@ 'flag-change-listeners', 'flag-value-change-listeners', 'fdv1-fallback', + 'flag-overrides', ], }.to_json end