bitfab 0.62.3 → 0.62.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ea9a0439252adacbe50f5c2bc210b5a9708eb772b9998c3660008b10e14dd95
4
- data.tar.gz: 0cd4bfab124dac3a35d3653f2fbef02c6b7e6671bbab36fa9f3b583652ed8339
3
+ metadata.gz: 17cb4215f2940d7b31473b2de0b4e5c1a0f87cc9eaed67050cb78f866ea1a24d
4
+ data.tar.gz: cab44aa11d1bb5f8a30cbfc38f2507dfc53e230821d0851279ace1ed24a19dff
5
5
  SHA512:
6
- metadata.gz: 4e191d599d446e776599c9b01014768e95710f23e9ca27f2c8618008eb3b454718d629f2533d242b412520e6c309a5a390ff65e66d1bd10a23a865b6c0d53654
7
- data.tar.gz: 74f6a2fa1301b226afca67d30490b5ed0095a28cae9aa8513d89291a7b06e7f95303028fe104ff672a79e57efcdc3c8bfd491e643a1ec7fe33f5a478936160d7
6
+ metadata.gz: 7f2c5073f314c9afe5b9dccb6c101476803a00602467089d618fe0131be631c97f2768bd240ae31728875953605f508517bfcb041339b43795dacba6bd50f695
7
+ data.tar.gz: cb1933586e1b8aeaf0233b7c163abb10cbe6805b156d26489c596cbbdba972984614ac5245aab38d0e35ad0333ae09fd7edc27f42b1ae9d826fef05aaa44c09b
data/lib/bitfab/client.rb CHANGED
@@ -37,7 +37,7 @@ module Bitfab
37
37
 
38
38
  attr_reader :service_url
39
39
 
40
- attr_reader :datasets, :assertion_categories, :organization_members, :traces, :labels, :graders
40
+ attr_reader :datasets, :assertion_categories, :organization_members, :traces, :labels, :graders, :experiments
41
41
 
42
42
  def initialize(api_key: nil, service_url: nil, capture_enabled: nil, enabled: nil, strict: false, simulation_plan: true, timeout: 120, trace_across_threads: nil, env_vars: nil, baml_client: nil, db_snapshot: nil)
43
43
  @db_snapshot = DbSnapshot.normalize_config(db_snapshot)
@@ -59,6 +59,7 @@ module Bitfab
59
59
  @traces = Traces.new(@http_client)
60
60
  @labels = Labels.new(@http_client)
61
61
  @graders = Graders.new(@http_client)
62
+ @experiments = Experiments.new(@http_client)
62
63
  # Mock overrides registered via register_mock_override, applied to every
63
64
  # replay on this client (after any per-call mock_override). Instance
64
65
  # state, no global; clear_mock_overrides resets it.
@@ -197,7 +198,7 @@ module Bitfab
197
198
  # @return [Hash] with :items, :experiment_id, :experiment_url, and the
198
199
  # deprecated aliases :test_run_id and :test_run_url carrying the same values
199
200
  def replay(receiver, method_name = nil, trace_function_key:, limit: nil, trace_ids: nil, concurrency: nil, max_concurrency: ReplayConcurrency::UNSET,
200
- name: nil, notes: nil, code_change_description: Replay::CODE_CHANGE_UNSET, code_change_files: Replay::CODE_CHANGE_UNSET, experiment_group_id: nil, dataset_id: nil, dataset_ids: nil, grader_ids: nil, mock: "marked", attempts: ReplayConcurrency::UNSET, only_with_assertions: false, judge_assertions: false, dry_run: false,
201
+ name: nil, notes: nil, metadata: nil, code_change_description: Replay::CODE_CHANGE_UNSET, code_change_files: Replay::CODE_CHANGE_UNSET, experiment_group_id: nil, dataset_id: nil, dataset_ids: nil, grader_ids: nil, mock: "marked", attempts: ReplayConcurrency::UNSET, only_with_assertions: false, judge_assertions: false, dry_run: false,
201
202
  adapt_inputs: nil, mock_override: nil, db_branch: nil, on_item_start: nil, on_item_finish: nil, on_progress: nil,
202
203
  on_experiment_start: nil, experimental_selective_replay: nil)
203
204
  Replay.run(
@@ -209,6 +210,7 @@ module Bitfab
209
210
  trace_ids:,
210
211
  name:,
211
212
  notes:,
213
+ metadata:,
212
214
  concurrency:,
213
215
  max_concurrency:,
214
216
  attempts:,
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "time"
5
+ require "uri"
6
+
7
+ module Bitfab
8
+ class Experiments
9
+ PATH = "/api/sdk/experiments"
10
+ private_constant :PATH
11
+
12
+ def initialize(http_client)
13
+ @http_client = http_client
14
+ end
15
+
16
+ def list(dataset_id: nil, trace_function_key: nil, git_branch: nil, experiment_group_id: nil, status: nil,
17
+ metadata: nil, created_after: nil, created_before: nil, cursor: nil, limit: nil)
18
+ params = {}
19
+ params["datasetId"] = dataset_id unless dataset_id.nil?
20
+ params["traceFunctionKey"] = trace_function_key unless trace_function_key.nil?
21
+ params["gitBranch"] = git_branch unless git_branch.nil?
22
+ params["experimentGroupId"] = experiment_group_id unless experiment_group_id.nil?
23
+ params["status"] = status unless status.nil?
24
+ params["metadata"] = JSON.generate(metadata) unless metadata.nil?
25
+ params["createdAfter"] = iso8601(created_after) unless created_after.nil?
26
+ params["createdBefore"] = iso8601(created_before) unless created_before.nil?
27
+ params["cursor"] = cursor unless cursor.nil?
28
+ params["limit"] = limit unless limit.nil?
29
+ query = URI.encode_www_form(params)
30
+ @http_client.get(query.empty? ? PATH : "#{PATH}?#{query}")
31
+ end
32
+
33
+ def get(id)
34
+ @http_client.get("#{PATH}/#{encode(id)}")["experiment"]
35
+ end
36
+
37
+ def get_rollup(id)
38
+ @http_client.get("#{PATH}/#{encode(id)}/rollup")
39
+ end
40
+
41
+ def get_rollup_all(ids)
42
+ return [] if ids.empty?
43
+
44
+ query = URI.encode_www_form("experimentIds" => ids.join(","))
45
+ @http_client.get("#{PATH}/rollups?#{query}")["rollups"]
46
+ end
47
+
48
+ private
49
+
50
+ def iso8601(value)
51
+ value.respond_to?(:iso8601) ? value.iso8601 : value.to_s
52
+ end
53
+
54
+ def encode(value)
55
+ URI.encode_www_form_component(value).gsub("+", "%20")
56
+ end
57
+ end
58
+ end
@@ -261,7 +261,7 @@ module Bitfab
261
261
  # runnable graders at completion; each must be an active/live grader in the
262
262
  # same org and trace function or the server rejects the replay
263
263
  def start_replay(trace_function_key, limit, trace_ids: nil, code_change_description: nil,
264
- code_change_files: nil, experiment_group_id: nil, name: nil, notes: nil, include_db_branch_lease: false, dataset_ids: nil,
264
+ code_change_files: nil, experiment_group_id: nil, name: nil, notes: nil, metadata: nil, include_db_branch_lease: false, dataset_ids: nil,
265
265
  grader_ids: nil, db_branch_settings: nil, attempts: 1, only_with_assertions: false, judge_assertions: false, include_original_metadata: false, experimental_selective_replay: nil)
266
266
  payload = {
267
267
  "traceFunctionKey" => trace_function_key
@@ -272,6 +272,7 @@ module Bitfab
272
272
  payload["traceIds"] = trace_ids if trace_ids
273
273
  payload["name"] = name unless name.nil?
274
274
  payload["notes"] = notes unless notes.nil?
275
+ payload["metadata"] = metadata unless metadata.nil?
275
276
  payload["codeChangeDescription"] = code_change_description unless code_change_description.nil?
276
277
  payload["codeChangeFiles"] = normalize_code_change_files(code_change_files) unless code_change_files.nil?
277
278
  payload["experimentGroupId"] = experiment_group_id unless experiment_group_id.nil?
data/lib/bitfab/replay.rb CHANGED
@@ -280,7 +280,7 @@ module Bitfab
280
280
  # crashes the run.
281
281
  # @return [Hash] with :items, :experiment_id, :experiment_url, and the
282
282
  # deprecated aliases :test_run_id and :test_run_url carrying the same values
283
- def run(client, receiver, method_name, trace_function_key:, limit: nil, trace_ids: nil, name: nil, notes: nil,
283
+ def run(client, receiver, method_name, trace_function_key:, limit: nil, trace_ids: nil, name: nil, notes: nil, metadata: nil,
284
284
  concurrency: nil, max_concurrency: ReplayConcurrency::UNSET, code_change_description: CODE_CHANGE_UNSET, code_change_files: CODE_CHANGE_UNSET, experiment_group_id: nil,
285
285
  dataset_id: nil, dataset_ids: nil, grader_ids: nil, mock: "marked", attempts: ReplayConcurrency::UNSET, only_with_assertions: false, judge_assertions: false, dry_run: false,
286
286
  adapt_inputs: nil, mock_override: nil, db_branch: nil, on_item_start: nil, on_item_finish: nil, on_progress: nil,
@@ -378,6 +378,7 @@ module Bitfab
378
378
  trace_ids:,
379
379
  name:,
380
380
  notes:,
381
+ metadata:,
381
382
  code_change_description:,
382
383
  code_change_files:,
383
384
  experiment_group_id:,
@@ -19,7 +19,7 @@ module Bitfab
19
19
  # Project-owned registry of production replay roots.
20
20
  class ReplayRegistry
21
21
  OPTION_NAMES = %i[
22
- limit trace_ids name notes concurrency max_concurrency code_change_description
22
+ limit trace_ids name notes metadata concurrency max_concurrency code_change_description
23
23
  code_change_files experiment_group_id dataset_id dataset_ids grader_ids mock
24
24
  mock_override adapt_inputs db_branch attempts only_with_assertions judge_assertions dry_run on_item_finish
25
25
  ].freeze
@@ -186,7 +186,7 @@ module Bitfab
186
186
  options[:limit] = bound || 10
187
187
  end
188
188
 
189
- %i[name notes max_concurrency experiment_group_id dataset_ids grader_ids mock attempts only_with_assertions judge_assertions dry_run].each do |key|
189
+ %i[name notes metadata max_concurrency experiment_group_id dataset_ids grader_ids mock attempts only_with_assertions judge_assertions dry_run].each do |key|
190
190
  options[key] = args[key] unless args[key].nil?
191
191
  end
192
192
 
@@ -291,6 +291,15 @@ module Bitfab
291
291
  options.on("--notes TEXT",
292
292
  "Run conditions Bitfab cannot see on its own, such as an environment override or a forced feature flag. " \
293
293
  "Kept on the experiment next to its name.") { |value| args[:notes] = value }
294
+ options.on("--metadata KEY=VALUE",
295
+ "A key and value stored on the experiment, such as schedule=eod. Repeat the flag for more pairs. " \
296
+ "Filter later runs on it with client.experiments.list(metadata: {...}).") do |value|
297
+ key, pair_value = value.split("=", 2)
298
+ if key.to_s.empty? || pair_value.nil?
299
+ raise OptionParser::InvalidArgument, "--metadata expects KEY=VALUE, got '#{value}'"
300
+ end
301
+ (args[:metadata] ||= {})[key] = pair_value
302
+ end
294
303
  options.on("--concurrency N", Integer) do |value|
295
304
  args[:max_concurrency] = positive_integer("--concurrency", value)
296
305
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bitfab
4
- VERSION = "0.62.3"
4
+ VERSION = "0.62.4"
5
5
  end
data/lib/bitfab.rb CHANGED
@@ -21,6 +21,7 @@ require_relative "bitfab/traces"
21
21
  require_relative "bitfab/assertions"
22
22
  require_relative "bitfab/labels"
23
23
  require_relative "bitfab/graders"
24
+ require_relative "bitfab/experiments"
24
25
  require_relative "bitfab/mock_override"
25
26
  require_relative "bitfab/replay"
26
27
  require_relative "bitfab/replay_branch"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitfab
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.62.3
4
+ version: 0.62.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harvest Team
@@ -170,6 +170,7 @@ files:
170
170
  - lib/bitfab/detached_trace.rb
171
171
  - lib/bitfab/env.rb
172
172
  - lib/bitfab/experiment_id.rb
173
+ - lib/bitfab/experiments.rb
173
174
  - lib/bitfab/git_command.rb
174
175
  - lib/bitfab/git_state.rb
175
176
  - lib/bitfab/graders.rb