datadog-ci 0.3.0 → 0.5.1

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +89 -1
  3. data/README.md +57 -34
  4. data/lib/datadog/ci/concurrent_span.rb +59 -0
  5. data/lib/datadog/ci/configuration/components.rb +40 -1
  6. data/lib/datadog/ci/configuration/extensions.rb +21 -0
  7. data/lib/datadog/ci/configuration/settings.rb +7 -1
  8. data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +12 -1
  9. data/lib/datadog/ci/contrib/cucumber/formatter.rb +22 -29
  10. data/lib/datadog/ci/contrib/minitest/configuration/settings.rb +10 -1
  11. data/lib/datadog/ci/contrib/minitest/hooks.rb +15 -25
  12. data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +10 -1
  13. data/lib/datadog/ci/contrib/rspec/example.rb +13 -18
  14. data/lib/datadog/ci/contrib/settings.rb +2 -0
  15. data/lib/datadog/ci/ext/app_types.rb +5 -0
  16. data/lib/datadog/ci/ext/environment/extractor.rb +5 -10
  17. data/lib/datadog/ci/ext/environment/providers/github_actions.rb +13 -4
  18. data/lib/datadog/ci/ext/settings.rb +11 -0
  19. data/lib/datadog/ci/ext/test.rb +12 -1
  20. data/lib/datadog/ci/null_span.rb +63 -0
  21. data/lib/datadog/ci/span.rb +117 -0
  22. data/lib/datadog/ci/test.rb +25 -0
  23. data/lib/datadog/ci/test_module.rb +23 -0
  24. data/lib/datadog/ci/test_session.rb +36 -0
  25. data/lib/datadog/ci/test_suite.rb +25 -0
  26. data/lib/datadog/ci/test_visibility/context/global.rb +82 -0
  27. data/lib/datadog/ci/test_visibility/context/local.rb +52 -0
  28. data/lib/datadog/ci/test_visibility/recorder.rb +293 -0
  29. data/lib/datadog/ci/test_visibility/serializers/base.rb +100 -12
  30. data/lib/datadog/ci/test_visibility/serializers/factories/test_suite_level.rb +37 -0
  31. data/lib/datadog/ci/test_visibility/serializers/span.rb +2 -16
  32. data/lib/datadog/ci/test_visibility/serializers/test_module.rb +46 -0
  33. data/lib/datadog/ci/test_visibility/serializers/test_session.rb +46 -0
  34. data/lib/datadog/ci/test_visibility/serializers/test_suite.rb +46 -0
  35. data/lib/datadog/ci/test_visibility/serializers/test_v1.rb +3 -17
  36. data/lib/datadog/ci/test_visibility/serializers/test_v2.rb +38 -0
  37. data/lib/datadog/ci/test_visibility/transport.rb +4 -4
  38. data/lib/datadog/ci/utils/test_run.rb +15 -0
  39. data/lib/datadog/ci/utils/url.rb +15 -0
  40. data/lib/datadog/ci/version.rb +2 -2
  41. data/lib/datadog/ci.rb +378 -7
  42. data/sig/datadog/ci/concurrent_span.rbs +23 -0
  43. data/sig/datadog/ci/configuration/components.rbs +6 -0
  44. data/sig/datadog/ci/configuration/extensions.rbs +9 -0
  45. data/sig/datadog/ci/ext/app_types.rbs +6 -1
  46. data/sig/datadog/ci/ext/environment/extractor.rbs +0 -2
  47. data/sig/datadog/ci/ext/environment/providers/github_actions.rbs +5 -0
  48. data/sig/datadog/ci/ext/settings.rbs +3 -0
  49. data/sig/datadog/ci/ext/test.rbs +15 -0
  50. data/sig/datadog/ci/null_span.rbs +37 -0
  51. data/sig/datadog/ci/span.rbs +39 -0
  52. data/sig/datadog/ci/test.rbs +7 -0
  53. data/sig/datadog/ci/test_module.rbs +6 -0
  54. data/sig/datadog/ci/test_session.rbs +9 -0
  55. data/sig/datadog/ci/test_suite.rbs +6 -0
  56. data/sig/datadog/ci/test_visibility/context/global.rbs +39 -0
  57. data/sig/datadog/ci/test_visibility/context/local.rbs +23 -0
  58. data/sig/datadog/ci/test_visibility/recorder.rbs +85 -0
  59. data/sig/datadog/ci/test_visibility/serializers/base.rbs +26 -5
  60. data/sig/datadog/ci/test_visibility/serializers/factories/test_suite_level.rbs +13 -0
  61. data/sig/datadog/ci/test_visibility/serializers/test_module.rbs +26 -0
  62. data/sig/datadog/ci/test_visibility/serializers/test_session.rbs +26 -0
  63. data/sig/datadog/ci/test_visibility/serializers/test_suite.rbs +26 -0
  64. data/sig/datadog/ci/test_visibility/serializers/test_v1.rbs +1 -1
  65. data/sig/datadog/ci/test_visibility/serializers/test_v2.rbs +25 -0
  66. data/sig/datadog/ci/test_visibility/transport.rbs +3 -3
  67. data/sig/datadog/ci/utils/test_run.rbs +11 -0
  68. data/sig/datadog/ci/utils/url.rbs +9 -0
  69. data/sig/datadog/ci.rbs +31 -3
  70. metadata +38 -6
  71. data/lib/datadog/ci/extensions.rb +0 -19
  72. data/lib/datadog/ci/recorder.rb +0 -83
  73. data/sig/datadog/ci/extensions.rbs +0 -7
  74. data/sig/datadog/ci/recorder.rbs +0 -18
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../../recorder"
4
3
  require_relative "../../ext/test"
5
4
  require_relative "ext"
6
5
 
@@ -19,41 +18,32 @@ module Datadog
19
18
  path, = method(name).source_location
20
19
  test_suite = Pathname.new(path.to_s).relative_path_from(Pathname.pwd).to_s
21
20
 
22
- span = CI::Recorder.trace(
23
- configuration[:operation_name],
24
- {
25
- span_options: {
26
- resource: test_name,
27
- service: configuration[:service_name]
28
- },
29
- framework: Ext::FRAMEWORK,
30
- framework_version: CI::Contrib::Minitest::Integration.version.to_s,
31
- test_name: test_name,
32
- test_suite: test_suite,
33
- test_type: Ext::TEST_TYPE
34
- }
21
+ CI.start_test(
22
+ test_name,
23
+ test_suite,
24
+ tags: {
25
+ CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
26
+ CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::Minitest::Integration.version.to_s,
27
+ CI::Ext::Test::TAG_TYPE => Ext::TEST_TYPE
28
+ },
29
+ service: configuration[:service_name]
35
30
  )
36
-
37
- Thread.current[:_datadog_test_span] = span
38
31
  end
39
32
 
40
33
  def after_teardown
41
- span = Thread.current[:_datadog_test_span]
42
- return super unless span
43
-
44
- Thread.current[:_datadog_test_span] = nil
34
+ test_span = CI.active_test
35
+ return super unless test_span
45
36
 
46
37
  case result_code
47
38
  when "."
48
- CI::Recorder.passed!(span)
39
+ test_span.passed!
49
40
  when "E", "F"
50
- CI::Recorder.failed!(span, failure)
41
+ test_span.failed!(exception: failure)
51
42
  when "S"
52
- CI::Recorder.skipped!(span)
53
- span.set_tag(CI::Ext::Test::TAG_SKIP_REASON, failure.message)
43
+ test_span.skipped!(reason: failure.message)
54
44
  end
55
45
 
56
- span.finish
46
+ test_span.finish
57
47
 
58
48
  super
59
49
  end
@@ -9,7 +9,7 @@ module Datadog
9
9
  module RSpec
10
10
  module Configuration
11
11
  # Custom settings for the RSpec integration
12
- # TODO: mark as `@public_api` when GA
12
+ # @public_api
13
13
  class Settings < Datadog::CI::Contrib::Settings
14
14
  option :enabled do |o|
15
15
  o.type :bool
@@ -22,10 +22,19 @@ module Datadog
22
22
  o.default { Datadog.configuration.service_without_fallback || Ext::SERVICE_NAME }
23
23
  end
24
24
 
25
+ # @deprecated Will be removed in 1.0
25
26
  option :operation_name do |o|
26
27
  o.type :string
27
28
  o.env Ext::ENV_OPERATION_NAME
28
29
  o.default Ext::OPERATION_NAME
30
+
31
+ o.after_set do |value|
32
+ if value && value != Ext::OPERATION_NAME
33
+ Datadog::Core.log_deprecation do
34
+ "The operation_name setting has no effect and will be removed in 1.0"
35
+ end
36
+ end
37
+ end
29
38
  end
30
39
  end
31
40
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../../recorder"
4
3
  require_relative "../../ext/test"
5
4
  require_relative "ext"
6
5
 
@@ -25,29 +24,25 @@ module Datadog
25
24
  test_name += " #{description}"
26
25
  end
27
26
 
28
- CI::Recorder.trace(
29
- configuration[:operation_name],
30
- {
31
- span_options: {
32
- resource: test_name,
33
- service: configuration[:service_name]
34
- },
35
- framework: Ext::FRAMEWORK,
36
- framework_version: CI::Contrib::RSpec::Integration.version.to_s,
37
- test_name: test_name,
38
- test_suite: metadata[:example_group][:file_path],
39
- test_type: Ext::TEST_TYPE
40
- }
41
- ) do |span|
27
+ CI.trace_test(
28
+ test_name,
29
+ metadata[:example_group][:file_path],
30
+ tags: {
31
+ CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
32
+ CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::RSpec::Integration.version.to_s,
33
+ CI::Ext::Test::TAG_TYPE => Ext::TEST_TYPE
34
+ },
35
+ service: configuration[:service_name]
36
+ ) do |test_span|
42
37
  result = super
43
38
 
44
39
  case execution_result.status
45
40
  when :passed
46
- CI::Recorder.passed!(span)
41
+ test_span.passed!
47
42
  when :failed
48
- CI::Recorder.failed!(span, execution_result.exception)
43
+ test_span.failed!(exception: execution_result.exception)
49
44
  else
50
- CI::Recorder.skipped!(span, execution_result.exception) if execution_result.example_skipped?
45
+ test_span.skipped!(exception: execution_result.exception) if execution_result.example_skipped?
51
46
  end
52
47
 
53
48
  result
@@ -10,6 +10,8 @@ module Datadog
10
10
 
11
11
  option :enabled, default: true
12
12
  option :service_name
13
+
14
+ # @deprecated Will be removed in 1.0
13
15
  option :operation_name
14
16
 
15
17
  def configure(options = {})
@@ -5,6 +5,11 @@ module Datadog
5
5
  module Ext
6
6
  module AppTypes
7
7
  TYPE_TEST = "test"
8
+ TYPE_TEST_SESSION = "test_session_end"
9
+ TYPE_TEST_MODULE = "test_module_end"
10
+ TYPE_TEST_SUITE = "test_suite_end"
11
+
12
+ CI_SPAN_TYPES = [TYPE_TEST, TYPE_TEST_SESSION, TYPE_TEST_MODULE, TYPE_TEST_SUITE].freeze
8
13
  end
9
14
  end
10
15
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "../git"
4
4
  require_relative "../../utils/git"
5
+ require_relative "../../utils/url"
5
6
  require_relative "providers"
6
7
 
7
8
  module Datadog
@@ -68,14 +69,14 @@ module Datadog
68
69
 
69
70
  def normalize_git!
70
71
  branch_ref = @tags[Git::TAG_BRANCH]
71
- if Datadog::CI::Utils::Git.is_git_tag?(branch_ref)
72
+ if Utils::Git.is_git_tag?(branch_ref)
72
73
  @tags[Git::TAG_TAG] = branch_ref
73
74
  @tags.delete(Git::TAG_BRANCH)
74
75
  end
75
76
 
76
- @tags[Git::TAG_TAG] = Datadog::CI::Utils::Git.normalize_ref(@tags[Git::TAG_TAG])
77
- @tags[Git::TAG_BRANCH] = Datadog::CI::Utils::Git.normalize_ref(@tags[Git::TAG_BRANCH])
78
- @tags[Git::TAG_REPOSITORY_URL] = filter_sensitive_info(
77
+ @tags[Git::TAG_TAG] = Utils::Git.normalize_ref(@tags[Git::TAG_TAG])
78
+ @tags[Git::TAG_BRANCH] = Utils::Git.normalize_ref(@tags[Git::TAG_BRANCH])
79
+ @tags[Git::TAG_REPOSITORY_URL] = Utils::Url.filter_sensitive_info(
79
80
  @tags[Git::TAG_REPOSITORY_URL]
80
81
  )
81
82
  end
@@ -87,12 +88,6 @@ module Datadog
87
88
  @tags[TAG_WORKSPACE_PATH] = File.expand_path(workspace_path)
88
89
  end
89
90
  end
90
-
91
- def filter_sensitive_info(url)
92
- return nil if url.nil?
93
-
94
- url.gsub(%r{(https?://)[^/]*@}, '\1')
95
- end
96
91
  end
97
92
  end
98
93
  end
@@ -3,6 +3,7 @@
3
3
  require "json"
4
4
 
5
5
  require_relative "base"
6
+ require_relative "../../../utils/url"
6
7
 
7
8
  module Datadog
8
9
  module CI
@@ -25,7 +26,7 @@ module Datadog
25
26
  end
26
27
 
27
28
  def job_url
28
- "#{env["GITHUB_SERVER_URL"]}/#{env["GITHUB_REPOSITORY"]}/commit/#{env["GITHUB_SHA"]}/checks"
29
+ "#{github_server_url}/#{env["GITHUB_REPOSITORY"]}/commit/#{env["GITHUB_SHA"]}/checks"
29
30
  end
30
31
 
31
32
  def pipeline_id
@@ -41,7 +42,7 @@ module Datadog
41
42
  end
42
43
 
43
44
  def pipeline_url
44
- res = "#{env["GITHUB_SERVER_URL"]}/#{env["GITHUB_REPOSITORY"]}/actions/runs/#{env["GITHUB_RUN_ID"]}"
45
+ res = "#{github_server_url}/#{env["GITHUB_REPOSITORY"]}/actions/runs/#{env["GITHUB_RUN_ID"]}"
45
46
  res = "#{res}/attempts/#{env["GITHUB_RUN_ATTEMPT"]}" if env["GITHUB_RUN_ATTEMPT"]
46
47
  res
47
48
  end
@@ -51,7 +52,7 @@ module Datadog
51
52
  end
52
53
 
53
54
  def git_repository_url
54
- "#{env["GITHUB_SERVER_URL"]}/#{env["GITHUB_REPOSITORY"]}.git"
55
+ "#{github_server_url}/#{env["GITHUB_REPOSITORY"]}.git"
55
56
  end
56
57
 
57
58
  def git_commit_sha
@@ -66,12 +67,20 @@ module Datadog
66
67
 
67
68
  def ci_env_vars
68
69
  {
69
- "GITHUB_SERVER_URL" => env["GITHUB_SERVER_URL"],
70
+ "GITHUB_SERVER_URL" => github_server_url,
70
71
  "GITHUB_REPOSITORY" => env["GITHUB_REPOSITORY"],
71
72
  "GITHUB_RUN_ID" => env["GITHUB_RUN_ID"],
72
73
  "GITHUB_RUN_ATTEMPT" => env["GITHUB_RUN_ATTEMPT"]
73
74
  }.reject { |_, v| v.nil? }.to_json
74
75
  end
76
+
77
+ private
78
+
79
+ def github_server_url
80
+ return @github_server_url if defined?(@github_server_url)
81
+
82
+ @github_server_url ||= Utils::Url.filter_sensitive_info(env["GITHUB_SERVER_URL"])
83
+ end
75
84
  end
76
85
  end
77
86
  end
@@ -8,6 +8,17 @@ module Datadog
8
8
  ENV_MODE_ENABLED = "DD_TRACE_CI_ENABLED"
9
9
  ENV_AGENTLESS_MODE_ENABLED = "DD_CIVISIBILITY_AGENTLESS_ENABLED"
10
10
  ENV_AGENTLESS_URL = "DD_CIVISIBILITY_AGENTLESS_URL"
11
+ ENV_EXPERIMENTAL_TEST_SUITE_LEVEL_VISIBILITY_ENABLED = "DD_CIVISIBILITY_EXPERIMENTAL_TEST_SUITE_LEVEL_VISIBILITY_ENABLED"
12
+
13
+ # Source: https://docs.datadoghq.com/getting_started/site/
14
+ DD_SITE_ALLOWLIST = [
15
+ "datadoghq.com",
16
+ "us3.datadoghq.com",
17
+ "us5.datadoghq.com",
18
+ "datadoghq.eu",
19
+ "ddog-gov.com",
20
+ "ap1.datadoghq.com"
21
+ ].freeze
11
22
  end
12
23
  end
13
24
  end
@@ -4,6 +4,7 @@ module Datadog
4
4
  module CI
5
5
  module Ext
6
6
  # Defines constants for test tags
7
+ # @public_api
7
8
  module Test
8
9
  CONTEXT_ORIGIN = "ciapp-test"
9
10
 
@@ -14,8 +15,19 @@ module Datadog
14
15
  TAG_SKIP_REASON = "test.skip_reason" # DEV: Not populated yet
15
16
  TAG_STATUS = "test.status"
16
17
  TAG_SUITE = "test.suite"
18
+ TAG_MODULE = "test.module"
17
19
  TAG_TRAITS = "test.traits"
18
20
  TAG_TYPE = "test.type"
21
+ TAG_COMMAND = "test.command"
22
+
23
+ # those tags are special and they are used to correlate tests with the test sessions, suites, and modules
24
+ TAG_TEST_SESSION_ID = "_test.session_id"
25
+ TAG_TEST_MODULE_ID = "_test.module_id"
26
+ TAG_TEST_SUITE_ID = "_test.suite_id"
27
+ SPECIAL_TAGS = [TAG_TEST_SESSION_ID, TAG_TEST_MODULE_ID, TAG_TEST_SUITE_ID].freeze
28
+
29
+ # tags that can be inherited from the test session
30
+ INHERITABLE_TAGS = [TAG_FRAMEWORK, TAG_FRAMEWORK_VERSION, TAG_TYPE].freeze
19
31
 
20
32
  # Environment runtime tags
21
33
  TAG_OS_ARCHITECTURE = "os.architecture"
@@ -23,7 +35,6 @@ module Datadog
23
35
  TAG_RUNTIME_NAME = "runtime.name"
24
36
  TAG_RUNTIME_VERSION = "runtime.version"
25
37
 
26
- # TODO: is there a better place for SPAN_KIND?
27
38
  TAG_SPAN_KIND = "span.kind"
28
39
 
29
40
  module Status
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "datadog/tracing/span_operation"
4
+
5
+ module Datadog
6
+ module CI
7
+ # Represents an ignored span when CI visibility is disabled.
8
+ # Replaces all methods with no-op.
9
+ #
10
+ # @public_api
11
+ class NullSpan < Span
12
+ def initialize
13
+ super(Datadog::Tracing::SpanOperation.new("null.span"))
14
+ end
15
+
16
+ def id
17
+ end
18
+
19
+ def name
20
+ end
21
+
22
+ def service
23
+ end
24
+
25
+ def span_type
26
+ end
27
+
28
+ def passed!
29
+ end
30
+
31
+ def failed!(exception: nil)
32
+ end
33
+
34
+ def skipped!(exception: nil, reason: nil)
35
+ end
36
+
37
+ def get_tag(key)
38
+ end
39
+
40
+ def set_tag(key, value)
41
+ end
42
+
43
+ def set_metric(key, value)
44
+ end
45
+
46
+ def finish
47
+ end
48
+
49
+ def set_tags(tags)
50
+ end
51
+
52
+ def set_environment_runtime_tags
53
+ end
54
+
55
+ def set_default_tags
56
+ end
57
+
58
+ def to_s
59
+ self.class.to_s
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "ext/test"
4
+ require_relative "utils/test_run"
5
+
6
+ module Datadog
7
+ module CI
8
+ # Represents a single part of a test run.
9
+ # Could be a session, suite, test, or any custom span.
10
+ #
11
+ # @public_api
12
+ class Span
13
+ attr_reader :tracer_span
14
+
15
+ def initialize(tracer_span)
16
+ @tracer_span = tracer_span
17
+ end
18
+
19
+ # @return [Integer] the ID of the span.
20
+ def id
21
+ tracer_span.id
22
+ end
23
+
24
+ # @return [String] the name of the span.
25
+ def name
26
+ tracer_span.name
27
+ end
28
+
29
+ # @return [String] the service name of the span.
30
+ def service
31
+ tracer_span.service
32
+ end
33
+
34
+ # @return [String] the type of the span (for example "test" or type that was provided to [Datadog::CI.trace]).
35
+ def span_type
36
+ tracer_span.type
37
+ end
38
+
39
+ # Sets the status of the span to "pass".
40
+ # @return [void]
41
+ def passed!
42
+ tracer_span.set_tag(Ext::Test::TAG_STATUS, Ext::Test::Status::PASS)
43
+ end
44
+
45
+ # Sets the status of the span to "fail".
46
+ # @param [Exception] exception the exception that caused the test to fail.
47
+ # @return [void]
48
+ def failed!(exception: nil)
49
+ tracer_span.status = 1
50
+ tracer_span.set_tag(Ext::Test::TAG_STATUS, Ext::Test::Status::FAIL)
51
+ tracer_span.set_error(exception) unless exception.nil?
52
+ end
53
+
54
+ # Sets the status of the span to "skip".
55
+ # @param [Exception] exception the exception that caused the test to fail.
56
+ # @param [String] reason the reason why the test was skipped.
57
+ # @return [void]
58
+ def skipped!(exception: nil, reason: nil)
59
+ tracer_span.set_tag(Ext::Test::TAG_STATUS, Ext::Test::Status::SKIP)
60
+ tracer_span.set_error(exception) unless exception.nil?
61
+ tracer_span.set_tag(Ext::Test::TAG_SKIP_REASON, reason) unless reason.nil?
62
+ end
63
+
64
+ # Gets tag value by key.
65
+ # @param [String] key the key of the tag.
66
+ # @return [String] the value of the tag.
67
+ def get_tag(key)
68
+ tracer_span.get_tag(key)
69
+ end
70
+
71
+ # Sets tag value by key.
72
+ # @param [String] key the key of the tag.
73
+ # @param [String] value the value of the tag.
74
+ # @return [void]
75
+ def set_tag(key, value)
76
+ tracer_span.set_tag(key, value)
77
+ end
78
+
79
+ # Sets metric value by key.
80
+ # @param [String] key the key of the metric.
81
+ # @param [Numeric] value the value of the metric.
82
+ # @return [void]
83
+ def set_metric(key, value)
84
+ tracer_span.set_metric(key, value)
85
+ end
86
+
87
+ # Finishes the span.
88
+ # @return [void]
89
+ def finish
90
+ tracer_span.finish
91
+ end
92
+
93
+ # Sets multiple tags at once.
94
+ # @param [Hash[String, String]] tags the tags to set.
95
+ # @return [void]
96
+ def set_tags(tags)
97
+ tracer_span.set_tags(tags)
98
+ end
99
+
100
+ def set_environment_runtime_tags
101
+ tracer_span.set_tag(Ext::Test::TAG_OS_ARCHITECTURE, ::RbConfig::CONFIG["host_cpu"])
102
+ tracer_span.set_tag(Ext::Test::TAG_OS_PLATFORM, ::RbConfig::CONFIG["host_os"])
103
+ tracer_span.set_tag(Ext::Test::TAG_RUNTIME_NAME, Core::Environment::Ext::LANG_ENGINE)
104
+ tracer_span.set_tag(Ext::Test::TAG_RUNTIME_VERSION, Core::Environment::Ext::ENGINE_VERSION)
105
+ tracer_span.set_tag(Ext::Test::TAG_COMMAND, Utils::TestRun.command)
106
+ end
107
+
108
+ def set_default_tags
109
+ tracer_span.set_tag(Ext::Test::TAG_SPAN_KIND, Ext::AppTypes::TYPE_TEST)
110
+ end
111
+
112
+ def to_s
113
+ "#{self.class}(name:#{name},tracer_span:#{@tracer_span})"
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "span"
4
+
5
+ module Datadog
6
+ module CI
7
+ # Represents a single part of a test run.
8
+ #
9
+ # @public_api
10
+ class Test < Span
11
+ # @return [String] the name of the test.
12
+ def name
13
+ get_tag(Ext::Test::TAG_NAME)
14
+ end
15
+
16
+ # Finishes the current test.
17
+ # @return [void]
18
+ def finish
19
+ super
20
+
21
+ CI.deactivate_test(self)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "concurrent_span"
4
+
5
+ module Datadog
6
+ module CI
7
+ # Represents a single test module.
8
+ # Read here on what test module could mean:
9
+ # https://docs.datadoghq.com/continuous_integration/explorer/?tab=testruns#module
10
+ # This object can be shared between multiple threads.
11
+ #
12
+ # @public_api
13
+ class TestModule < ConcurrentSpan
14
+ # Finishes this test module.
15
+ # @return [void]
16
+ def finish
17
+ super
18
+
19
+ CI.deactivate_test_module
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "concurrent_span"
4
+ require_relative "ext/test"
5
+
6
+ module Datadog
7
+ module CI
8
+ # Represents the whole test session process.
9
+ # Documentation on test sessions is here:
10
+ # https://docs.datadoghq.com/continuous_integration/explorer/?tab=testruns#sessions
11
+ # This object can be shared between multiple threads.
12
+ #
13
+ # @public_api
14
+ class TestSession < ConcurrentSpan
15
+ # Finishes the current test session.
16
+ # @return [void]
17
+ def finish
18
+ super
19
+
20
+ CI.deactivate_test_session
21
+ end
22
+
23
+ def inheritable_tags
24
+ return @inheritable_tags if defined?(@inheritable_tags)
25
+
26
+ # this method is not synchronized because it does not iterate over the tags collection, but rather
27
+ # uses synchronized method to get each tag value
28
+ res = {}
29
+ Ext::Test::INHERITABLE_TAGS.each do |tag|
30
+ res[tag] = get_tag(tag)
31
+ end
32
+ @inheritable_tags = res.freeze
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "concurrent_span"
4
+
5
+ module Datadog
6
+ module CI
7
+ # Represents a single test suite.
8
+ #
9
+ # Read here on what test suite means:
10
+ # https://docs.datadoghq.com/continuous_integration/explorer/?tab=testruns#suite
11
+ #
12
+ # This object can be shared between multiple threads.
13
+ #
14
+ # @public_api
15
+ class TestSuite < ConcurrentSpan
16
+ # Finishes this test suite.
17
+ # @return [void]
18
+ def finish
19
+ super
20
+
21
+ CI.deactivate_test_suite(name)
22
+ end
23
+ end
24
+ end
25
+ end