datadog-ci 0.5.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +60 -1
  3. data/README.md +1 -1
  4. data/lib/datadog/ci/codeowners/matcher.rb +102 -0
  5. data/lib/datadog/ci/codeowners/parser.rb +42 -0
  6. data/lib/datadog/ci/codeowners/rule.rb +33 -0
  7. data/lib/datadog/ci/concurrent_span.rb +2 -1
  8. data/lib/datadog/ci/configuration/components.rb +15 -11
  9. data/lib/datadog/ci/configuration/settings.rb +15 -0
  10. data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +4 -1
  11. data/lib/datadog/ci/contrib/cucumber/ext.rb +7 -5
  12. data/lib/datadog/ci/contrib/cucumber/formatter.rb +138 -27
  13. data/lib/datadog/ci/contrib/cucumber/instrumentation.rb +2 -1
  14. data/lib/datadog/ci/contrib/minitest/configuration/settings.rb +4 -1
  15. data/lib/datadog/ci/contrib/minitest/ext.rb +6 -4
  16. data/lib/datadog/ci/contrib/minitest/helpers.rb +23 -0
  17. data/lib/datadog/ci/contrib/minitest/hooks.rb +34 -19
  18. data/lib/datadog/ci/contrib/minitest/patcher.rb +10 -0
  19. data/lib/datadog/ci/contrib/minitest/reporter.rb +50 -0
  20. data/lib/datadog/ci/contrib/minitest/runnable.rb +42 -0
  21. data/lib/datadog/ci/contrib/minitest/runner.rb +41 -0
  22. data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +4 -1
  23. data/lib/datadog/ci/contrib/rspec/example.rb +55 -14
  24. data/lib/datadog/ci/contrib/rspec/example_group.rb +51 -0
  25. data/lib/datadog/ci/contrib/rspec/ext.rb +5 -4
  26. data/lib/datadog/ci/contrib/rspec/integration.rb +1 -1
  27. data/lib/datadog/ci/contrib/rspec/patcher.rb +14 -0
  28. data/lib/datadog/ci/contrib/rspec/runner.rb +57 -0
  29. data/lib/datadog/ci/contrib/settings.rb +1 -1
  30. data/lib/datadog/ci/ext/app_types.rb +2 -0
  31. data/lib/datadog/ci/ext/environment/providers/local_git.rb +8 -29
  32. data/lib/datadog/ci/ext/settings.rb +1 -0
  33. data/lib/datadog/ci/ext/test.rb +19 -6
  34. data/lib/datadog/ci/span.rb +33 -2
  35. data/lib/datadog/ci/test.rb +96 -1
  36. data/lib/datadog/ci/test_module.rb +1 -1
  37. data/lib/datadog/ci/test_session.rb +10 -2
  38. data/lib/datadog/ci/test_suite.rb +53 -2
  39. data/lib/datadog/ci/test_visibility/context/local.rb +3 -9
  40. data/lib/datadog/ci/test_visibility/null_recorder.rb +53 -0
  41. data/lib/datadog/ci/test_visibility/recorder.rb +52 -25
  42. data/lib/datadog/ci/test_visibility/serializers/base.rb +6 -5
  43. data/lib/datadog/ci/test_visibility/serializers/span.rb +1 -1
  44. data/lib/datadog/ci/test_visibility/serializers/test_module.rb +1 -1
  45. data/lib/datadog/ci/test_visibility/serializers/test_session.rb +1 -1
  46. data/lib/datadog/ci/test_visibility/serializers/test_suite.rb +1 -1
  47. data/lib/datadog/ci/test_visibility/serializers/test_v1.rb +1 -1
  48. data/lib/datadog/ci/utils/configuration.rb +15 -0
  49. data/lib/datadog/ci/utils/git.rb +70 -0
  50. data/lib/datadog/ci/version.rb +2 -2
  51. data/lib/datadog/ci.rb +40 -56
  52. metadata +14 -82
  53. data/lib/datadog/ci/null_span.rb +0 -63
  54. data/sig/datadog/ci/concurrent_span.rbs +0 -23
  55. data/sig/datadog/ci/configuration/components.rbs +0 -21
  56. data/sig/datadog/ci/configuration/extensions.rbs +0 -9
  57. data/sig/datadog/ci/configuration/settings.rbs +0 -16
  58. data/sig/datadog/ci/contrib/cucumber/configuration/settings.rbs +0 -12
  59. data/sig/datadog/ci/contrib/cucumber/ext.rbs +0 -25
  60. data/sig/datadog/ci/contrib/cucumber/formatter.rbs +0 -35
  61. data/sig/datadog/ci/contrib/cucumber/instrumentation.rbs +0 -16
  62. data/sig/datadog/ci/contrib/cucumber/integration.rbs +0 -26
  63. data/sig/datadog/ci/contrib/cucumber/patcher.rbs +0 -15
  64. data/sig/datadog/ci/contrib/integration.rbs +0 -44
  65. data/sig/datadog/ci/contrib/minitest/configuration/settings.rbs +0 -12
  66. data/sig/datadog/ci/contrib/minitest/ext.rbs +0 -23
  67. data/sig/datadog/ci/contrib/minitest/hooks.rbs +0 -19
  68. data/sig/datadog/ci/contrib/minitest/integration.rbs +0 -26
  69. data/sig/datadog/ci/contrib/minitest/patcher.rbs +0 -15
  70. data/sig/datadog/ci/contrib/rspec/configuration/settings.rbs +0 -12
  71. data/sig/datadog/ci/contrib/rspec/example.rbs +0 -20
  72. data/sig/datadog/ci/contrib/rspec/ext.rbs +0 -23
  73. data/sig/datadog/ci/contrib/rspec/integration.rbs +0 -26
  74. data/sig/datadog/ci/contrib/rspec/patcher.rbs +0 -15
  75. data/sig/datadog/ci/contrib/settings.rbs +0 -25
  76. data/sig/datadog/ci/ext/app_types.rbs +0 -14
  77. data/sig/datadog/ci/ext/environment/extractor.rbs +0 -25
  78. data/sig/datadog/ci/ext/environment/providers/appveyor.rbs +0 -48
  79. data/sig/datadog/ci/ext/environment/providers/aws_code_pipeline.rbs +0 -19
  80. data/sig/datadog/ci/ext/environment/providers/azure.rbs +0 -56
  81. data/sig/datadog/ci/ext/environment/providers/base.rbs +0 -71
  82. data/sig/datadog/ci/ext/environment/providers/bitbucket.rbs +0 -37
  83. data/sig/datadog/ci/ext/environment/providers/bitrise.rbs +0 -41
  84. data/sig/datadog/ci/ext/environment/providers/buddy.rbs +0 -37
  85. data/sig/datadog/ci/ext/environment/providers/buildkite.rbs +0 -45
  86. data/sig/datadog/ci/ext/environment/providers/circleci.rbs +0 -41
  87. data/sig/datadog/ci/ext/environment/providers/codefresh.rbs +0 -25
  88. data/sig/datadog/ci/ext/environment/providers/github_actions.rbs +0 -42
  89. data/sig/datadog/ci/ext/environment/providers/gitlab.rbs +0 -57
  90. data/sig/datadog/ci/ext/environment/providers/jenkins.rbs +0 -35
  91. data/sig/datadog/ci/ext/environment/providers/local_git.rbs +0 -66
  92. data/sig/datadog/ci/ext/environment/providers/teamcity.rbs +0 -17
  93. data/sig/datadog/ci/ext/environment/providers/travis.rbs +0 -35
  94. data/sig/datadog/ci/ext/environment/providers/user_defined_tags.rbs +0 -33
  95. data/sig/datadog/ci/ext/environment/providers.rbs +0 -13
  96. data/sig/datadog/ci/ext/environment.rbs +0 -44
  97. data/sig/datadog/ci/ext/git.rbs +0 -53
  98. data/sig/datadog/ci/ext/settings.rbs +0 -14
  99. data/sig/datadog/ci/ext/test.rbs +0 -58
  100. data/sig/datadog/ci/ext/transport.rbs +0 -29
  101. data/sig/datadog/ci/null_span.rbs +0 -37
  102. data/sig/datadog/ci/span.rbs +0 -39
  103. data/sig/datadog/ci/test.rbs +0 -7
  104. data/sig/datadog/ci/test_module.rbs +0 -6
  105. data/sig/datadog/ci/test_session.rbs +0 -9
  106. data/sig/datadog/ci/test_suite.rbs +0 -6
  107. data/sig/datadog/ci/test_visibility/context/global.rbs +0 -39
  108. data/sig/datadog/ci/test_visibility/context/local.rbs +0 -23
  109. data/sig/datadog/ci/test_visibility/flush.rbs +0 -17
  110. data/sig/datadog/ci/test_visibility/recorder.rbs +0 -85
  111. data/sig/datadog/ci/test_visibility/serializers/base.rbs +0 -94
  112. data/sig/datadog/ci/test_visibility/serializers/factories/test_level.rbs +0 -13
  113. data/sig/datadog/ci/test_visibility/serializers/factories/test_suite_level.rbs +0 -13
  114. data/sig/datadog/ci/test_visibility/serializers/span.rbs +0 -18
  115. data/sig/datadog/ci/test_visibility/serializers/test_module.rbs +0 -26
  116. data/sig/datadog/ci/test_visibility/serializers/test_session.rbs +0 -26
  117. data/sig/datadog/ci/test_visibility/serializers/test_suite.rbs +0 -26
  118. data/sig/datadog/ci/test_visibility/serializers/test_v1.rbs +0 -23
  119. data/sig/datadog/ci/test_visibility/serializers/test_v2.rbs +0 -25
  120. data/sig/datadog/ci/test_visibility/transport.rbs +0 -35
  121. data/sig/datadog/ci/transport/api/base.rbs +0 -21
  122. data/sig/datadog/ci/transport/api/builder.rbs +0 -12
  123. data/sig/datadog/ci/transport/api/ci_test_cycle.rbs +0 -21
  124. data/sig/datadog/ci/transport/api/evp_proxy.rbs +0 -19
  125. data/sig/datadog/ci/transport/gzip.rbs +0 -9
  126. data/sig/datadog/ci/transport/http.rbs +0 -36
  127. data/sig/datadog/ci/utils/git.rbs +0 -11
  128. data/sig/datadog/ci/utils/test_run.rbs +0 -11
  129. data/sig/datadog/ci/utils/url.rbs +0 -9
  130. data/sig/datadog/ci/version.rbs +0 -16
  131. data/sig/datadog/ci.rbs +0 -35
@@ -7,13 +7,15 @@ module Datadog
7
7
  # Minitest integration constants
8
8
  # TODO: mark as `@public_api` when GA, to protect from resource and tag name changes.
9
9
  module Ext
10
- APP = "minitest"
11
10
  ENV_ENABLED = "DD_TRACE_MINITEST_ENABLED"
12
- ENV_OPERATION_NAME = "DD_TRACE_MINITEST_OPERATION_NAME"
11
+
13
12
  FRAMEWORK = "minitest"
13
+
14
+ DEFAULT_SERVICE_NAME = "minitest"
15
+
16
+ # TODO: remove in 1.0
17
+ ENV_OPERATION_NAME = "DD_TRACE_MINITEST_OPERATION_NAME"
14
18
  OPERATION_NAME = "minitest.test"
15
- SERVICE_NAME = "minitest"
16
- TEST_TYPE = "test"
17
19
  end
18
20
  end
19
21
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module CI
5
+ module Contrib
6
+ module Minitest
7
+ module Helpers
8
+ def self.test_suite_name(klass, method_name)
9
+ source_location, = klass.instance_method(method_name).source_location
10
+ source_file_path = Pathname.new(source_location.to_s).relative_path_from(Pathname.pwd).to_s
11
+
12
+ "#{klass.name} at #{source_file_path}"
13
+ end
14
+
15
+ def self.parallel?(klass)
16
+ klass.ancestors.include?(::Minitest::Parallel::Test) ||
17
+ (defined?(::Minitest::Queue) && ::Minitest.singleton_class.ancestors.include?(::Minitest::Queue))
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ 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
@@ -11,22 +12,28 @@ module Datadog
11
12
  module Hooks
12
13
  def before_setup
13
14
  super
14
- return unless configuration[:enabled]
15
+ return unless datadog_configuration[:enabled]
15
16
 
16
- test_name = "#{class_name}##{name}"
17
+ test_suite_name = Helpers.test_suite_name(self.class, name)
18
+ if Helpers.parallel?(self.class)
19
+ test_suite_name = "#{test_suite_name} (#{name} concurrently)"
17
20
 
18
- path, = method(name).source_location
19
- test_suite = Pathname.new(path.to_s).relative_path_from(Pathname.pwd).to_s
21
+ # for parallel execution we need to start a new test suite for each test
22
+ CI.start_test_suite(test_suite_name)
23
+ end
24
+
25
+ source_file, line_number = method(name).source_location
20
26
 
21
27
  CI.start_test(
22
- test_name,
23
- test_suite,
28
+ name,
29
+ test_suite_name,
24
30
  tags: {
25
31
  CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
26
32
  CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::Minitest::Integration.version.to_s,
27
- CI::Ext::Test::TAG_TYPE => Ext::TEST_TYPE
33
+ CI::Ext::Test::TAG_SOURCE_FILE => Utils::Git.relative_to_root(source_file),
34
+ CI::Ext::Test::TAG_SOURCE_START => line_number.to_s
28
35
  },
29
- service: configuration[:service_name]
36
+ service: datadog_configuration[:service_name]
30
37
  )
31
38
  end
32
39
 
@@ -34,24 +41,32 @@ module Datadog
34
41
  test_span = CI.active_test
35
42
  return super unless test_span
36
43
 
37
- case result_code
38
- when "."
39
- test_span.passed!
40
- when "E", "F"
41
- test_span.failed!(exception: failure)
42
- when "S"
43
- test_span.skipped!(reason: failure.message)
44
+ finish_with_result(test_span, result_code)
45
+ if Helpers.parallel?(self.class)
46
+ finish_with_result(test_span.test_suite, result_code)
44
47
  end
45
48
 
46
- test_span.finish
47
-
48
49
  super
49
50
  end
50
51
 
51
52
  private
52
53
 
53
- def configuration
54
- ::Datadog.configuration.ci[:minitest]
54
+ def finish_with_result(span, result_code)
55
+ return unless span
56
+
57
+ case result_code
58
+ when "."
59
+ span.passed!
60
+ when "E", "F"
61
+ span.failed!(exception: failure)
62
+ when "S"
63
+ span.skipped!(reason: failure.message)
64
+ end
65
+ span.finish
66
+ end
67
+
68
+ def datadog_configuration
69
+ Datadog.configuration.ci[:minitest]
55
70
  end
56
71
  end
57
72
  end
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "runner"
4
+ require_relative "reporter"
3
5
  require_relative "hooks"
6
+ require_relative "runnable"
4
7
 
5
8
  module Datadog
6
9
  module CI
@@ -17,7 +20,14 @@ module Datadog
17
20
  end
18
21
 
19
22
  def patch
23
+ # test session start
24
+ ::Minitest.include(Runner)
25
+ # test suites (when not executed concurrently)
26
+ ::Minitest::Runnable.include(Runnable)
27
+ # tests; test suites (when executed concurrently)
20
28
  ::Minitest::Test.include(Hooks)
29
+ # test session finish
30
+ ::Minitest::CompositeReporter.include(Reporter)
21
31
  end
22
32
  end
23
33
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../ext/test"
4
+ require_relative "ext"
5
+
6
+ module Datadog
7
+ module CI
8
+ module Contrib
9
+ module Minitest
10
+ module Reporter
11
+ def self.included(base)
12
+ base.prepend(InstanceMethods)
13
+ end
14
+
15
+ module InstanceMethods
16
+ def report(*)
17
+ return super unless datadog_configuration[:enabled]
18
+
19
+ res = super
20
+
21
+ active_test_session = CI.active_test_session
22
+ active_test_module = CI.active_test_module
23
+
24
+ return res if active_test_session.nil? || active_test_module.nil?
25
+
26
+ if passed?
27
+ active_test_module.passed!
28
+ active_test_session.passed!
29
+ else
30
+ active_test_module.failed!
31
+ active_test_session.failed!
32
+ end
33
+
34
+ active_test_module.finish
35
+ active_test_session.finish
36
+
37
+ res
38
+ end
39
+
40
+ private
41
+
42
+ def datadog_configuration
43
+ Datadog.configuration.ci[:minitest]
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,42 @@
1
+ require_relative "helpers"
2
+
3
+ module Datadog
4
+ module CI
5
+ module Contrib
6
+ module Minitest
7
+ module Runnable
8
+ def self.included(base)
9
+ base.singleton_class.prepend(ClassMethods)
10
+ end
11
+
12
+ module ClassMethods
13
+ def run(*)
14
+ return super unless datadog_configuration[:enabled]
15
+ return super if Helpers.parallel?(self)
16
+
17
+ method = runnable_methods.first
18
+ return super if method.nil?
19
+
20
+ test_suite_name = Helpers.test_suite_name(self, method)
21
+
22
+ test_suite = Datadog::CI.start_test_suite(test_suite_name)
23
+
24
+ results = super
25
+ return results unless test_suite
26
+
27
+ test_suite.finish
28
+
29
+ results
30
+ end
31
+
32
+ private
33
+
34
+ def datadog_configuration
35
+ Datadog.configuration.ci[:minitest]
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../ext/test"
4
+ require_relative "ext"
5
+
6
+ module Datadog
7
+ module CI
8
+ module Contrib
9
+ module Minitest
10
+ module Runner
11
+ def self.included(base)
12
+ base.singleton_class.prepend(ClassMethods)
13
+ end
14
+
15
+ module ClassMethods
16
+ def init_plugins(*)
17
+ super
18
+
19
+ return unless datadog_configuration[:enabled]
20
+
21
+ test_session = CI.start_test_session(
22
+ tags: {
23
+ CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
24
+ CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::Minitest::Integration.version.to_s
25
+ },
26
+ service: datadog_configuration[:service_name]
27
+ )
28
+ CI.start_test_module(test_session.name) if test_session
29
+ end
30
+
31
+ private
32
+
33
+ def datadog_configuration
34
+ Datadog.configuration.ci[:minitest]
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "../ext"
4
4
  require_relative "../../settings"
5
+ require_relative "../../../utils/configuration"
5
6
 
6
7
  module Datadog
7
8
  module CI
@@ -19,7 +20,9 @@ module Datadog
19
20
 
20
21
  option :service_name do |o|
21
22
  o.type :string
22
- o.default { Datadog.configuration.service_without_fallback || Ext::SERVICE_NAME }
23
+ o.default do
24
+ Utils::Configuration.fetch_service_name(Ext::DEFAULT_SERVICE_NAME)
25
+ end
23
26
  end
24
27
 
25
28
  # @deprecated Will be removed in 1.0
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "../../ext/test"
4
+ require_relative "../../utils/git"
4
5
  require_relative "ext"
5
6
 
6
7
  module Datadog
@@ -13,10 +14,9 @@ module Datadog
13
14
  base.prepend(InstanceMethods)
14
15
  end
15
16
 
16
- # Instance methods for configuration
17
17
  module InstanceMethods
18
- def run(example_group_instance, reporter)
19
- return super unless configuration[:enabled]
18
+ def run(*)
19
+ return super unless datadog_configuration[:enabled]
20
20
 
21
21
  test_name = full_description.strip
22
22
  if metadata[:description].empty?
@@ -24,36 +24,77 @@ module Datadog
24
24
  test_name += " #{description}"
25
25
  end
26
26
 
27
+ test_suite_description = fetch_top_level_example_group[:description]
28
+ suite_name = "#{test_suite_description} at #{metadata[:example_group][:rerun_file_path]}"
29
+
30
+ # remove example group description from test name to avoid duplication
31
+ test_name = test_name.sub(test_suite_description, "").strip
32
+
33
+ if ci_queue?
34
+ suite_name += " (ci-queue running example [#{test_name}])"
35
+ test_suite_span = CI.start_test_suite(suite_name)
36
+ end
37
+
27
38
  CI.trace_test(
28
39
  test_name,
29
- metadata[:example_group][:file_path],
40
+ suite_name,
30
41
  tags: {
31
42
  CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
32
43
  CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::RSpec::Integration.version.to_s,
33
- CI::Ext::Test::TAG_TYPE => Ext::TEST_TYPE
44
+ CI::Ext::Test::TAG_SOURCE_FILE => Utils::Git.relative_to_root(metadata[:file_path]),
45
+ CI::Ext::Test::TAG_SOURCE_START => metadata[:line_number].to_s
34
46
  },
35
- service: configuration[:service_name]
47
+ service: datadog_configuration[:service_name]
36
48
  ) do |test_span|
37
49
  result = super
38
50
 
39
- case execution_result.status
40
- when :passed
41
- test_span.passed!
42
- when :failed
43
- test_span.failed!(exception: execution_result.exception)
44
- else
45
- test_span.skipped!(exception: execution_result.exception) if execution_result.example_skipped?
51
+ if test_span
52
+ test_span.set_parameters({}, {"scoped_id" => metadata[:scoped_id]})
53
+
54
+ case execution_result.status
55
+ when :passed
56
+ test_span.passed!
57
+ test_suite_span.passed! if test_suite_span
58
+ when :failed
59
+ test_span.failed!(exception: execution_result.exception)
60
+ test_suite_span.failed! if test_suite_span
61
+ else
62
+ # :pending or nil
63
+ test_span.skipped!(
64
+ reason: execution_result.pending_message,
65
+ exception: execution_result.pending_exception
66
+ )
67
+
68
+ test_suite_span.skipped! if test_suite_span
69
+ end
46
70
  end
47
71
 
72
+ test_suite_span.finish if test_suite_span
73
+
48
74
  result
49
75
  end
50
76
  end
51
77
 
52
78
  private
53
79
 
54
- def configuration
80
+ def fetch_top_level_example_group
81
+ return metadata[:example_group] unless metadata[:example_group][:parent_example_group]
82
+
83
+ res = metadata[:example_group][:parent_example_group]
84
+ while (parent = res[:parent_example_group])
85
+ res = parent
86
+ end
87
+ res
88
+ end
89
+
90
+ def datadog_configuration
55
91
  Datadog.configuration.ci[:rspec]
56
92
  end
93
+
94
+ def ci_queue?
95
+ defined?(::RSpec::Queue::ExampleExtension) &&
96
+ self.class.ancestors.include?(::RSpec::Queue::ExampleExtension)
97
+ end
57
98
  end
58
99
  end
59
100
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../ext/test"
4
+ require_relative "ext"
5
+
6
+ module Datadog
7
+ module CI
8
+ module Contrib
9
+ module RSpec
10
+ # Instrument RSpec::Core::ExampleGroup
11
+ module ExampleGroup
12
+ def self.included(base)
13
+ base.singleton_class.prepend(ClassMethods)
14
+ end
15
+
16
+ # Instance methods for configuration
17
+ module ClassMethods
18
+ def run(reporter = ::RSpec::Core::NullReporter)
19
+ return super unless datadog_configuration[:enabled]
20
+ return super unless top_level?
21
+
22
+ suite_name = "#{description} at #{file_path}"
23
+ test_suite = Datadog::CI.start_test_suite(suite_name)
24
+
25
+ success = super
26
+ return success unless test_suite
27
+
28
+ if success && test_suite.passed_tests_count > 0
29
+ test_suite.passed!
30
+ elsif success
31
+ test_suite.skipped!
32
+ else
33
+ test_suite.failed!
34
+ end
35
+
36
+ test_suite.finish
37
+
38
+ success
39
+ end
40
+
41
+ private
42
+
43
+ def datadog_configuration
44
+ Datadog.configuration.ci[:rspec]
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -7,13 +7,14 @@ module Datadog
7
7
  # RSpec integration constants
8
8
  # TODO: mark as `@public_api` when GA, to protect from resource and tag name changes.
9
9
  module Ext
10
- APP = "rspec"
10
+ FRAMEWORK = "rspec"
11
+ DEFAULT_SERVICE_NAME = "rspec"
12
+
11
13
  ENV_ENABLED = "DD_TRACE_RSPEC_ENABLED"
14
+
15
+ # TODO: remove in 1.0
12
16
  ENV_OPERATION_NAME = "DD_TRACE_RSPEC_OPERATION_NAME"
13
- FRAMEWORK = "rspec"
14
17
  OPERATION_NAME = "rspec.example"
15
- SERVICE_NAME = "rspec"
16
- TEST_TYPE = "test"
17
18
  end
18
19
  end
19
20
  end
@@ -22,7 +22,7 @@ module Datadog
22
22
  end
23
23
 
24
24
  def self.loaded?
25
- !defined?(::RSpec).nil? && !defined?(::RSpec::Core).nil? && \
25
+ !defined?(::RSpec).nil? && !defined?(::RSpec::Core).nil? &&
26
26
  !defined?(::RSpec::Core::Example).nil?
27
27
  end
28
28
 
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "datadog/tracing/contrib/patcher"
4
+
4
5
  require_relative "example"
6
+ require_relative "example_group"
7
+ require_relative "runner"
5
8
 
6
9
  module Datadog
7
10
  module CI
@@ -18,7 +21,18 @@ module Datadog
18
21
  end
19
22
 
20
23
  def patch
24
+ if ci_queue?
25
+ ::RSpec::Queue::Runner.include(Runner)
26
+ end
27
+
28
+ ::RSpec::Core::Runner.include(Runner)
21
29
  ::RSpec::Core::Example.include(Example)
30
+ ::RSpec::Core::ExampleGroup.include(ExampleGroup)
31
+ end
32
+
33
+ def ci_queue?
34
+ # ::RSpec::Queue::Runner is a ci-queue runner
35
+ defined?(::RSpec::Queue::Runner)
22
36
  end
23
37
  end
24
38
  end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../ext/test"
4
+ require_relative "ext"
5
+
6
+ module Datadog
7
+ module CI
8
+ module Contrib
9
+ module RSpec
10
+ # Instrument RSpec::Core::Runner
11
+ module Runner
12
+ def self.included(base)
13
+ base.prepend(InstanceMethods)
14
+ end
15
+
16
+ module InstanceMethods
17
+ def run_specs(*)
18
+ return super unless datadog_configuration[:enabled]
19
+
20
+ test_session = CI.start_test_session(
21
+ tags: {
22
+ CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
23
+ CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::RSpec::Integration.version.to_s
24
+ },
25
+ service: datadog_configuration[:service_name]
26
+ )
27
+
28
+ test_module = CI.start_test_module(test_session.name) if test_session
29
+
30
+ result = super
31
+ return result unless test_module && test_session
32
+
33
+ if result != 0
34
+ # TODO: repeating this twice feels clunky, we need to remove test_module API before GA
35
+ test_module.failed!
36
+ test_session.failed!
37
+ else
38
+ test_module.passed!
39
+ test_session.passed!
40
+ end
41
+ test_module.finish
42
+ test_session.finish
43
+
44
+ result
45
+ end
46
+
47
+ private
48
+
49
+ def datadog_configuration
50
+ Datadog.configuration.ci[:rspec]
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -27,7 +27,7 @@ module Datadog
27
27
  end
28
28
 
29
29
  def []=(name, value)
30
- respond_to?("#{name}=") ? send("#{name}=", value) : set_option(name, value)
30
+ respond_to?(:"#{name}=") ? send(:"#{name}=", value) : set_option(name, value)
31
31
  end
32
32
  end
33
33
  end
@@ -3,6 +3,8 @@
3
3
  module Datadog
4
4
  module CI
5
5
  module Ext
6
+ # Defines span types for CI visibility
7
+ # @public_api
6
8
  module AppTypes
7
9
  TYPE_TEST = "test"
8
10
  TYPE_TEST_SESSION = "test_session_end"