datadog-ci 1.0.0.beta4 → 1.0.0.beta6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -2
  3. data/lib/datadog/ci/contrib/contrib.rb +31 -0
  4. data/lib/datadog/ci/contrib/minitest/reporter.rb +1 -1
  5. data/lib/datadog/ci/contrib/minitest/runnable.rb +1 -1
  6. data/lib/datadog/ci/contrib/minitest/runner.rb +1 -1
  7. data/lib/datadog/ci/contrib/rspec/example.rb +2 -1
  8. data/lib/datadog/ci/contrib/rspec/example_group.rb +1 -0
  9. data/lib/datadog/ci/contrib/rspec/knapsack_pro/extension.rb +0 -1
  10. data/lib/datadog/ci/contrib/rspec/knapsack_pro/patcher.rb +26 -0
  11. data/lib/datadog/ci/contrib/rspec/knapsack_pro/runner.rb +2 -1
  12. data/lib/datadog/ci/contrib/rspec/patcher.rb +6 -4
  13. data/lib/datadog/ci/contrib/rspec/runner.rb +2 -1
  14. data/lib/datadog/ci/contrib/selenium/capybara_driver.rb +45 -0
  15. data/lib/datadog/ci/contrib/selenium/configuration/settings.rb +32 -0
  16. data/lib/datadog/ci/contrib/selenium/driver.rb +45 -0
  17. data/lib/datadog/ci/contrib/selenium/ext.rb +30 -0
  18. data/lib/datadog/ci/contrib/selenium/integration.rb +48 -0
  19. data/lib/datadog/ci/contrib/selenium/navigation.rb +74 -0
  20. data/lib/datadog/ci/contrib/selenium/patcher.rb +36 -0
  21. data/lib/datadog/ci/contrib/selenium/rum.rb +45 -0
  22. data/lib/datadog/ci/ext/test.rb +18 -5
  23. data/lib/datadog/ci/ext/transport.rb +3 -0
  24. data/lib/datadog/ci/span.rb +5 -0
  25. data/lib/datadog/ci/test_visibility/recorder.rb +4 -0
  26. data/lib/datadog/ci/transport/api/agentless.rb +11 -3
  27. data/lib/datadog/ci/transport/gzip.rb +12 -0
  28. data/lib/datadog/ci/transport/http.rb +35 -3
  29. data/lib/datadog/ci/version.rb +1 -1
  30. data/lib/datadog/ci.rb +1 -0
  31. metadata +12 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 035d75d50e0e09c7895bc0e434c5ac1e0655618763ac724a94989833e0c07d61
4
- data.tar.gz: bfbd5d6ff101ef51e59d3546d110f906f178c23602241f85b3a8b413524a9900
3
+ metadata.gz: a905eacfa2face6f297e027aa344b9b36f99d7f7f2120ab6946b2e9c650c390b
4
+ data.tar.gz: 537bd49690464320a74f88d9a0c392dcac10b83575407d703cf756a71ea8c29e
5
5
  SHA512:
6
- metadata.gz: c1b6463b913cbff1e20a2c3f4fcaa6c47814ba693eee5682fa41c3baa74f9e92414b4e554ec8407807d6eeb1744f0c76d87bb0889bd0e639c6ebdc3de1dcd180
7
- data.tar.gz: dca4568f30dbaef22e8fac94389e682beb21ba6f92f0578553ff01d2ad289f38d33f899c79bef604f3f83906d6c31b9e64a9495cc3dc986fb321bd810430780d
6
+ metadata.gz: 8c87d7be67c31a970d0f6e75fcc4a0305719604afe02eac4061fd9c43a2539632f7a6f9199aafdaf55438913e721280ec2e5ac30f75d5921dd4bb3bdc1638f5a
7
+ data.tar.gz: '0838f7ce0df3bdf19a9a9c2c0df6c1b8ef0a96421e7043bfa339b6aa8d7a04f204a8c2a0dcb1cccb80f13df4a47a5da16c127a756d5064512120ea35a9beb8d0'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.0.0.beta6] - 2024-05-29
4
+
5
+ ### Added
6
+
7
+ * Browser tests support via selenium integration ([#183][])
8
+
9
+ ## [1.0.0.beta5] - 2024-05-23
10
+
11
+ ### Changed
12
+
13
+ * accept gzipped responses from API ([#170][])
14
+
15
+ ### Fixed
16
+
17
+ * Fix Knapsack Pro integration ([#180][])
18
+
3
19
  ## [1.0.0.beta4] - 2024-05-14
4
20
 
5
21
  ### Added
@@ -238,7 +254,9 @@ Currently test suite level visibility is not used by our instrumentation: it wil
238
254
 
239
255
  - Ruby versions < 2.7 no longer supported ([#8][])
240
256
 
241
- [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta4...main
257
+ [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta6...main
258
+ [1.0.0.beta6]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta5...v1.0.0.beta6
259
+ [1.0.0.beta5]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta4...v1.0.0.beta5
242
260
  [1.0.0.beta4]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta3...v1.0.0.beta4
243
261
  [1.0.0.beta3]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta2...v1.0.0.beta3
244
262
  [1.0.0.beta2]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0.beta1...v1.0.0.beta2
@@ -334,7 +352,10 @@ Currently test suite level visibility is not used by our instrumentation: it wil
334
352
  [#166]: https://github.com/DataDog/datadog-ci-rb/issues/166
335
353
  [#167]: https://github.com/DataDog/datadog-ci-rb/issues/167
336
354
  [#168]: https://github.com/DataDog/datadog-ci-rb/issues/168
355
+ [#170]: https://github.com/DataDog/datadog-ci-rb/issues/170
337
356
  [#172]: https://github.com/DataDog/datadog-ci-rb/issues/172
338
357
  [#173]: https://github.com/DataDog/datadog-ci-rb/issues/173
339
358
  [#174]: https://github.com/DataDog/datadog-ci-rb/issues/174
340
- [#175]: https://github.com/DataDog/datadog-ci-rb/issues/175
359
+ [#175]: https://github.com/DataDog/datadog-ci-rb/issues/175
360
+ [#180]: https://github.com/DataDog/datadog-ci-rb/issues/180
361
+ [#183]: https://github.com/DataDog/datadog-ci-rb/issues/183
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "integration"
4
+
5
+ module Datadog
6
+ module CI
7
+ module Contrib
8
+ # This method auto instruments all test libraries (ex: selenium-webdriver).
9
+ # It is intended to be called when test session starts to add additional capabilities to test visibility.
10
+ #
11
+ # This method does not automatically instrument test frameworks (ex: RSpec, Cucumber, etc), it requires
12
+ # test framework to be already instrumented.
13
+ def self.auto_instrument_on_session_start!
14
+ Datadog.logger.debug("Auto instrumenting all integrations...")
15
+
16
+ Integration.registry.each do |name, integration|
17
+ next unless integration.auto_instrument?
18
+
19
+ Datadog.logger.debug "#{name} is allowed to be auto instrumented"
20
+
21
+ patch_results = integration.patch
22
+ if patch_results == true
23
+ Datadog.logger.debug("#{name} is patched")
24
+ else
25
+ Datadog.logger.debug("#{name} is not patched (#{patch_results})")
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -13,7 +13,7 @@ module Datadog
13
13
  end
14
14
 
15
15
  module InstanceMethods
16
- def report(*)
16
+ def report(*args)
17
17
  return super unless datadog_configuration[:enabled]
18
18
 
19
19
  res = super
@@ -10,7 +10,7 @@ module Datadog
10
10
  end
11
11
 
12
12
  module ClassMethods
13
- def run(*)
13
+ def run(*args)
14
14
  return super unless datadog_configuration[:enabled]
15
15
  return super if Helpers.parallel?(self)
16
16
 
@@ -13,7 +13,7 @@ module Datadog
13
13
  end
14
14
 
15
15
  module ClassMethods
16
- def init_plugins(*)
16
+ def init_plugins(*args)
17
17
  super
18
18
 
19
19
  return unless datadog_configuration[:enabled]
@@ -16,7 +16,8 @@ module Datadog
16
16
  end
17
17
 
18
18
  module InstanceMethods
19
- def run(*)
19
+ def run(*args)
20
+ return super if ::RSpec.configuration.dry_run?
20
21
  return super unless datadog_configuration[:enabled]
21
22
 
22
23
  test_name = full_description.strip
@@ -16,6 +16,7 @@ module Datadog
16
16
  # Instance methods for configuration
17
17
  module ClassMethods
18
18
  def run(reporter = ::RSpec::Core::NullReporter)
19
+ return super if ::RSpec.configuration.dry_run?
19
20
  return super unless datadog_configuration[:enabled]
20
21
  return super unless top_level?
21
22
 
@@ -8,7 +8,6 @@ module Datadog
8
8
  module CI
9
9
  module Contrib
10
10
  module RSpec
11
- # Instrument RSpec::Core::Example
12
11
  module KnapsackPro
13
12
  module Extension
14
13
  def self.included(base)
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module CI
5
+ module Contrib
6
+ module RSpec
7
+ module KnapsackPro
8
+ module Patcher
9
+ def self.patch
10
+ if defined?(::KnapsackPro::Extensions::RSpecExtension::Runner) &&
11
+ ::RSpec::Core::Runner.ancestors.include?(::KnapsackPro::Extensions::RSpecExtension::Runner)
12
+ # knapsack already patched rspec runner
13
+ require_relative "runner"
14
+ ::RSpec::Core::Runner.include(KnapsackPro::Runner)
15
+ else
16
+ # knapsack didn't patch rspec runner yet
17
+ require_relative "extension"
18
+ ::KnapsackPro::Extensions::RSpecExtension.include(KnapsackPro::Extension)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -14,7 +14,8 @@ module Datadog
14
14
  end
15
15
 
16
16
  module InstanceMethods
17
- def knapsack__run_specs(*)
17
+ def knapsack__run_specs(*args)
18
+ return super if ::RSpec.configuration.dry_run?
18
19
  return super unless datadog_configuration[:enabled]
19
20
 
20
21
  test_session = CI.start_test_session(
@@ -27,14 +27,16 @@ module Datadog
27
27
  ::RSpec::Queue::Runner.include(Runner)
28
28
  end
29
29
 
30
- # Knapsack Pro test runner instrumentation
31
- # https://github.com/KnapsackPro/knapsack_pro-ruby
32
30
  if knapsack_pro?
33
- require_relative "knapsack_pro/extension"
34
- ::KnapsackPro::Extensions::RSpecExtension.include(KnapsackPro::Extension)
31
+ # Knapsack Pro test runner instrumentation
32
+ # https://github.com/KnapsackPro/knapsack_pro-ruby
33
+ require_relative "knapsack_pro/patcher"
34
+ Datadog::CI::Contrib::RSpec::KnapsackPro::Patcher.patch
35
35
  end
36
36
 
37
+ # default rspec test runner instrumentation
37
38
  ::RSpec::Core::Runner.include(Runner)
39
+
38
40
  ::RSpec::Core::Example.include(Example)
39
41
  ::RSpec::Core::ExampleGroup.include(ExampleGroup)
40
42
  end
@@ -14,7 +14,8 @@ module Datadog
14
14
  end
15
15
 
16
16
  module InstanceMethods
17
- def run_specs(*)
17
+ def run_specs(*args)
18
+ return super if ::RSpec.configuration.dry_run?
18
19
  return super unless datadog_configuration[:enabled]
19
20
 
20
21
  test_session = CI.start_test_session(
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "datadog/tracing/contrib/patcher"
4
+
5
+ require_relative "ext"
6
+ require_relative "rum"
7
+ require_relative "../../ext/test"
8
+
9
+ module Datadog
10
+ module CI
11
+ module Contrib
12
+ module Selenium
13
+ # instruments Capybara::Selenium::Driver
14
+ module CapybaraDriver
15
+ def self.included(base)
16
+ base.prepend(InstanceMethods)
17
+ end
18
+
19
+ module InstanceMethods
20
+ def reset!
21
+ return super unless datadog_configuration[:enabled]
22
+
23
+ Datadog.logger.debug("[Selenium] Capybara session reset event")
24
+
25
+ RUM.stop_rum_session(@browser)
26
+
27
+ Datadog.logger.debug("[Selenium] RUM session stopped, deleting cookie")
28
+ @browser.manage.delete_cookie(Ext::COOKIE_TEST_EXECUTION_ID)
29
+ rescue ::Selenium::WebDriver::Error::WebDriverError => e
30
+ Datadog.logger.debug("[Selenium] Error while resetting Capybara session: #{e.message}")
31
+ ensure
32
+ super
33
+ end
34
+
35
+ private
36
+
37
+ def datadog_configuration
38
+ Datadog.configuration.ci[:selenium]
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "datadog/core"
4
+
5
+ require_relative "../ext"
6
+ require_relative "../../settings"
7
+
8
+ module Datadog
9
+ module CI
10
+ module Contrib
11
+ module Selenium
12
+ module Configuration
13
+ # Custom settings for the Selenium integration
14
+ # @public_api
15
+ class Settings < Datadog::CI::Contrib::Settings
16
+ option :enabled do |o|
17
+ o.type :bool
18
+ o.env Ext::ENV_ENABLED
19
+ o.default true
20
+ end
21
+
22
+ option :rum_flush_wait_millis do |o|
23
+ o.type :int
24
+ o.env Ext::ENV_RUM_FLUSH_WAIT_MILLIS
25
+ o.default 500
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "datadog/tracing/contrib/patcher"
4
+
5
+ require_relative "ext"
6
+ require_relative "rum"
7
+ require_relative "../../ext/test"
8
+
9
+ module Datadog
10
+ module CI
11
+ module Contrib
12
+ module Selenium
13
+ # instruments Selenium::WebDriver::Driver
14
+ module Driver
15
+ def self.included(base)
16
+ base.prepend(InstanceMethods)
17
+ end
18
+
19
+ module InstanceMethods
20
+ def quit
21
+ return super unless datadog_configuration[:enabled]
22
+
23
+ Datadog.logger.debug("[Selenium] Driver quit event")
24
+
25
+ RUM.stop_rum_session(@bridge)
26
+
27
+ Datadog.logger.debug("[Selenium] RUM session stopped, deleting cookie")
28
+ @bridge.manage.delete_cookie(Ext::COOKIE_TEST_EXECUTION_ID)
29
+ rescue ::Selenium::WebDriver::Error::WebDriverError => e
30
+ Datadog.logger.debug("[Selenium] Error while quitting Selenium driver: #{e.message}")
31
+ ensure
32
+ super
33
+ end
34
+
35
+ private
36
+
37
+ def datadog_configuration
38
+ Datadog.configuration.ci[:selenium]
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module CI
5
+ module Contrib
6
+ module Selenium
7
+ # Selenium integration constants
8
+ # @public_api
9
+ module Ext
10
+ ENV_ENABLED = "DD_CIVISIBILITY_SELENIUM_ENABLED"
11
+ ENV_RUM_FLUSH_WAIT_MILLIS = "DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS"
12
+
13
+ COOKIE_TEST_EXECUTION_ID = "datadog-ci-visibility-test-execution-id"
14
+
15
+ SCRIPT_IS_RUM_ACTIVE = <<~JS
16
+ return !!window.DD_RUM
17
+ JS
18
+ SCRIPT_STOP_RUM_SESSION = <<~JS
19
+ if (window.DD_RUM && window.DD_RUM.stopSession) {
20
+ window.DD_RUM.stopSession();
21
+ return true;
22
+ } else {
23
+ return false;
24
+ }
25
+ JS
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,48 @@
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 Selenium
11
+ # Description of Selenium integration
12
+ class Integration
13
+ include Datadog::CI::Contrib::Integration
14
+
15
+ MINIMUM_VERSION = Gem::Version.new("4.0.0")
16
+
17
+ register_as :selenium
18
+
19
+ def self.version
20
+ Gem.loaded_specs["selenium-webdriver"]&.version
21
+ end
22
+
23
+ def self.loaded?
24
+ !defined?(::Selenium).nil? && !defined?(::Selenium::WebDriver).nil? &&
25
+ !defined?(::Selenium::WebDriver::Driver).nil?
26
+ end
27
+
28
+ def self.compatible?
29
+ super && version >= MINIMUM_VERSION
30
+ end
31
+
32
+ # additional instrumentations for test helpers are auto instrumented on test session start
33
+ def auto_instrument?
34
+ true
35
+ end
36
+
37
+ def new_configuration
38
+ Configuration::Settings.new
39
+ end
40
+
41
+ def patcher
42
+ Patcher
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "datadog/tracing/contrib/patcher"
4
+
5
+ require_relative "ext"
6
+ require_relative "../../ext/test"
7
+
8
+ module Datadog
9
+ module CI
10
+ module Contrib
11
+ module Selenium
12
+ # instruments Selenium::WebDriver::Navigation
13
+ module Navigation
14
+ def self.included(base)
15
+ base.prepend(InstanceMethods)
16
+ end
17
+
18
+ module InstanceMethods
19
+ def to(url)
20
+ result = super
21
+
22
+ return result unless datadog_configuration[:enabled]
23
+
24
+ Datadog.logger.debug("[Selenium] Navigation to #{url}")
25
+
26
+ # on session reset Capybara navigates to about:blank
27
+ return result if url == "about:blank"
28
+
29
+ active_test = Datadog::CI.active_test
30
+ Datadog.logger.debug("[Selenium] Active test: #{active_test}")
31
+
32
+ return result unless active_test
33
+
34
+ # Set the test's trace id as a cookie in browser session
35
+ cookie_hash = {name: Ext::COOKIE_TEST_EXECUTION_ID, value: active_test.trace_id.to_s}
36
+ Datadog.logger.debug { "[Selenium] Setting cookie: #{cookie_hash}" }
37
+ @bridge.manage.add_cookie(cookie_hash)
38
+
39
+ # set the test type to browser
40
+ active_test.set_tag(CI::Ext::Test::TAG_TYPE, CI::Ext::Test::Type::BROWSER)
41
+
42
+ # set the tags specific to the browser test
43
+ active_test.set_tag(CI::Ext::Test::TAG_BROWSER_DRIVER, "selenium")
44
+ active_test.set_tag(
45
+ CI::Ext::Test::TAG_BROWSER_DRIVER_VERSION,
46
+ Integration.version
47
+ )
48
+ active_test.set_tag(
49
+ CI::Ext::Test::TAG_BROWSER_NAME,
50
+ @bridge.browser
51
+ )
52
+ active_test.set_tag(
53
+ CI::Ext::Test::TAG_BROWSER_VERSION,
54
+ @bridge.capabilities.browser_version
55
+ )
56
+
57
+ result
58
+ rescue ::Selenium::WebDriver::Error::WebDriverError => e
59
+ Datadog.logger.debug("[Selenium] Error while navigating: #{e.message}")
60
+
61
+ result
62
+ end
63
+
64
+ private
65
+
66
+ def datadog_configuration
67
+ Datadog.configuration.ci[:selenium]
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "datadog/tracing/contrib/patcher"
4
+
5
+ require_relative "capybara_driver"
6
+ require_relative "driver"
7
+ require_relative "navigation"
8
+
9
+ module Datadog
10
+ module CI
11
+ module Contrib
12
+ module Selenium
13
+ # Patcher enables patching of 'Selenium::WebDriver' module.
14
+ module Patcher
15
+ include Datadog::Tracing::Contrib::Patcher
16
+
17
+ module_function
18
+
19
+ def target_version
20
+ Integration.version
21
+ end
22
+
23
+ def patch
24
+ ::Selenium::WebDriver::Driver.include(Driver)
25
+ ::Selenium::WebDriver::Navigation.include(Navigation)
26
+
27
+ # capybara calls `reset!` after each test, so we need to patch it as well
28
+ if defined?(::Capybara::Selenium::Driver)
29
+ ::Capybara::Selenium::Driver.include(CapybaraDriver)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "datadog/tracing/contrib/patcher"
4
+
5
+ require_relative "ext"
6
+ require_relative "../../ext/test"
7
+ require_relative "../../utils/parsing"
8
+
9
+ module Datadog
10
+ module CI
11
+ module Contrib
12
+ module Selenium
13
+ # Provides functionality to interact with Datadog Real User Monitoring product
14
+ # via executing JavaScript code in the browser.
15
+ #
16
+ # Relevant docs: https://docs.datadoghq.com/real_user_monitoring/browser/
17
+ module RUM
18
+ def self.is_rum_active?(script_executor)
19
+ is_rum_active_script_result = script_executor.execute_script(Ext::SCRIPT_IS_RUM_ACTIVE)
20
+ Datadog.logger.debug { "[Selenium] SCRIPT_IS_RUM_ACTIVE result is #{is_rum_active_script_result.inspect}" }
21
+ Utils::Parsing.convert_to_bool(is_rum_active_script_result)
22
+ end
23
+
24
+ def self.stop_rum_session(script_executor)
25
+ config = Datadog.configuration.ci[:selenium]
26
+ if is_rum_active?(script_executor)
27
+ Datadog::CI.active_test&.set_tag(
28
+ CI::Ext::Test::TAG_IS_RUM_ACTIVE,
29
+ "true"
30
+ )
31
+
32
+ result = script_executor.execute_script(Ext::SCRIPT_STOP_RUM_SESSION)
33
+ Datadog.logger.debug { "[Selenium] SCRIPT_STOP_RUM_SESSION result is #{result.inspect}" }
34
+
35
+ # introduce a delay to allow the RUM session to be stopped
36
+ delay = config[:rum_flush_wait_millis] / 1000.0
37
+ Datadog.logger.debug { "[Selenium] Waiting for #{delay} seconds" }
38
+ sleep(delay)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -8,6 +8,7 @@ module Datadog
8
8
  module Test
9
9
  CONTEXT_ORIGIN = "ciapp-test"
10
10
 
11
+ # Base test visibility tags
11
12
  TAG_FRAMEWORK = "test.framework"
12
13
  TAG_FRAMEWORK_VERSION = "test.framework_version"
13
14
  TAG_NAME = "test.name"
@@ -34,16 +35,13 @@ module Datadog
34
35
  # Code coverage tags
35
36
  TAG_CODE_COVERAGE_ENABLED = "test.code_coverage.enabled"
36
37
 
37
- # those tags are special and used to correlate tests with the test sessions, suites, and modules
38
- # they are transient and not sent to the backend
38
+ # Special tags, not sent to the backend.
39
+ # these tags are special and used to correlate tests with the test sessions, suites, and modules
39
40
  TAG_TEST_SESSION_ID = "_test.session_id"
40
41
  TAG_TEST_MODULE_ID = "_test.module_id"
41
42
  TAG_TEST_SUITE_ID = "_test.suite_id"
42
43
  TRANSIENT_TAGS = [TAG_TEST_SESSION_ID, TAG_TEST_MODULE_ID, TAG_TEST_SUITE_ID].freeze
43
44
 
44
- # tags that are common for the whole session and can be inherited from the test session
45
- INHERITABLE_TAGS = [TAG_FRAMEWORK, TAG_FRAMEWORK_VERSION].freeze
46
-
47
45
  # Environment runtime tags
48
46
  TAG_OS_ARCHITECTURE = "os.architecture"
49
47
  TAG_OS_PLATFORM = "os.platform"
@@ -51,10 +49,24 @@ module Datadog
51
49
  TAG_RUNTIME_NAME = "runtime.name"
52
50
  TAG_RUNTIME_VERSION = "runtime.version"
53
51
 
52
+ # Tags for browser tests
53
+ # true if Datadog RUM was detected in the page(s) loaded by Selenium
54
+ TAG_IS_RUM_ACTIVE = "test.is_rum_active"
55
+ TAG_BROWSER_DRIVER = "test.browser.driver"
56
+ # version of selenium driver used
57
+ TAG_BROWSER_DRIVER_VERSION = "test.browser.driver_version"
58
+ # name of the browser (Chrome, Firefox, Edge, etc), if multiple browsers then this tag is empty
59
+ TAG_BROWSER_NAME = "test.browser.name"
60
+ # version of the browser, if multiple browsers or multiple versions then this tag is empty
61
+ TAG_BROWSER_VERSION = "test.browser.version"
62
+
54
63
  # internal APM tag to mark a span as a test span
55
64
  TAG_SPAN_KIND = "span.kind"
56
65
  SPAN_KIND_TEST = "test"
57
66
 
67
+ # tags that are common for the whole session and can be inherited from the test session
68
+ INHERITABLE_TAGS = [TAG_FRAMEWORK, TAG_FRAMEWORK_VERSION].freeze
69
+
58
70
  # could be either "test" or "suite" depending on whether we skip individual tests or whole suites
59
71
  # we use test skipping for Ruby
60
72
  ITR_TEST_SKIPPING_MODE = "test"
@@ -71,6 +83,7 @@ module Datadog
71
83
  # test types (e.g. test, benchmark, browser)
72
84
  module Type
73
85
  TEST = "test"
86
+ BROWSER = "browser"
74
87
  BENCHMARK = "benchmark" # DEV: not used yet, will be used when benchmarks are supported
75
88
  end
76
89
  end
@@ -7,6 +7,7 @@ module Datadog
7
7
  DEFAULT_DD_SITE = "datadoghq.com"
8
8
 
9
9
  HEADER_DD_API_KEY = "DD-API-KEY"
10
+ HEADER_ACCEPT_ENCODING = "Accept-Encoding"
10
11
  HEADER_CONTENT_TYPE = "Content-Type"
11
12
  HEADER_CONTENT_ENCODING = "Content-Encoding"
12
13
  HEADER_EVP_SUBDOMAIN = "X-Datadog-EVP-Subdomain"
@@ -48,6 +49,8 @@ module Datadog
48
49
  CONTENT_TYPE_JSON = "application/json"
49
50
  CONTENT_TYPE_MULTIPART_FORM_DATA = "multipart/form-data"
50
51
  CONTENT_ENCODING_GZIP = "gzip"
52
+
53
+ GZIP_MAGIC_NUMBER = "\x1F\x8B".b
51
54
  end
52
55
  end
53
56
  end
@@ -23,6 +23,11 @@ module Datadog
23
23
  tracer_span.id
24
24
  end
25
25
 
26
+ # @return [Integer] the trace ID of the trace this span belongs to
27
+ def trace_id
28
+ tracer_span.trace_id
29
+ end
30
+
26
31
  # @return [String] the name of the span.
27
32
  def name
28
33
  tracer_span.name
@@ -10,6 +10,7 @@ require_relative "context/global"
10
10
  require_relative "context/local"
11
11
 
12
12
  require_relative "../codeowners/parser"
13
+ require_relative "../contrib/contrib"
13
14
  require_relative "../ext/app_types"
14
15
  require_relative "../ext/test"
15
16
  require_relative "../ext/environment"
@@ -57,6 +58,9 @@ module Datadog
57
58
  def start_test_session(service: nil, tags: {})
58
59
  return skip_tracing unless test_suite_level_visibility_enabled
59
60
 
61
+ # finds and instruments additional test libraries that we support (ex: selenium-webdriver)
62
+ Contrib.auto_instrument_on_session_start!
63
+
60
64
  @global_context.fetch_or_activate_test_session do
61
65
  tracer_span = start_datadog_tracer_span(
62
66
  "test.session", build_span_options(service, Ext::AppTypes::TYPE_TEST_SESSION)
@@ -26,7 +26,14 @@ module Datadog
26
26
  def api_request(path:, payload:, headers: {}, verb: "post")
27
27
  super
28
28
 
29
- perform_request(@api_http, path: path, payload: payload, headers: headers, verb: verb)
29
+ perform_request(
30
+ @api_http,
31
+ path: path,
32
+ payload: payload,
33
+ headers: headers,
34
+ verb: verb,
35
+ accept_compressed_response: true
36
+ )
30
37
  end
31
38
 
32
39
  def citestcov_request(path:, payload:, headers: {}, verb: "post")
@@ -37,12 +44,13 @@ module Datadog
37
44
 
38
45
  private
39
46
 
40
- def perform_request(http_client, path:, payload:, headers:, verb:)
47
+ def perform_request(http_client, path:, payload:, headers:, verb:, accept_compressed_response: false)
41
48
  http_client.request(
42
49
  path: path,
43
50
  payload: payload,
44
51
  headers: headers_with_default(headers),
45
- verb: verb
52
+ verb: verb,
53
+ accept_compressed_response: accept_compressed_response
46
54
  )
47
55
  end
48
56
 
@@ -16,6 +16,18 @@ module Datadog
16
16
  gzip_writer.close
17
17
  sio.string
18
18
  end
19
+
20
+ def decompress(input)
21
+ sio = StringIO.new(input)
22
+ gzip_reader = Zlib::GzipReader.new(
23
+ sio,
24
+ external_encoding: Encoding::UTF_8,
25
+ internal_encoding: Encoding::UTF_8
26
+ )
27
+ gzip_reader.read || ""
28
+ ensure
29
+ gzip_reader&.close
30
+ end
19
31
  end
20
32
  end
21
33
  end
@@ -32,12 +32,24 @@ module Datadog
32
32
  @compress = compress.nil? ? false : compress
33
33
  end
34
34
 
35
- def request(path:, payload:, headers:, verb: "post", retries: MAX_RETRIES, backoff: INITIAL_BACKOFF)
35
+ def request(
36
+ path:,
37
+ payload:,
38
+ headers:,
39
+ verb: "post",
40
+ retries: MAX_RETRIES,
41
+ backoff: INITIAL_BACKOFF,
42
+ accept_compressed_response: false
43
+ )
36
44
  if compress
37
45
  headers[Ext::Transport::HEADER_CONTENT_ENCODING] = Ext::Transport::CONTENT_ENCODING_GZIP
38
46
  payload = Gzip.compress(payload)
39
47
  end
40
48
 
49
+ if accept_compressed_response
50
+ headers[Ext::Transport::HEADER_ACCEPT_ENCODING] = Ext::Transport::CONTENT_ENCODING_GZIP
51
+ end
52
+
41
53
  Datadog.logger.debug do
42
54
  "Sending #{verb} request: host=#{host}; port=#{port}; ssl_enabled=#{ssl}; " \
43
55
  "compression_enabled=#{compress}; path=#{path}; payload_size=#{payload.size}"
@@ -91,12 +103,32 @@ module Datadog
91
103
  @adapter ||= Datadog::Core::Transport::HTTP::Adapters::Net.new(settings)
92
104
  end
93
105
 
94
- # this is needed because Datadog::Tracing::Writer is not fully compatiple with Datadog::Core::Transport
95
- # TODO: remove when CI implements its own worker
106
+ # adds compatibility with Datadog::Tracing transport and
107
+ # provides ungzipping capabilities
96
108
  class ResponseDecorator < ::SimpleDelegator
109
+ def payload
110
+ return @decompressed_payload if defined?(@decompressed_payload)
111
+
112
+ if gzipped?(__getobj__.payload)
113
+ Datadog.logger.debug("Decompressing gzipped response payload")
114
+ @decompressed_payload = Gzip.decompress(__getobj__.payload)
115
+ else
116
+ __getobj__.payload
117
+ end
118
+ end
119
+
97
120
  def trace_count
98
121
  0
99
122
  end
123
+
124
+ def gzipped?(payload)
125
+ return false if payload.nil? || payload.empty?
126
+
127
+ first_bytes = payload[0, 2]
128
+ return false if first_bytes.nil? || first_bytes.empty?
129
+
130
+ first_bytes.b == Datadog::CI::Ext::Transport::GZIP_MAGIC_NUMBER
131
+ end
100
132
  end
101
133
 
102
134
  class AdapterSettings
@@ -6,7 +6,7 @@ module Datadog
6
6
  MAJOR = "1"
7
7
  MINOR = "0"
8
8
  PATCH = "0"
9
- PRE = "beta4"
9
+ PRE = "beta6"
10
10
  BUILD = nil
11
11
  # PRE and BUILD above are modified for dev gems during gem build GHA workflow
12
12
 
data/lib/datadog/ci.rb CHANGED
@@ -376,6 +376,7 @@ end
376
376
  require_relative "ci/contrib/cucumber/integration"
377
377
  require_relative "ci/contrib/rspec/integration"
378
378
  require_relative "ci/contrib/minitest/integration"
379
+ require_relative "ci/contrib/selenium/integration"
379
380
 
380
381
  # Configuration extensions
381
382
  require_relative "ci/configuration/extensions"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datadog-ci
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta4
4
+ version: 1.0.0.beta6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-14 00:00:00.000000000 Z
11
+ date: 2024-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: datadog
@@ -66,6 +66,7 @@ files:
66
66
  - lib/datadog/ci/configuration/components.rb
67
67
  - lib/datadog/ci/configuration/extensions.rb
68
68
  - lib/datadog/ci/configuration/settings.rb
69
+ - lib/datadog/ci/contrib/contrib.rb
69
70
  - lib/datadog/ci/contrib/cucumber/configuration/settings.rb
70
71
  - lib/datadog/ci/contrib/cucumber/ext.rb
71
72
  - lib/datadog/ci/contrib/cucumber/formatter.rb
@@ -89,9 +90,18 @@ files:
89
90
  - lib/datadog/ci/contrib/rspec/ext.rb
90
91
  - lib/datadog/ci/contrib/rspec/integration.rb
91
92
  - lib/datadog/ci/contrib/rspec/knapsack_pro/extension.rb
93
+ - lib/datadog/ci/contrib/rspec/knapsack_pro/patcher.rb
92
94
  - lib/datadog/ci/contrib/rspec/knapsack_pro/runner.rb
93
95
  - lib/datadog/ci/contrib/rspec/patcher.rb
94
96
  - lib/datadog/ci/contrib/rspec/runner.rb
97
+ - lib/datadog/ci/contrib/selenium/capybara_driver.rb
98
+ - lib/datadog/ci/contrib/selenium/configuration/settings.rb
99
+ - lib/datadog/ci/contrib/selenium/driver.rb
100
+ - lib/datadog/ci/contrib/selenium/ext.rb
101
+ - lib/datadog/ci/contrib/selenium/integration.rb
102
+ - lib/datadog/ci/contrib/selenium/navigation.rb
103
+ - lib/datadog/ci/contrib/selenium/patcher.rb
104
+ - lib/datadog/ci/contrib/selenium/rum.rb
95
105
  - lib/datadog/ci/contrib/settings.rb
96
106
  - lib/datadog/ci/ext/app_types.rb
97
107
  - lib/datadog/ci/ext/environment.rb