datadog-ci 1.14.0 → 1.15.0

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -2
  3. data/lib/datadog/ci/configuration/components.rb +2 -1
  4. data/lib/datadog/ci/configuration/settings.rb +6 -0
  5. data/lib/datadog/ci/contrib/minitest/runner.rb +4 -1
  6. data/lib/datadog/ci/contrib/parallel_tests/cli.rb +84 -0
  7. data/lib/datadog/ci/contrib/parallel_tests/configuration/settings.rb +32 -0
  8. data/lib/datadog/ci/contrib/parallel_tests/ext.rb +16 -0
  9. data/lib/datadog/ci/contrib/parallel_tests/integration.rb +42 -0
  10. data/lib/datadog/ci/contrib/parallel_tests/patcher.rb +24 -0
  11. data/lib/datadog/ci/contrib/rspec/example.rb +7 -0
  12. data/lib/datadog/ci/contrib/rspec/example_group.rb +18 -8
  13. data/lib/datadog/ci/contrib/rspec/helpers.rb +18 -0
  14. data/lib/datadog/ci/contrib/rspec/runner.rb +2 -0
  15. data/lib/datadog/ci/ext/settings.rb +1 -0
  16. data/lib/datadog/ci/ext/test.rb +20 -0
  17. data/lib/datadog/ci/git/local_repository.rb +1 -1
  18. data/lib/datadog/ci/git/tree_uploader.rb +9 -0
  19. data/lib/datadog/ci/readonly_test_module.rb +28 -0
  20. data/lib/datadog/ci/readonly_test_session.rb +31 -0
  21. data/lib/datadog/ci/remote/component.rb +43 -16
  22. data/lib/datadog/ci/test_management/component.rb +34 -1
  23. data/lib/datadog/ci/test_management/tests_properties.rb +2 -1
  24. data/lib/datadog/ci/test_optimisation/component.rb +31 -5
  25. data/lib/datadog/ci/test_session.rb +7 -1
  26. data/lib/datadog/ci/test_visibility/component.rb +82 -28
  27. data/lib/datadog/ci/test_visibility/context.rb +77 -29
  28. data/lib/datadog/ci/test_visibility/null_component.rb +4 -0
  29. data/lib/datadog/ci/test_visibility/store/{local.rb → fiber_local.rb} +1 -1
  30. data/lib/datadog/ci/test_visibility/store/{global.rb → process.rb} +23 -18
  31. data/lib/datadog/ci/test_visibility/transport.rb +1 -2
  32. data/lib/datadog/ci/transport/http.rb +1 -1
  33. data/lib/datadog/ci/utils/file_storage.rb +57 -0
  34. data/lib/datadog/ci/utils/stateful.rb +52 -0
  35. data/lib/datadog/ci/version.rb +1 -1
  36. data/lib/datadog/ci.rb +4 -3
  37. metadata +14 -5
  38. data/lib/datadog/ci/test_visibility/capabilities.rb +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 694421f4e4621608a9aa6d8deb0b1407fa348fec68820a28ced1a567c56ed289
4
- data.tar.gz: 12b586d1eabe233af428c7294564f8b7a46ff8bbb64d44f222762afd371a2c1c
3
+ metadata.gz: c4507da31359cd997cb38e73190a4e6514ad8c69d86f9ce1b0c47fd7764e5dbd
4
+ data.tar.gz: 515872f426f95492fed9d1577f14bb7b1e447b0c011edf2bbfbb7ea23992d9cc
5
5
  SHA512:
6
- metadata.gz: 81c173cb2b22a8e0e3853d21d4e1ac023569142d51bb266c287ef7d4c7c5f2dfd97d2f3914acd1ac766d3e60ac15929cbee849b7284d300644113e6a14dea331
7
- data.tar.gz: c1f1f93f35850cf9b6d1e360d53f2a26e2e46961aeed8e69f216327513e4001c45a42c363c20609ad0b525a4aeaf0fdec59e32f38d9302289c9e256ccf5aa81c
6
+ metadata.gz: 3d0db7cb6a13a4c2f0b38b22c8dc2470a9ec760c38312c929a7b6224b118e18b279addf76901f7f094f60123a9e65d9afef06c15970bf01b247bc031bf80725d
7
+ data.tar.gz: f731bc7979a69ae63362d06d0313754bd825a22baf934cb682c1dc2a16a8584d0c3ece806f2bfb75d42924c09fff6296bf8c5c1be142afbe3ab7716bcb753815
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.15.0] - 2025-03-25
4
+
5
+
6
+ ### Added
7
+
8
+ * parallel tests gem support ([#299][])
9
+ * implemented attempt to fix flow V2 ([#298][])
10
+
11
+ ### Fixed
12
+
13
+ * Fix: prevent test impact analysis from skipping flaky tests that are attempted to be fixed ([#301][])
14
+ * Fix git commit message extraction to extract multiline commit messages correctly ([#300][])
15
+
3
16
  ## [1.14.0] - 2025-03-11
4
17
 
5
18
  ### Added
@@ -404,7 +417,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
404
417
 
405
418
  - Ruby versions < 2.7 no longer supported ([#8][])
406
419
 
407
- [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.14.0...main
420
+ [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.15.0...main
421
+ [1.15.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.14.0...v1.15.0
408
422
  [1.14.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.13.0...v1.14.0
409
423
  [1.13.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.12.0...v1.13.0
410
424
  [1.12.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.11.0...v1.12.0
@@ -579,4 +593,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
579
593
  [#289]: https://github.com/DataDog/datadog-ci-rb/issues/289
580
594
  [#292]: https://github.com/DataDog/datadog-ci-rb/issues/292
581
595
  [#294]: https://github.com/DataDog/datadog-ci-rb/issues/294
582
- [#295]: https://github.com/DataDog/datadog-ci-rb/issues/295
596
+ [#295]: https://github.com/DataDog/datadog-ci-rb/issues/295
597
+ [#298]: https://github.com/DataDog/datadog-ci-rb/issues/298
598
+ [#299]: https://github.com/DataDog/datadog-ci-rb/issues/299
599
+ [#300]: https://github.com/DataDog/datadog-ci-rb/issues/300
600
+ [#301]: https://github.com/DataDog/datadog-ci-rb/issues/301
@@ -129,7 +129,8 @@ module Datadog
129
129
  @test_visibility = TestVisibility::Component.new(
130
130
  test_suite_level_visibility_enabled: !settings.ci.force_test_level_visibility,
131
131
  logical_test_session_name: settings.ci.test_session_name,
132
- known_tests_client: build_known_tests_client(settings, test_visibility_api)
132
+ known_tests_client: build_known_tests_client(settings, test_visibility_api),
133
+ context_service_uri: settings.ci.test_visibility_drb_server_uri
133
134
  )
134
135
  end
135
136
 
@@ -134,6 +134,12 @@ module Datadog
134
134
  o.default false
135
135
  end
136
136
 
137
+ # internal only
138
+ option :test_visibility_drb_server_uri do |o|
139
+ o.type :string, nilable: true
140
+ o.env CI::Ext::Settings::ENV_TEST_VISIBILITY_DRB_SERVER_URI
141
+ end
142
+
137
143
  define_method(:instrument) do |integration_name, options = {}, &block|
138
144
  return unless enabled
139
145
 
@@ -27,7 +27,10 @@ module Datadog
27
27
  CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_integration.version.to_s
28
28
  },
29
29
  service: datadog_configuration[:service_name],
30
- estimated_total_tests_count: tests_count
30
+ estimated_total_tests_count: tests_count,
31
+ # if minitest is being used with a parallel runner, then tests split will happen by example, not by test suite
32
+ # we need to always start/stop test suites in the parent process in this case
33
+ local_test_suites_mode: false
31
34
  )
32
35
  test_visibility_component.start_test_module(Ext::FRAMEWORK)
33
36
  end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../ext/test"
4
+ require_relative "../rspec/ext"
5
+
6
+ module Datadog
7
+ module CI
8
+ module Contrib
9
+ module ParallelTests
10
+ module CLI
11
+ def self.included(base)
12
+ base.prepend(InstanceMethods)
13
+ end
14
+
15
+ module InstanceMethods
16
+ def run_tests_in_parallel(num_processes, options)
17
+ # only rspec runner is supported for now
18
+ return super if @runner != ::ParallelTests::RSpec::Runner
19
+
20
+ begin
21
+ test_session = test_visibility_component.start_test_session(
22
+ tags: {
23
+ CI::Ext::Test::TAG_FRAMEWORK => CI::Contrib::RSpec::Ext::FRAMEWORK,
24
+ CI::Ext::Test::TAG_FRAMEWORK_VERSION => datadog_extract_rspec_version
25
+ },
26
+ service: datadog_configuration[:service_name],
27
+ estimated_total_tests_count: 10_000, # temporary value, updated by child processes
28
+ distributed: true
29
+ )
30
+ test_module = test_visibility_component.start_test_module("rspec")
31
+
32
+ options[:env] ||= {}
33
+ options[:env][CI::Ext::Settings::ENV_TEST_VISIBILITY_DRB_SERVER_URI] = test_visibility_component.context_service_uri
34
+
35
+ super
36
+ ensure
37
+ test_module&.finish
38
+ test_session&.finish
39
+ end
40
+ end
41
+
42
+ def any_test_failed?(test_results)
43
+ res = super
44
+
45
+ test_session = test_visibility_component.active_test_session
46
+ test_module = test_visibility_component.active_test_module
47
+ if res
48
+ test_module&.failed!
49
+ test_session&.failed!
50
+ else
51
+ test_module&.passed!
52
+ test_session&.passed!
53
+ end
54
+
55
+ res
56
+ end
57
+
58
+ def datadog_extract_rspec_version
59
+ # Try to find either 'rspec' or 'rspec-core' gem
60
+ if Gem.loaded_specs["rspec"]
61
+ Gem.loaded_specs["rspec"].version.to_s
62
+ elsif Gem.loaded_specs["rspec-core"]
63
+ Gem.loaded_specs["rspec-core"].version.to_s
64
+ else
65
+ "0.0.0"
66
+ end
67
+ rescue => e
68
+ Datadog.logger.debug("Error extracting RSpec version: #{e.class.name} - #{e.message}")
69
+ "0.0.0"
70
+ end
71
+
72
+ def datadog_configuration
73
+ Datadog.configuration.ci[:paralleltests]
74
+ end
75
+
76
+ def test_visibility_component
77
+ Datadog.send(:components).test_visibility
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../ext"
4
+ require_relative "../../settings"
5
+ require_relative "../../../utils/configuration"
6
+
7
+ module Datadog
8
+ module CI
9
+ module Contrib
10
+ module ParallelTests
11
+ module Configuration
12
+ # Custom settings for the ParallelTests integration
13
+ # @public_api
14
+ class Settings < Datadog::CI::Contrib::Settings
15
+ option :enabled do |o|
16
+ o.type :bool
17
+ o.env Ext::ENV_ENABLED
18
+ o.default true
19
+ end
20
+
21
+ option :service_name do |o|
22
+ o.type :string
23
+ o.default do
24
+ Utils::Configuration.fetch_service_name(Ext::DEFAULT_SERVICE_NAME)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module CI
5
+ module Contrib
6
+ module ParallelTests
7
+ # Datadog ParallelTests integration constants
8
+ module Ext
9
+ ENV_ENABLED = "DD_TRACE_PARALLEL_TESTS_ENABLED"
10
+
11
+ DEFAULT_SERVICE_NAME = "parallel_tests"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../integration"
4
+ require_relative "configuration/settings"
5
+ require_relative "patcher"
6
+
7
+ module Datadog
8
+ module CI
9
+ module Contrib
10
+ module ParallelTests
11
+ # Description of ParallelTests integration
12
+ class Integration < Datadog::CI::Contrib::Integration
13
+ MINIMUM_VERSION = Gem::Version.new("4.0")
14
+
15
+ def version
16
+ Gem.loaded_specs["parallel_tests"]&.version
17
+ end
18
+
19
+ def loaded?
20
+ !defined?(::ParallelTests).nil? && !defined?(::ParallelTests::CLI).nil?
21
+ end
22
+
23
+ def compatible?
24
+ super && version >= MINIMUM_VERSION
25
+ end
26
+
27
+ def late_instrument?
28
+ false
29
+ end
30
+
31
+ def new_configuration
32
+ Configuration::Settings.new
33
+ end
34
+
35
+ def patcher
36
+ Patcher
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "cli"
4
+ require_relative "integration"
5
+ require_relative "../patcher"
6
+
7
+ module Datadog
8
+ module CI
9
+ module Contrib
10
+ module ParallelTests
11
+ # Patcher enables patching of parallel_tests module
12
+ module Patcher
13
+ include Datadog::CI::Contrib::Patcher
14
+
15
+ module_function
16
+
17
+ def patch
18
+ ::ParallelTests::CLI.include(CLI)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -97,6 +97,13 @@ module Datadog
97
97
  )
98
98
  end
99
99
 
100
+ def datadog_fqn_test_id
101
+ @datadog_fqn_test_id ||= Utils::TestRun.datadog_test_id(
102
+ datadog_test_name,
103
+ datadog_test_suite_name
104
+ )
105
+ end
106
+
100
107
  def datadog_unskippable?
101
108
  !!metadata[CI::Ext::Test::ITR_UNSKIPPABLE_OPTION]
102
109
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "../../ext/test"
4
4
  require_relative "ext"
5
+ require_relative "helpers"
5
6
 
6
7
  module Datadog
7
8
  module CI
@@ -28,13 +29,17 @@ module Datadog
28
29
  return super unless top_level?
29
30
 
30
31
  suite_name = "#{description} at #{file_path}"
31
- test_suite = test_visibility_component&.start_test_suite(
32
- suite_name,
33
- tags: {
34
- CI::Ext::Test::TAG_SOURCE_FILE => Git::LocalRepository.relative_to_root(metadata[:file_path]),
35
- CI::Ext::Test::TAG_SOURCE_START => metadata[:line_number].to_s
36
- }
37
- )
32
+ suite_tags = {
33
+ CI::Ext::Test::TAG_SOURCE_FILE => Git::LocalRepository.relative_to_root(metadata[:file_path]),
34
+ CI::Ext::Test::TAG_SOURCE_START => metadata[:line_number].to_s
35
+ }
36
+
37
+ test_suite =
38
+ test_visibility_component&.start_test_suite(
39
+ suite_name,
40
+ tags: suite_tags,
41
+ service: datadog_configuration[:service_name]
42
+ )
38
43
 
39
44
  success = super
40
45
  return success unless test_suite
@@ -56,7 +61,8 @@ module Datadog
56
61
 
57
62
  def all_examples_skipped_by_datadog?
58
63
  descendant_filtered_examples.all? do |example|
59
- !example.datadog_unskippable? && test_optimisation_component&.skippable?(example)
64
+ !example.datadog_unskippable? && test_optimisation_component&.skippable?(example.datadog_test_id) &&
65
+ !test_management_component&.attempt_to_fix?(example.datadog_fqn_test_id)
60
66
  end
61
67
  end
62
68
 
@@ -71,6 +77,10 @@ module Datadog
71
77
  def test_optimisation_component
72
78
  Datadog.send(:components).test_optimisation
73
79
  end
80
+
81
+ def test_management_component
82
+ Datadog.send(:components).test_management
83
+ end
74
84
  end
75
85
  end
76
86
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module CI
5
+ module Contrib
6
+ module RSpec
7
+ # Helper methods for RSpec instrumentation
8
+ module Helpers
9
+ module_function
10
+
11
+ def parallel_tests?
12
+ !!ENV.fetch("TEST_ENV_NUMBER", nil) && !!ENV.fetch("PARALLEL_TEST_GROUPS", nil)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -3,6 +3,7 @@
3
3
  require_relative "../../ext/test"
4
4
  require_relative "../instrumentation"
5
5
  require_relative "ext"
6
+ require_relative "helpers"
6
7
 
7
8
  module Datadog
8
9
  module CI
@@ -32,6 +33,7 @@ module Datadog
32
33
 
33
34
  result = super
34
35
  return result unless test_module && test_session
36
+ return result if Helpers.parallel_tests?
35
37
 
36
38
  if result != 0
37
39
  test_module.failed!
@@ -22,6 +22,7 @@ module Datadog
22
22
  ENV_TEST_SESSION_NAME = "DD_TEST_SESSION_NAME"
23
23
  ENV_TEST_MANAGEMENT_ENABLED = "DD_TEST_MANAGEMENT_ENABLED"
24
24
  ENV_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES = "DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES"
25
+ ENV_TEST_VISIBILITY_DRB_SERVER_URI = "DD_TEST_VISIBILITY_DRB_SERVER_URI"
25
26
 
26
27
  # Source: https://docs.datadoghq.com/getting_started/site/
27
28
  DD_SITE_ALLOWLIST = %w[
@@ -86,6 +86,26 @@ module Datadog
86
86
  TAG_TEST_MANAGEMENT_QUARANTINE = "_dd.library_capabilities.test_management.quarantine"
87
87
  TAG_TEST_MANAGEMENT_DISABLE = "_dd.library_capabilities.test_management.disable"
88
88
  TAG_TEST_MANAGEMENT_ATTEMPT_TO_FIX = "_dd.library_capabilities.test_management.attempt_to_fix"
89
+
90
+ # Version numbers for library capabilities
91
+ module Versions
92
+ TEST_IMPACT_ANALYSIS_VERSION = "1"
93
+ EARLY_FLAKE_DETECTION_VERSION = "1"
94
+ AUTO_TEST_RETRIES_VERSION = "1"
95
+ TEST_MANAGEMENT_QUARANTINE_VERSION = "1"
96
+ TEST_MANAGEMENT_DISABLE_VERSION = "1"
97
+ TEST_MANAGEMENT_ATTEMPT_TO_FIX_VERSION = "2"
98
+ end
99
+
100
+ # Map of capabilities to their versions
101
+ CAPABILITY_VERSIONS = {
102
+ TAG_TEST_IMPACT_ANALYSIS => Versions::TEST_IMPACT_ANALYSIS_VERSION,
103
+ TAG_EARLY_FLAKE_DETECTION => Versions::EARLY_FLAKE_DETECTION_VERSION,
104
+ TAG_AUTO_TEST_RETRIES => Versions::AUTO_TEST_RETRIES_VERSION,
105
+ TAG_TEST_MANAGEMENT_QUARANTINE => Versions::TEST_MANAGEMENT_QUARANTINE_VERSION,
106
+ TAG_TEST_MANAGEMENT_DISABLE => Versions::TEST_MANAGEMENT_DISABLE_VERSION,
107
+ TAG_TEST_MANAGEMENT_ATTEMPT_TO_FIX => Versions::TEST_MANAGEMENT_ATTEMPT_TO_FIX_VERSION
108
+ }.freeze
89
109
  end
90
110
 
91
111
  # internal APM tag to mark a span as a test span
@@ -142,7 +142,7 @@ module Datadog
142
142
  end
143
143
 
144
144
  def self.git_commit_message
145
- exec_git_command("git show -s --format=%s")
145
+ exec_git_command("git log -n 1 --format=%B")
146
146
  rescue => e
147
147
  log_failure(e, "git commit message")
148
148
  nil
@@ -27,6 +27,11 @@ module Datadog
27
27
  return
28
28
  end
29
29
 
30
+ if test_visibility_component.client_process?
31
+ Datadog.logger.debug("Test visibility component is running in client process, aborting git upload")
32
+ return
33
+ end
34
+
30
35
  Datadog.logger.debug { "Uploading git tree for repository #{repository_url}" }
31
36
 
32
37
  latest_commits = LocalRepository.git_commits
@@ -91,6 +96,10 @@ module Datadog
91
96
  backend_commits.include?(commit)
92
97
  end
93
98
  end
99
+
100
+ def test_visibility_component
101
+ Datadog.send(:components).test_visibility
102
+ end
94
103
  end
95
104
  end
96
105
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "test_module"
4
+
5
+ module Datadog
6
+ module CI
7
+ # @internal_api
8
+ class ReadonlyTestModule < TestModule
9
+ def initialize(test_module)
10
+ @id = test_module.id
11
+ @name = test_module.name
12
+ end
13
+ attr_reader :id, :name
14
+
15
+ def finish
16
+ raise "ReadonlyTestModule cannot be finished"
17
+ end
18
+
19
+ def set_tag(key, value)
20
+ raise "ReadonlyTestModule cannot be modified"
21
+ end
22
+
23
+ def set_metric(key, value)
24
+ raise "ReadonlyTestModule cannot be modified"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "test_session"
4
+
5
+ module Datadog
6
+ module CI
7
+ # @internal_api
8
+ class ReadonlyTestSession < TestSession
9
+ def initialize(test_session)
10
+ @id = test_session.id
11
+ @name = test_session.name
12
+ @inheritable_tags = test_session.inheritable_tags
13
+ @service = test_session.service
14
+ end
15
+
16
+ attr_reader :id, :name, :inheritable_tags, :service
17
+
18
+ def finish
19
+ raise "ReadonlyTestSession cannot be finished"
20
+ end
21
+
22
+ def set_tag(key, value)
23
+ raise "ReadonlyTestSession cannot be modified"
24
+ end
25
+
26
+ def set_metric(key, value)
27
+ raise "ReadonlyTestSession cannot be modified"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "../worker"
4
+ require_relative "../utils/stateful"
4
5
 
5
6
  module Datadog
6
7
  module CI
@@ -8,33 +9,44 @@ module Datadog
8
9
  # Remote configuration component.
9
10
  # Responsible for fetching library settings and configuring the library accordingly.
10
11
  class Component
12
+ include Datadog::CI::Utils::Stateful
13
+
14
+ FILE_STORAGE_KEY = "remote_component_state"
15
+
11
16
  def initialize(library_settings_client:)
12
17
  @library_settings_client = library_settings_client
18
+ @library_configuration = nil
13
19
  end
14
20
 
15
21
  # called on test session start, uses test session info to send configuration request to the backend
16
22
  def configure(test_session)
17
- library_configuration = @library_settings_client.fetch(test_session)
18
- # sometimes we can skip code coverage for default branch if there are no changes in the repository
19
- # backend needs git metadata uploaded for this test session to check if we can skip code coverage
20
- if library_configuration.require_git?
21
- Datadog.logger.debug { "Library configuration endpoint requires git upload to be finished, waiting..." }
22
- git_tree_upload_worker.wait_until_done
23
-
24
- Datadog.logger.debug { "Requesting library configuration again..." }
25
- library_configuration = @library_settings_client.fetch(test_session)
26
-
27
- if library_configuration.require_git?
28
- Datadog.logger.debug { "git metadata upload did not complete in time when configuring library" }
23
+ # If component state is loaded successfully, skip fetching library configuration
24
+ unless load_component_state
25
+ @library_configuration = @library_settings_client.fetch(test_session)
26
+ # sometimes we can skip code coverage for default branch if there are no changes in the repository
27
+ # backend needs git metadata uploaded for this test session to check if we can skip code coverage
28
+ if @library_configuration.require_git?
29
+ Datadog.logger.debug { "Library configuration endpoint requires git upload to be finished, waiting..." }
30
+ git_tree_upload_worker.wait_until_done
31
+
32
+ Datadog.logger.debug { "Requesting library configuration again..." }
33
+ @library_configuration = @library_settings_client.fetch(test_session)
34
+
35
+ if @library_configuration.require_git?
36
+ Datadog.logger.debug { "git metadata upload did not complete in time when configuring library" }
37
+ end
29
38
  end
39
+
40
+ # Store component state for distributed test runs
41
+ store_component_state if test_session.distributed
30
42
  end
31
43
 
32
44
  # configure different components in parallel because they might block on HTTP requests
33
45
  configuration_workers = [
34
- Worker.new { test_optimisation.configure(library_configuration, test_session) },
35
- Worker.new { test_retries.configure(library_configuration, test_session) },
36
- Worker.new { test_visibility.configure(library_configuration, test_session) },
37
- Worker.new { test_management.configure(library_configuration, test_session) }
46
+ Worker.new { test_optimisation.configure(@library_configuration, test_session) },
47
+ Worker.new { test_retries.configure(@library_configuration, test_session) },
48
+ Worker.new { test_visibility.configure(@library_configuration, test_session) },
49
+ Worker.new { test_management.configure(@library_configuration, test_session) }
38
50
  ]
39
51
 
40
52
  # launch configuration workers
@@ -44,6 +56,21 @@ module Datadog
44
56
  configuration_workers.each(&:wait_until_done)
45
57
  end
46
58
 
59
+ # Implementation of Stateful interface
60
+ def serialize_state
61
+ {
62
+ library_configuration: @library_configuration
63
+ }
64
+ end
65
+
66
+ def restore_state(state)
67
+ @library_configuration = state[:library_configuration]
68
+ end
69
+
70
+ def storage_key
71
+ FILE_STORAGE_KEY
72
+ end
73
+
47
74
  private
48
75
 
49
76
  def test_management