datadog-ci 1.19.0 → 1.20.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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -2
  3. data/README.md +8 -17
  4. data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +6 -0
  5. data/lib/datadog/ci/contrib/rspec/documentation_formatter.rb +126 -0
  6. data/lib/datadog/ci/contrib/rspec/example.rb +18 -0
  7. data/lib/datadog/ci/contrib/rspec/ext.rb +9 -0
  8. data/lib/datadog/ci/contrib/rspec/patcher.rb +2 -0
  9. data/lib/datadog/ci/ext/environment/configuration_discrepancy_checker.rb +91 -0
  10. data/lib/datadog/ci/ext/environment/extractor.rb +8 -2
  11. data/lib/datadog/ci/ext/environment/providers/appveyor.rb +8 -0
  12. data/lib/datadog/ci/ext/environment/providers/azure.rb +8 -0
  13. data/lib/datadog/ci/ext/environment/providers/base.rb +3 -0
  14. data/lib/datadog/ci/ext/environment/providers/bitbucket.rb +4 -0
  15. data/lib/datadog/ci/ext/environment/providers/bitrise.rb +4 -0
  16. data/lib/datadog/ci/ext/environment/providers/buddy.rb +4 -0
  17. data/lib/datadog/ci/ext/environment/providers/buildkite.rb +6 -0
  18. data/lib/datadog/ci/ext/environment/providers/circleci.rb +4 -0
  19. data/lib/datadog/ci/ext/environment/providers/codefresh.rb +8 -0
  20. data/lib/datadog/ci/ext/environment/providers/drone.rb +83 -0
  21. data/lib/datadog/ci/ext/environment/providers/github_actions.rb +0 -2
  22. data/lib/datadog/ci/ext/environment/providers/gitlab.rb +4 -0
  23. data/lib/datadog/ci/ext/environment/providers/jenkins.rb +8 -0
  24. data/lib/datadog/ci/ext/environment/providers/teamcity.rb +8 -0
  25. data/lib/datadog/ci/ext/environment/providers/travis.rb +22 -0
  26. data/lib/datadog/ci/ext/environment/providers.rb +2 -0
  27. data/lib/datadog/ci/ext/environment.rb +9 -3
  28. data/lib/datadog/ci/ext/telemetry.rb +3 -0
  29. data/lib/datadog/ci/ext/test.rb +6 -0
  30. data/lib/datadog/ci/remote/library_settings_client.rb +1 -1
  31. data/lib/datadog/ci/span.rb +12 -0
  32. data/lib/datadog/ci/test_retries/component.rb +6 -0
  33. data/lib/datadog/ci/test_retries/driver/base.rb +7 -2
  34. data/lib/datadog/ci/test_visibility/component.rb +3 -2
  35. data/lib/datadog/ci/test_visibility/transport.rb +10 -9
  36. data/lib/datadog/ci/version.rb +1 -1
  37. metadata +4 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c730f78f9fefc725ba4499a38729eff14f5fc48a4a8e6a055ade2b4cedc030a
4
- data.tar.gz: 86a9682f7623bc85a8e8a05fd8b1f91ecb12f459e7f2425fd2fb79d4ce217227
3
+ metadata.gz: b04703fefecfa1e090ce2265ed419e4fa41c170a35c897ab2ac900fe9bca467b
4
+ data.tar.gz: b94de33937e2116579dcaf36c7a7c4f6040597420b27dff1e0f47641f1966be2
5
5
  SHA512:
6
- metadata.gz: ebb3fca5a5cf1db85795b017ffefef4bb09560c4c8c65f54b4d4cc88b93016776a861ec5c48bf700bdff4ee18c4416f6aee632b5abd392ae930a1a1b00042f0c
7
- data.tar.gz: 9b5b171277dc7bb8510dec4bd332a937431ac4bb3f277c9ad3221dd38f3d5eec27b1c92415aa47c0289259543d2ee21fe8ae1dc532e0f9d9376706a38e59e712
6
+ metadata.gz: 0bce96aa0950aecccac7b7382c731c62d29035b403231fec3ca7f59bb85768e52e0041cfa709a62ed5054e360979776d37e0a501a587d875f3263e82d455ab14
7
+ data.tar.gz: 6035f0db0a5a7eb9aae0f51813f330acd3abbe43175000513860abf5ad406f0d76d0aaf8f6e09409f00c251816aae84c7c3757eb56a660fdcefe7e9cbd478d7a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.20.0] - 2025-07-03
4
+
5
+ ### Added
6
+
7
+ * Add Datadog output to RSpec documentation formatter ([#355][])
8
+ * Add Drone CI support and update CI envs handling ([#349][])
9
+
10
+ ### Fixed
11
+
12
+ * FIX: send git.tag when requesting library settings if git.branch is not available ([#359][])
13
+
3
14
  ## [1.19.0] - 2025-06-16
4
15
 
5
16
  ### Changed
@@ -463,7 +474,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
463
474
 
464
475
  - Ruby versions < 2.7 no longer supported ([#8][])
465
476
 
466
- [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.19.0...main
477
+ [Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.20.0...main
478
+ [1.20.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.19.0...v1.20.0
467
479
  [1.19.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.18.0...v1.19.0
468
480
  [1.18.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.17.0...v1.18.0
469
481
  [1.17.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.16.0...v1.17.0
@@ -660,4 +672,7 @@ Currently test suite level visibility is not used by our instrumentation: it wil
660
672
  [#327]: https://github.com/DataDog/datadog-ci-rb/issues/327
661
673
  [#329]: https://github.com/DataDog/datadog-ci-rb/issues/329
662
674
  [#335]: https://github.com/DataDog/datadog-ci-rb/issues/335
663
- [#339]: https://github.com/DataDog/datadog-ci-rb/issues/339
675
+ [#339]: https://github.com/DataDog/datadog-ci-rb/issues/339
676
+ [#349]: https://github.com/DataDog/datadog-ci-rb/issues/349
677
+ [#355]: https://github.com/DataDog/datadog-ci-rb/issues/355
678
+ [#359]: https://github.com/DataDog/datadog-ci-rb/issues/359
data/README.md CHANGED
@@ -9,34 +9,25 @@ Learn more on our [official website](https://docs.datadoghq.com/tests/) and chec
9
9
  ## Features
10
10
 
11
11
  - [Test Visibility](https://docs.datadoghq.com/tests/) - collect metrics and results for your tests
12
+ - [Flaky test management](https://docs.datadoghq.com/tests/flaky_management/) - track, triage, and remediate flaky tests across your organization. Quarantine or disable problematic tests to keep known flakes from breaking builds, and create cases and Jira issues to track work toward fixes.
13
+ - [Auto test retries](https://docs.datadoghq.com/tests/flaky_tests/auto_test_retries/?tab=ruby) - retrying failing tests up to N times to avoid failing your build due to flaky tests
14
+ - [Early flake detection](https://docs.datadoghq.com/tests/flaky_tests/early_flake_detection/?tab=ruby) - Datadog’s test flakiness solution that identifies flakes early by running newly added tests multiple times
12
15
  - [Test impact analysis](https://docs.datadoghq.com/tests/test_impact_analysis/) - save time by selectively running only tests affected by code changes
13
- - [Flaky test management](https://docs.datadoghq.com/tests/flaky_test_management/) - track, alert, search your flaky tests in Datadog UI
14
- - [Auto test retries](https://docs.datadoghq.com/tests/flaky_test_management/auto_test_retries/?tab=ruby) - retrying failing tests up to N times to avoid failing your build due to flaky tests
15
- - [Early flake detection](https://docs.datadoghq.com/tests/flaky_test_management/early_flake_detection/?tab=ruby) - Datadog’s test flakiness solution that identifies flakes early by running newly added tests multiple times
16
- - [Search and manage CI tests](https://docs.datadoghq.com/tests/search/)
16
+ - [Test Health](https://docs.datadoghq.com/tests/test_health) - The Test Health dashboard provides analytics to help teams manage and optimize their testing in CI. This includes sections showing the current impact of test flakiness and how Test Optimization is mitigating these problems.
17
+ - [Inspect your tests' logs in Datadog](https://docs.datadoghq.com/tests/correlate_logs_and_tests)
17
18
  - [Enhance developer workflows](https://docs.datadoghq.com/tests/developer_workflows)
18
19
  - [Add custom measures to your tests](https://docs.datadoghq.com/tests/guides/add_custom_measures/?tab=ruby)
19
20
  - [Browser tests integration with Datadog RUM](https://docs.datadoghq.com/tests/browser_tests)
20
21
 
21
- ## Installation
22
-
23
- Add to your Gemfile.
22
+ ## Setup
24
23
 
25
- ```ruby
26
- group :test do
27
- gem "datadog-ci"
28
- end
29
- ```
24
+ - [Test visibility setup](https://docs.datadoghq.com/tests/setup/ruby/?tab=cloudciprovideragentless)
25
+ - [Test impact analysis setup](https://docs.datadoghq.com/tests/test_impact_analysis/setup/ruby/?tab=cloudciprovideragentless) (test visibility setup is required before setting up test impact analysis)
30
26
 
31
27
  ## Upgrade from ddtrace v1.x
32
28
 
33
29
  If you used [test visibility for Ruby](https://docs.datadoghq.com/tests/setup/ruby/) with [ddtrace](https://github.com/datadog/dd-trace-rb) gem, check out our [upgrade guide](/docs/UpgradeGuide.md).
34
30
 
35
- ## Setup
36
-
37
- - [Test visibility setup](https://docs.datadoghq.com/tests/setup/ruby/?tab=cloudciprovideragentless)
38
- - [Test impact analysis setup](https://docs.datadoghq.com/tests/test_impact_analysis/setup/ruby/?tab=cloudciprovideragentless) (test visibility setup is required before setting up test impact analysis)
39
-
40
31
  ## Contributing
41
32
 
42
33
  See [development guide](/docs/DevelopmentGuide.md), [static typing guide](docs/StaticTypingGuide.md) and [contributing guidelines](/CONTRIBUTING.md).
@@ -25,6 +25,12 @@ module Datadog
25
25
  end
26
26
  end
27
27
 
28
+ option :datadog_formatter_enabled do |o|
29
+ o.type :bool
30
+ o.env Ext::ENV_DATADOG_FORMATTER_ENABLED
31
+ o.default true
32
+ end
33
+
28
34
  # internal only
29
35
  option :dry_run_enabled do |o|
30
36
  o.type :bool
@@ -0,0 +1,126 @@
1
+ module Datadog
2
+ module CI
3
+ module Contrib
4
+ module RSpec
5
+ # Instrument RSpec::Core::Formatters::DocumentationFormatter
6
+ module DocumentationFormatter
7
+ def self.included(base)
8
+ base.prepend(InstanceMethods)
9
+ end
10
+
11
+ module InstanceMethods
12
+ def example_passed(notification)
13
+ super
14
+
15
+ dd_example_finished(notification.example)
16
+ end
17
+
18
+ def example_failed(notification)
19
+ super
20
+
21
+ dd_example_finished(notification.example)
22
+ end
23
+
24
+ def example_pending(notification)
25
+ super
26
+
27
+ dd_example_finished(notification.example)
28
+ end
29
+
30
+ def dump_summary(notification)
31
+ super
32
+
33
+ return unless @dd_flaky_tests || @dd_quarantined_tests || @dd_disabled_tests || @dd_skipped_by_tia_tests
34
+
35
+ summary = "\nDatadog Test Optimization Summary:\n"
36
+ summary << "#{@dd_flaky_tests} flaky detected " if @dd_flaky_tests&.positive?
37
+ summary << "#{@dd_quarantined_tests} quarantined " if @dd_quarantined_tests&.positive?
38
+ summary << "#{@dd_disabled_tests} disabled " if @dd_disabled_tests&.positive?
39
+ summary << "#{@dd_skipped_by_tia_tests} skipped by test impact analysis " if @dd_skipped_by_tia_tests&.positive?
40
+ summary << "\n"
41
+
42
+ output.puts summary
43
+ end
44
+
45
+ private
46
+
47
+ def dd_example_finished(example)
48
+ @group_level += 1
49
+
50
+ dd_retries_output(example)
51
+ dd_test_management_output(example)
52
+ dd_test_impact_analysis_output(example)
53
+
54
+ @group_level -= 1
55
+ end
56
+
57
+ def dd_retries_output(example)
58
+ if !example.metadata[Ext::METADATA_DD_RETRIES] ||
59
+ !CI::Ext::Test::RetryReason::DATADOG_RETRY_REASONS.include?(
60
+ example.metadata[Ext::METADATA_DD_RETRY_REASON]
61
+ )
62
+ return
63
+ end
64
+
65
+ retries_count = example.metadata[Ext::METADATA_DD_RETRIES]
66
+
67
+ output.puts(
68
+ "#{current_indentation}| Retried #{retries_count} times by #{dd_retry_source(example.metadata[Ext::METADATA_DD_RETRY_REASON])}"
69
+ )
70
+ results = example.metadata[Ext::METADATA_DD_RETRY_RESULTS]
71
+ results_output = results.map { |status, count| "#{count} / #{retries_count} #{status}" }.join(", ")
72
+ output.puts(
73
+ "#{current_indentation}| Results were: #{results_output}"
74
+ )
75
+
76
+ if results[CI::Ext::Test::Status::FAIL] > 0 && results[CI::Ext::Test::Status::PASS] > 0
77
+ output.puts(
78
+ "#{current_indentation}| Flaky test detected"
79
+ )
80
+
81
+ @dd_flaky_tests ||= 0
82
+ @dd_flaky_tests += 1
83
+ end
84
+ end
85
+
86
+ def dd_retry_source(reason)
87
+ case reason
88
+ when CI::Ext::Test::RetryReason::RETRY_FAILED
89
+ "Datadog Auto Test Retries"
90
+ when CI::Ext::Test::RetryReason::RETRY_DETECT_FLAKY
91
+ "Datadog Early Flake Detection"
92
+ when CI::Ext::Test::RetryReason::RETRY_FLAKY_FIXED
93
+ "Datadog Flaky Test Management"
94
+ else
95
+ "Datadog Test Optimization"
96
+ end
97
+ end
98
+
99
+ def dd_test_management_output(example)
100
+ if example.metadata[Ext::METADATA_DD_QUARANTINED]
101
+ output.puts("#{current_indentation}| Test was quarantined by Datadog Flaky Test Management")
102
+
103
+ @dd_quarantined_tests ||= 0
104
+ @dd_quarantined_tests += 1
105
+ end
106
+
107
+ if example.metadata[Ext::METADATA_DD_DISABLED]
108
+ output.puts("#{current_indentation}| Test was disabled by Datadog Flaky Test Management")
109
+
110
+ @dd_disabled_tests ||= 0
111
+ @dd_disabled_tests += 1
112
+ end
113
+ end
114
+
115
+ def dd_test_impact_analysis_output(example)
116
+ if example.metadata[Ext::METADATA_DD_SKIPPED_BY_ITR]
117
+ @dd_skipped_by_tia_tests ||= 0
118
+ @dd_skipped_by_tia_tests += 1
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -74,6 +74,24 @@ module Datadog
74
74
  exception: execution_result.pending_exception
75
75
  )
76
76
  end
77
+
78
+ if datadog_configuration[:datadog_formatter_enabled]
79
+ if test_span&.is_retry?
80
+ metadata[Ext::METADATA_DD_RETRIES] ||= 0
81
+ metadata[Ext::METADATA_DD_RETRY_RESULTS] ||= Hash.new(0)
82
+
83
+ metadata[Ext::METADATA_DD_RETRIES] += 1
84
+ metadata[Ext::METADATA_DD_RETRY_REASON] = test_span&.retry_reason
85
+ metadata[Ext::METADATA_DD_RETRY_RESULTS][test_span&.status] += 1
86
+ end
87
+
88
+ metadata[Ext::METADATA_DD_QUARANTINED] = true if test_span&.quarantined?
89
+ metadata[Ext::METADATA_DD_DISABLED] = true if test_span&.disabled?
90
+
91
+ if test_span&.skipped_by_test_impact_analysis?
92
+ metadata[Ext::METADATA_DD_SKIPPED_BY_ITR] = true
93
+ end
94
+ end
77
95
  end
78
96
  end
79
97
 
@@ -11,6 +11,15 @@ module Datadog
11
11
  DEFAULT_SERVICE_NAME = "rspec"
12
12
 
13
13
  ENV_ENABLED = "DD_TRACE_RSPEC_ENABLED"
14
+ ENV_DATADOG_FORMATTER_ENABLED = "DD_TRACE_RSPEC_DATADOG_FORMATTER_ENABLED"
15
+
16
+ # Metadata keys
17
+ METADATA_DD_RETRIES = :dd_retries
18
+ METADATA_DD_RETRY_RESULTS = :dd_retry_results
19
+ METADATA_DD_RETRY_REASON = :dd_retry_reason
20
+ METADATA_DD_QUARANTINED = :dd_quarantined
21
+ METADATA_DD_DISABLED = :dd_disabled
22
+ METADATA_DD_SKIPPED_BY_ITR = :dd_skipped_by_itr
14
23
  end
15
24
  end
16
25
  end
@@ -5,6 +5,7 @@ require_relative "../patcher"
5
5
  require_relative "example"
6
6
  require_relative "example_group"
7
7
  require_relative "runner"
8
+ require_relative "documentation_formatter"
8
9
 
9
10
  module Datadog
10
11
  module CI
@@ -20,6 +21,7 @@ module Datadog
20
21
  ::RSpec::Core::Runner.include(Runner)
21
22
  ::RSpec::Core::Example.include(Example)
22
23
  ::RSpec::Core::ExampleGroup.include(ExampleGroup)
24
+ ::RSpec::Core::Formatters::DocumentationFormatter.include(DocumentationFormatter)
23
25
  end
24
26
  end
25
27
  end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../git"
4
+ require_relative "../telemetry"
5
+ require_relative "../../utils/telemetry"
6
+
7
+ module Datadog
8
+ module CI
9
+ module Ext
10
+ module Environment
11
+ class ConfigurationDiscrepancyChecker
12
+ def initialize(ci_provider_env_tags, local_git_tags, user_provided_tags)
13
+ @ci_provider_env_tags = ci_provider_env_tags
14
+ @local_git_tags = local_git_tags
15
+ @user_provided_tags = user_provided_tags
16
+ end
17
+
18
+ def check_for_discrepancies
19
+ checks = [
20
+ {
21
+ left: normalize_value(@ci_provider_env_tags[Git::TAG_COMMIT_SHA]),
22
+ right: normalize_value(@local_git_tags[Git::TAG_COMMIT_SHA]),
23
+ type: "commit_discrepancy",
24
+ expected: "ci_provider",
25
+ discrepant: "git_client"
26
+ },
27
+ {
28
+ left: normalize_value(@user_provided_tags[Git::TAG_COMMIT_SHA]),
29
+ right: normalize_value(@local_git_tags[Git::TAG_COMMIT_SHA]),
30
+ type: "commit_discrepancy",
31
+ expected: "user_supplied",
32
+ discrepant: "git_client"
33
+ },
34
+ {
35
+ left: normalize_value(@user_provided_tags[Git::TAG_COMMIT_SHA]),
36
+ right: normalize_value(@ci_provider_env_tags[Git::TAG_COMMIT_SHA]),
37
+ type: "commit_discrepancy",
38
+ expected: "user_supplied",
39
+ discrepant: "ci_provider"
40
+ },
41
+ {
42
+ left: normalize_value(@ci_provider_env_tags[Git::TAG_REPOSITORY_URL]),
43
+ right: normalize_value(@local_git_tags[Git::TAG_REPOSITORY_URL]),
44
+ type: "repository_discrepancy",
45
+ expected: "ci_provider",
46
+ discrepant: "git_client"
47
+ },
48
+ {
49
+ left: normalize_value(@user_provided_tags[Git::TAG_REPOSITORY_URL]),
50
+ right: normalize_value(@local_git_tags[Git::TAG_REPOSITORY_URL]),
51
+ type: "repository_discrepancy",
52
+ expected: "user_supplied",
53
+ discrepant: "git_client"
54
+ },
55
+ {
56
+ left: normalize_value(@user_provided_tags[Git::TAG_REPOSITORY_URL]),
57
+ right: normalize_value(@ci_provider_env_tags[Git::TAG_REPOSITORY_URL]),
58
+ type: "repository_discrepancy",
59
+ expected: "user_supplied",
60
+ discrepant: "ci_provider"
61
+ }
62
+ ]
63
+
64
+ git_info_match = true
65
+ checks.each do |check|
66
+ if check[:left] && check[:right] && check[:left] != check[:right]
67
+ Utils::Telemetry.inc(Ext::Telemetry::METRIC_GIT_COMMIT_SHA_DISCREPANCY, 1, {
68
+ type: check[:type].to_s,
69
+ expected_provider: check[:expected].to_s,
70
+ discrepant_provider: check[:discrepant].to_s
71
+ })
72
+ git_info_match = false
73
+ end
74
+ end
75
+
76
+ Utils::Telemetry.inc(Ext::Telemetry::METRIC_GIT_COMMIT_SHA_MATCH, 1, {
77
+ matched: git_info_match.to_s
78
+ })
79
+ end
80
+
81
+ private
82
+
83
+ def normalize_value(value)
84
+ return nil if value.nil? || value == ""
85
+ value
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -49,7 +49,9 @@ module Datadog
49
49
  Git::TAG_COMMIT_SHA => @provider.git_commit_sha,
50
50
  Git::TAG_PULL_REQUEST_BASE_BRANCH => @provider.git_pull_request_base_branch,
51
51
  Git::TAG_PULL_REQUEST_BASE_BRANCH_SHA => @provider.git_pull_request_base_branch_sha,
52
- Git::TAG_COMMIT_HEAD_SHA => @provider.git_commit_head_sha
52
+ Git::TAG_COMMIT_HEAD_SHA => @provider.git_commit_head_sha,
53
+
54
+ Environment::TAG_PR_NUMBER => @provider.pr_number
53
55
  }
54
56
 
55
57
  # Normalize Git references and filter sensitive data
@@ -57,13 +59,16 @@ module Datadog
57
59
  # Expand ~
58
60
  expand_workspace!
59
61
 
62
+ # Convert all tag values to strings
63
+ @tags.transform_values! { |v| v&.to_s }
64
+
60
65
  # remove empty tags
61
66
  @tags.reject! do |_, v|
62
67
  # setting type of v here to untyped because steep does not
63
68
  # understand `v.nil? || something`
64
69
 
65
70
  # @type var v: untyped
66
- v.nil? || v.strip.empty?
71
+ v.nil? || v.to_s.strip.empty?
67
72
  end
68
73
 
69
74
  @tags
@@ -80,6 +85,7 @@ module Datadog
80
85
 
81
86
  @tags[Git::TAG_TAG] = Utils::Git.normalize_ref(@tags[Git::TAG_TAG])
82
87
  @tags[Git::TAG_BRANCH] = Utils::Git.normalize_ref(@tags[Git::TAG_BRANCH])
88
+ @tags[Git::TAG_PULL_REQUEST_BASE_BRANCH] = Utils::Git.normalize_ref(@tags[Git::TAG_PULL_REQUEST_BASE_BRANCH])
83
89
  @tags[Git::TAG_REPOSITORY_URL] = Datadog::Core::Utils::Url.filter_basic_auth(
84
90
  @tags[Git::TAG_REPOSITORY_URL]
85
91
  )
@@ -74,6 +74,14 @@ module Datadog
74
74
  env["APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL"]
75
75
  end
76
76
 
77
+ def git_commit_head_sha
78
+ env["APPVEYOR_PULL_REQUEST_HEAD_COMMIT"]
79
+ end
80
+
81
+ def pr_number
82
+ env["APPVEYOR_PULL_REQUEST_NUMBER"]
83
+ end
84
+
77
85
  def git_commit_message
78
86
  commit_message = env["APPVEYOR_REPO_COMMIT_MESSAGE"]
79
87
  if commit_message
@@ -80,6 +80,14 @@ module Datadog
80
80
  env["BUILD_SOURCEVERSIONMESSAGE"]
81
81
  end
82
82
 
83
+ def git_pull_request_base_branch
84
+ env["SYSTEM_PULLREQUEST_TARGETBRANCH"]
85
+ end
86
+
87
+ def pr_number
88
+ env["SYSTEM_PULLREQUEST_PULLREQUESTNUMBER"]
89
+ end
90
+
83
91
  def ci_env_vars
84
92
  {
85
93
  "SYSTEM_TEAMPROJECTID" => env["SYSTEM_TEAMPROJECTID"],
@@ -105,6 +105,9 @@ module Datadog
105
105
  def git_commit_head_sha
106
106
  end
107
107
 
108
+ def pr_number
109
+ end
110
+
108
111
  private
109
112
 
110
113
  def set_branch_and_tag
@@ -65,6 +65,10 @@ module Datadog
65
65
  env["BITBUCKET_PR_DESTINATION_BRANCH"]
66
66
  end
67
67
 
68
+ def pr_number
69
+ env["BITBUCKET_PR_ID"]
70
+ end
71
+
68
72
  private
69
73
 
70
74
  def url
@@ -79,6 +79,10 @@ module Datadog
79
79
  # For example, a pull request wants to merge the content of a branch into the branch main. In this case, this Env Var’s value is main.
80
80
  env["BITRISEIO_GIT_BRANCH_DEST"]
81
81
  end
82
+
83
+ def pr_number
84
+ env["BITRISE_PULL_REQUEST"]
85
+ end
82
86
  end
83
87
  end
84
88
  end
@@ -70,6 +70,10 @@ module Datadog
70
70
  # from docs: The name of the Git BASE branch of the currently run Pull Request
71
71
  env["BUDDY_RUN_PR_BASE_BRANCH"]
72
72
  end
73
+
74
+ def pr_number
75
+ env["BUDDY_RUN_PR_NO"]
76
+ end
73
77
  end
74
78
  end
75
79
  end
@@ -89,6 +89,12 @@ module Datadog
89
89
  env["BUILDKITE_PULL_REQUEST_BASE_BRANCH"]
90
90
  end
91
91
 
92
+ def pr_number
93
+ return nil if env["BUILDKITE_PULL_REQUEST"] == "false"
94
+
95
+ env["BUILDKITE_PULL_REQUEST"]
96
+ end
97
+
92
98
  def ci_env_vars
93
99
  {
94
100
  "BUILDKITE_BUILD_ID" => env["BUILDKITE_BUILD_ID"],
@@ -72,6 +72,10 @@ module Datadog
72
72
  env["BUILD_SOURCEVERSIONMESSAGE"]
73
73
  end
74
74
 
75
+ def pr_number
76
+ env["CIRCLE_PR_NUMBER"]
77
+ end
78
+
75
79
  def ci_env_vars
76
80
  {
77
81
  "CIRCLE_WORKFLOW_ID" => env["CIRCLE_WORKFLOW_ID"],
@@ -40,6 +40,14 @@ module Datadog
40
40
  env["CF_BRANCH"]
41
41
  end
42
42
 
43
+ def git_pull_request_base_branch
44
+ env["CF_PULL_REQUEST_TARGET"]
45
+ end
46
+
47
+ def pr_number
48
+ env["CF_PULL_REQUEST_NUMBER"]
49
+ end
50
+
43
51
  def ci_env_vars
44
52
  {
45
53
  "CF_BUILD_ID" => env["CF_BUILD_ID"]
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ require_relative "base"
6
+
7
+ module Datadog
8
+ module CI
9
+ module Ext
10
+ module Environment
11
+ module Providers
12
+ # Drone CI: https://drone.io/
13
+ # Environment variables docs: https://docs.drone.io/pipeline/environment/reference/
14
+ class Drone < Base
15
+ def self.handles?(env)
16
+ env.key?("DRONE")
17
+ end
18
+
19
+ def provider_name
20
+ Provider::DRONE
21
+ end
22
+
23
+ def job_name
24
+ env["DRONE_STEP_NAME"]
25
+ end
26
+
27
+ def pipeline_number
28
+ env["DRONE_BUILD_NUMBER"]
29
+ end
30
+
31
+ def pipeline_url
32
+ env["DRONE_BUILD_LINK"]
33
+ end
34
+
35
+ def stage_name
36
+ env["DRONE_STAGE_NAME"]
37
+ end
38
+
39
+ def workspace_path
40
+ env["DRONE_WORKSPACE"]
41
+ end
42
+
43
+ def git_repository_url
44
+ env["DRONE_GIT_HTTP_URL"]
45
+ end
46
+
47
+ def git_commit_sha
48
+ env["DRONE_COMMIT_SHA"]
49
+ end
50
+
51
+ def git_branch
52
+ env["DRONE_BRANCH"]
53
+ end
54
+
55
+ def git_tag
56
+ env["DRONE_TAG"]
57
+ end
58
+
59
+ def git_commit_author_name
60
+ env["DRONE_COMMIT_AUTHOR_NAME"]
61
+ end
62
+
63
+ def git_commit_author_email
64
+ env["DRONE_COMMIT_AUTHOR_EMAIL"]
65
+ end
66
+
67
+ def git_commit_message
68
+ env["DRONE_COMMIT_MESSAGE"]
69
+ end
70
+
71
+ def git_pull_request_base_branch
72
+ env["DRONE_TARGET_BRANCH"]
73
+ end
74
+
75
+ def pr_number
76
+ env["DRONE_PULL_REQUEST"]
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -77,8 +77,6 @@ module Datadog
77
77
  end
78
78
 
79
79
  def git_pull_request_base_branch
80
- return nil if github_event_json.nil?
81
-
82
80
  env["GITHUB_BASE_REF"]
83
81
  end
84
82
 
@@ -108,6 +108,10 @@ module Datadog
108
108
  env["CI_MERGE_REQUEST_SOURCE_BRANCH_SHA"]
109
109
  end
110
110
 
111
+ def pr_number
112
+ env["CI_MERGE_REQUEST_IID"]
113
+ end
114
+
111
115
  private
112
116
 
113
117
  def extract_name_email
@@ -65,6 +65,14 @@ module Datadog
65
65
  env["GIT_BRANCH"]
66
66
  end
67
67
 
68
+ def git_pull_request_base_branch
69
+ env["CHANGE_TARGET"]
70
+ end
71
+
72
+ def pr_number
73
+ env["CHANGE_ID"]
74
+ end
75
+
68
76
  def ci_env_vars
69
77
  {
70
78
  "DD_CUSTOM_TRACE_ID" => env["DD_CUSTOM_TRACE_ID"]
@@ -25,6 +25,14 @@ module Datadog
25
25
  def job_url
26
26
  env["BUILD_URL"]
27
27
  end
28
+
29
+ def git_pull_request_base_branch
30
+ env["TEAMCITY_PULLREQUEST_TARGET_BRANCH"]
31
+ end
32
+
33
+ def pr_number
34
+ env["TEAMCITY_PULLREQUEST_NUMBER"]
35
+ end
28
36
  end
29
37
  end
30
38
  end
@@ -61,6 +61,28 @@ module Datadog
61
61
  def git_commit_message
62
62
  env["TRAVIS_COMMIT_MESSAGE"]
63
63
  end
64
+
65
+ def git_pull_request_base_branch
66
+ return nil unless pull_request?
67
+
68
+ env["TRAVIS_BRANCH"]
69
+ end
70
+
71
+ def git_commit_head_sha
72
+ return nil unless pull_request?
73
+
74
+ env["TRAVIS_PULL_REQUEST_SHA"]
75
+ end
76
+
77
+ def pr_number
78
+ return nil unless pull_request?
79
+
80
+ env["TRAVIS_PULL_REQUEST"]
81
+ end
82
+
83
+ def pull_request?
84
+ env["TRAVIS_EVENT_TYPE"] == "pull_request"
85
+ end
64
86
  end
65
87
  end
66
88
  end
@@ -10,6 +10,7 @@ require_relative "providers/buddy"
10
10
  require_relative "providers/buildkite"
11
11
  require_relative "providers/circleci"
12
12
  require_relative "providers/codefresh"
13
+ require_relative "providers/drone"
13
14
  require_relative "providers/github_actions"
14
15
  require_relative "providers/gitlab"
15
16
  require_relative "providers/jenkins"
@@ -34,6 +35,7 @@ module Datadog
34
35
  Providers::Buildkite,
35
36
  Providers::Circleci,
36
37
  Providers::Codefresh,
38
+ Providers::Drone,
37
39
  Providers::GithubActions,
38
40
  Providers::Gitlab,
39
41
  Providers::Jenkins,
@@ -3,6 +3,7 @@
3
3
  require "datadog/core/telemetry/logging"
4
4
 
5
5
  require_relative "git"
6
+ require_relative "environment/configuration_discrepancy_checker"
6
7
  require_relative "environment/extractor"
7
8
 
8
9
  require_relative "../utils/git"
@@ -24,6 +25,7 @@ module Datadog
24
25
  TAG_NODE_LABELS = "ci.node.labels"
25
26
  TAG_NODE_NAME = "ci.node.name"
26
27
  TAG_CI_ENV_VARS = "_dd.ci.env_vars"
28
+ TAG_PR_NUMBER = "pr.number"
27
29
 
28
30
  module Provider
29
31
  APPVEYOR = "appveyor"
@@ -35,6 +37,7 @@ module Datadog
35
37
  BUILDKITE = "buildkite"
36
38
  CIRCLECI = "circleci"
37
39
  CODEFRESH = "codefresh"
40
+ DRONE = "drone"
38
41
  GITHUB = "github"
39
42
  GITLAB = "gitlab"
40
43
  JENKINS = "jenkins"
@@ -51,9 +54,8 @@ module Datadog
51
54
  tags = Environment::Extractor.new(env).tags
52
55
 
53
56
  # If user defined metadata is defined, overwrite
54
- tags.merge!(
55
- Environment::Extractor.new(env, provider_klass: Providers::UserDefinedTags).tags
56
- )
57
+ user_provided_tags = Environment::Extractor.new(env, provider_klass: Providers::UserDefinedTags).tags
58
+ tags.merge!(user_provided_tags)
57
59
 
58
60
  # Fill out tags from local git as fallback
59
61
  local_git_tags = Environment::Extractor.new(env, provider_klass: Providers::LocalGit).tags
@@ -61,6 +63,10 @@ module Datadog
61
63
  tags[key] ||= value
62
64
  end
63
65
 
66
+ # send some telemetry for the cases where git commit sha is overriden
67
+ discrepancy_checker = ConfigurationDiscrepancyChecker.new(tags, local_git_tags, user_provided_tags)
68
+ discrepancy_checker.check_for_discrepancies
69
+
64
70
  ensure_post_conditions(tags)
65
71
 
66
72
  tags
@@ -68,6 +68,9 @@ module Datadog
68
68
 
69
69
  METRIC_TEST_SESSION = "test_session"
70
70
 
71
+ METRIC_GIT_COMMIT_SHA_MATCH = "git.commit_sha_match"
72
+ METRIC_GIT_COMMIT_SHA_DISCREPANCY = "git.commit_sha_discrepancy"
73
+
71
74
  TAG_TEST_FRAMEWORK = "test_framework"
72
75
  TAG_EVENT_TYPE = "event_type"
73
76
  TAG_HAS_CODEOWNER = "has_codeowner"
@@ -159,6 +159,12 @@ module Datadog
159
159
  RETRY_FAILED = "auto_test_retries"
160
160
  RETRY_FLAKY_FIXED = "attempt_to_fix"
161
161
  RETRY_EXTERNAL = "external"
162
+
163
+ DATADOG_RETRY_REASONS = [
164
+ RETRY_FAILED,
165
+ RETRY_DETECT_FLAKY,
166
+ RETRY_FLAKY_FIXED
167
+ ]
162
168
  end
163
169
 
164
170
  # possible reasons why a test was skipped
@@ -81,7 +81,7 @@ module Datadog
81
81
  "service" => test_session.service,
82
82
  "env" => @dd_env,
83
83
  "repository_url" => test_session.git_repository_url,
84
- "branch" => test_session.git_branch,
84
+ "branch" => test_session.git_branch || test_session.git_tag,
85
85
  "sha" => test_session.git_commit_sha,
86
86
  "test_level" => Ext::Test::ITR_TEST_SKIPPING_MODE,
87
87
  "configurations" => {
@@ -72,6 +72,12 @@ module Datadog
72
72
  tracer_span.get_tag(Ext::Test::TAG_STATUS) == Ext::Test::Status::SKIP
73
73
  end
74
74
 
75
+ # Returns the current status of the span.
76
+ # @return [String, nil] the status of the span ("pass", "fail", "skip"), or nil if not set
77
+ def status
78
+ tracer_span.get_tag(Ext::Test::TAG_STATUS)
79
+ end
80
+
75
81
  # Sets the status of the span to "pass".
76
82
  # @return [void]
77
83
  def passed!
@@ -165,6 +171,12 @@ module Datadog
165
171
  tracer_span.get_tag(Ext::Git::TAG_BRANCH)
166
172
  end
167
173
 
174
+ # Returns the git tag extracted from the environment.
175
+ # @return [String, nil] the tag or nil if not set.
176
+ def git_tag
177
+ tracer_span.get_tag(Ext::Git::TAG_TAG)
178
+ end
179
+
168
180
  # Returns the base commit SHA for the pull request, if available.
169
181
  # @return [String, nil] the base commit SHA or nil if not set.
170
182
  def base_commit_sha
@@ -86,6 +86,12 @@ module Datadog
86
86
  end
87
87
  end
88
88
 
89
+ def record_test_started(test_span)
90
+ # mark test as retry in the beginning
91
+ # if this is a first execution, the current_retry_driver is nil and this is noop
92
+ current_retry_driver&.mark_as_retry(test_span)
93
+ end
94
+
89
95
  def record_test_finished(test_span)
90
96
  if current_retry_driver.nil?
91
97
  # we always run test at least once and after the first pass create a correct retry driver
@@ -11,17 +11,22 @@ module Datadog
11
11
  false
12
12
  end
13
13
 
14
- def record_retry(test_span)
14
+ def mark_as_retry(test_span)
15
15
  test_span&.set_tag(Ext::Test::TAG_IS_RETRY, "true")
16
16
  test_span&.set_tag(Ext::Test::TAG_RETRY_REASON, retry_reason)
17
17
  end
18
18
 
19
+ def record_retry(test_span)
20
+ end
21
+
19
22
  # duration in float seconds
20
23
  def record_duration(duration)
21
24
  end
22
25
 
23
26
  def retry_reason
24
- "unknown"
27
+ # we set retry reason to be external (ie retried outside of datadog)
28
+ # by default if we don't know why the test was retried
29
+ Ext::Test::RetryReason::RETRY_EXTERNAL
25
30
  end
26
31
  end
27
32
  end
@@ -267,6 +267,8 @@ module Datadog
267
267
 
268
268
  test_optimisation.mark_if_skippable(test)
269
269
  test_optimisation.start_coverage(test)
270
+
271
+ test_retries.record_test_started(test)
270
272
  end
271
273
 
272
274
  def on_test_session_finished(test_session)
@@ -293,9 +295,8 @@ module Datadog
293
295
  test_optimisation.stop_coverage(test)
294
296
  test_optimisation.on_test_finished(test, maybe_remote_context)
295
297
 
296
- Telemetry.event_finished(test)
297
-
298
298
  test_retries.record_test_finished(test)
299
+ Telemetry.event_finished(test)
299
300
  end
300
301
 
301
302
  def on_after_test_span_finished(tracer_span)
@@ -19,10 +19,6 @@ module Datadog
19
19
  class Transport < Datadog::CI::Transport::EventPlatformTransport
20
20
  attr_reader :serializers_factory, :dd_env
21
21
 
22
- def self.log_once
23
- @log_once ||= Datadog::Core::Utils::OnlyOnce.new
24
- end
25
-
26
22
  def initialize(
27
23
  api:,
28
24
  dd_env:,
@@ -72,12 +68,17 @@ module Datadog
72
68
 
73
69
  encoded
74
70
  else
75
- message = "Invalid event skipped: #{serializer} Errors: #{serializer.validation_errors}"
76
- Datadog.logger.warn(message)
77
- CI::Transport::Telemetry.endpoint_payload_dropped(1, endpoint: telemetry_endpoint_tag)
71
+ message = "Event with type #{serializer.event_type}(name=#{serializer.name}) is invalid: #{serializer.validation_errors}"
72
+
73
+ if serializer.event_type == "span"
74
+ # events of type span are often skipped because of missing resource field
75
+ # (because they are misconfigured in tests context)
76
+ Datadog.logger.debug(message)
77
+ else
78
+ Datadog.logger.warn(message)
79
+ CI::Transport::Telemetry.endpoint_payload_dropped(1, endpoint: telemetry_endpoint_tag)
78
80
 
79
- # log invalid message once as error to internal telemetry
80
- self.class.log_once.run do
81
+ # for CI events log all events to internal telemetry
81
82
  Core::Telemetry::Logger.error(message)
82
83
  end
83
84
 
@@ -4,7 +4,7 @@ module Datadog
4
4
  module CI
5
5
  module VERSION
6
6
  MAJOR = 1
7
- MINOR = 19
7
+ MINOR = 20
8
8
  PATCH = 0
9
9
  PRE = nil
10
10
  BUILD = nil
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datadog-ci
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.19.0
4
+ version: 1.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
@@ -139,6 +139,7 @@ files:
139
139
  - lib/datadog/ci/contrib/parallel_tests/patcher.rb
140
140
  - lib/datadog/ci/contrib/patcher.rb
141
141
  - lib/datadog/ci/contrib/rspec/configuration/settings.rb
142
+ - lib/datadog/ci/contrib/rspec/documentation_formatter.rb
142
143
  - lib/datadog/ci/contrib/rspec/example.rb
143
144
  - lib/datadog/ci/contrib/rspec/example_group.rb
144
145
  - lib/datadog/ci/contrib/rspec/ext.rb
@@ -166,6 +167,7 @@ files:
166
167
  - lib/datadog/ci/contrib/simplecov/result_extractor.rb
167
168
  - lib/datadog/ci/ext/app_types.rb
168
169
  - lib/datadog/ci/ext/environment.rb
170
+ - lib/datadog/ci/ext/environment/configuration_discrepancy_checker.rb
169
171
  - lib/datadog/ci/ext/environment/extractor.rb
170
172
  - lib/datadog/ci/ext/environment/providers.rb
171
173
  - lib/datadog/ci/ext/environment/providers/appveyor.rb
@@ -178,6 +180,7 @@ files:
178
180
  - lib/datadog/ci/ext/environment/providers/buildkite.rb
179
181
  - lib/datadog/ci/ext/environment/providers/circleci.rb
180
182
  - lib/datadog/ci/ext/environment/providers/codefresh.rb
183
+ - lib/datadog/ci/ext/environment/providers/drone.rb
181
184
  - lib/datadog/ci/ext/environment/providers/github_actions.rb
182
185
  - lib/datadog/ci/ext/environment/providers/gitlab.rb
183
186
  - lib/datadog/ci/ext/environment/providers/jenkins.rb