datadog-ci 0.6.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +63 -2
- data/README.md +21 -2
- data/lib/datadog/ci/codeowners/matcher.rb +102 -0
- data/lib/datadog/ci/codeowners/parser.rb +42 -0
- data/lib/datadog/ci/codeowners/rule.rb +33 -0
- data/lib/datadog/ci/concurrent_span.rb +2 -1
- data/lib/datadog/ci/configuration/components.rb +59 -57
- data/lib/datadog/ci/configuration/settings.rb +21 -0
- data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +4 -1
- data/lib/datadog/ci/contrib/cucumber/formatter.rb +69 -38
- data/lib/datadog/ci/contrib/cucumber/instrumentation.rb +2 -1
- data/lib/datadog/ci/contrib/minitest/configuration/settings.rb +4 -1
- data/lib/datadog/ci/contrib/minitest/helpers.rb +2 -1
- data/lib/datadog/ci/contrib/minitest/hooks.rb +9 -22
- data/lib/datadog/ci/contrib/minitest/patcher.rb +9 -6
- data/lib/datadog/ci/contrib/minitest/reporter.rb +50 -0
- data/lib/datadog/ci/contrib/minitest/runnable.rb +1 -1
- data/lib/datadog/ci/contrib/minitest/runner.rb +41 -0
- data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +4 -1
- data/lib/datadog/ci/contrib/rspec/example.rb +55 -14
- data/lib/datadog/ci/contrib/rspec/example_group.rb +12 -7
- data/lib/datadog/ci/contrib/rspec/patcher.rb +10 -1
- data/lib/datadog/ci/contrib/rspec/runner.rb +7 -8
- data/lib/datadog/ci/ext/app_types.rb +2 -0
- data/lib/datadog/ci/ext/environment/providers/local_git.rb +8 -29
- data/lib/datadog/ci/ext/settings.rb +2 -0
- data/lib/datadog/ci/ext/test.rb +29 -7
- data/lib/datadog/ci/ext/transport.rb +19 -1
- data/lib/datadog/ci/itr/runner.rb +67 -0
- data/lib/datadog/ci/span.rb +51 -2
- data/lib/datadog/ci/test.rb +67 -2
- data/lib/datadog/ci/test_module.rb +1 -1
- data/lib/datadog/ci/test_session.rb +10 -2
- data/lib/datadog/ci/test_suite.rb +53 -2
- data/lib/datadog/ci/test_visibility/context/local.rb +3 -9
- data/lib/datadog/ci/test_visibility/null_recorder.rb +2 -22
- data/lib/datadog/ci/test_visibility/recorder.rb +46 -20
- data/lib/datadog/ci/test_visibility/serializers/base.rb +6 -5
- data/lib/datadog/ci/test_visibility/serializers/span.rb +1 -1
- data/lib/datadog/ci/test_visibility/serializers/test_module.rb +1 -1
- data/lib/datadog/ci/test_visibility/serializers/test_session.rb +1 -1
- data/lib/datadog/ci/test_visibility/serializers/test_suite.rb +1 -1
- data/lib/datadog/ci/test_visibility/serializers/test_v1.rb +1 -1
- data/lib/datadog/ci/test_visibility/transport.rb +1 -5
- data/lib/datadog/ci/transport/api/agentless.rb +63 -0
- data/lib/datadog/ci/transport/api/base.rb +10 -14
- data/lib/datadog/ci/transport/api/builder.rb +25 -22
- data/lib/datadog/ci/transport/api/evp_proxy.rb +47 -7
- data/lib/datadog/ci/transport/http.rb +7 -1
- data/lib/datadog/ci/transport/remote_settings_api.rb +96 -0
- data/lib/datadog/ci/utils/configuration.rb +15 -0
- data/lib/datadog/ci/utils/git.rb +70 -0
- data/lib/datadog/ci/version.rb +1 -1
- data/lib/datadog/ci.rb +40 -56
- metadata +12 -90
- data/lib/datadog/ci/contrib/minitest/plugin.rb +0 -73
- data/lib/datadog/ci/null_span.rb +0 -63
- data/lib/datadog/ci/transport/api/ci_test_cycle.rb +0 -30
- data/sig/datadog/ci/concurrent_span.rbs +0 -23
- data/sig/datadog/ci/configuration/components.rbs +0 -21
- data/sig/datadog/ci/configuration/extensions.rbs +0 -9
- data/sig/datadog/ci/configuration/settings.rbs +0 -16
- data/sig/datadog/ci/contrib/cucumber/configuration/settings.rbs +0 -12
- data/sig/datadog/ci/contrib/cucumber/ext.rbs +0 -21
- data/sig/datadog/ci/contrib/cucumber/formatter.rbs +0 -48
- data/sig/datadog/ci/contrib/cucumber/instrumentation.rbs +0 -16
- data/sig/datadog/ci/contrib/cucumber/integration.rbs +0 -26
- data/sig/datadog/ci/contrib/cucumber/patcher.rbs +0 -15
- data/sig/datadog/ci/contrib/integration.rbs +0 -44
- data/sig/datadog/ci/contrib/minitest/configuration/settings.rbs +0 -12
- data/sig/datadog/ci/contrib/minitest/ext.rbs +0 -19
- data/sig/datadog/ci/contrib/minitest/helpers.rbs +0 -13
- data/sig/datadog/ci/contrib/minitest/hooks.rbs +0 -27
- data/sig/datadog/ci/contrib/minitest/integration.rbs +0 -26
- data/sig/datadog/ci/contrib/minitest/patcher.rbs +0 -15
- data/sig/datadog/ci/contrib/minitest/plugin.rbs +0 -31
- data/sig/datadog/ci/contrib/minitest/runnable.rbs +0 -24
- data/sig/datadog/ci/contrib/rspec/configuration/settings.rbs +0 -12
- data/sig/datadog/ci/contrib/rspec/example.rbs +0 -20
- data/sig/datadog/ci/contrib/rspec/example_group.rbs +0 -21
- data/sig/datadog/ci/contrib/rspec/ext.rbs +0 -17
- data/sig/datadog/ci/contrib/rspec/integration.rbs +0 -26
- data/sig/datadog/ci/contrib/rspec/patcher.rbs +0 -15
- data/sig/datadog/ci/contrib/rspec/runner.rbs +0 -21
- data/sig/datadog/ci/contrib/settings.rbs +0 -25
- data/sig/datadog/ci/ext/app_types.rbs +0 -14
- data/sig/datadog/ci/ext/environment/extractor.rbs +0 -25
- data/sig/datadog/ci/ext/environment/providers/appveyor.rbs +0 -48
- data/sig/datadog/ci/ext/environment/providers/aws_code_pipeline.rbs +0 -19
- data/sig/datadog/ci/ext/environment/providers/azure.rbs +0 -56
- data/sig/datadog/ci/ext/environment/providers/base.rbs +0 -71
- data/sig/datadog/ci/ext/environment/providers/bitbucket.rbs +0 -37
- data/sig/datadog/ci/ext/environment/providers/bitrise.rbs +0 -41
- data/sig/datadog/ci/ext/environment/providers/buddy.rbs +0 -37
- data/sig/datadog/ci/ext/environment/providers/buildkite.rbs +0 -45
- data/sig/datadog/ci/ext/environment/providers/circleci.rbs +0 -41
- data/sig/datadog/ci/ext/environment/providers/codefresh.rbs +0 -25
- data/sig/datadog/ci/ext/environment/providers/github_actions.rbs +0 -42
- data/sig/datadog/ci/ext/environment/providers/gitlab.rbs +0 -57
- data/sig/datadog/ci/ext/environment/providers/jenkins.rbs +0 -35
- data/sig/datadog/ci/ext/environment/providers/local_git.rbs +0 -66
- data/sig/datadog/ci/ext/environment/providers/teamcity.rbs +0 -17
- data/sig/datadog/ci/ext/environment/providers/travis.rbs +0 -35
- data/sig/datadog/ci/ext/environment/providers/user_defined_tags.rbs +0 -33
- data/sig/datadog/ci/ext/environment/providers.rbs +0 -13
- data/sig/datadog/ci/ext/environment.rbs +0 -44
- data/sig/datadog/ci/ext/git.rbs +0 -53
- data/sig/datadog/ci/ext/settings.rbs +0 -14
- data/sig/datadog/ci/ext/test.rbs +0 -60
- data/sig/datadog/ci/ext/transport.rbs +0 -29
- data/sig/datadog/ci/null_span.rbs +0 -37
- data/sig/datadog/ci/span.rbs +0 -47
- data/sig/datadog/ci/test.rbs +0 -12
- data/sig/datadog/ci/test_module.rbs +0 -6
- data/sig/datadog/ci/test_session.rbs +0 -9
- data/sig/datadog/ci/test_suite.rbs +0 -6
- data/sig/datadog/ci/test_visibility/context/global.rbs +0 -39
- data/sig/datadog/ci/test_visibility/context/local.rbs +0 -23
- data/sig/datadog/ci/test_visibility/flush.rbs +0 -17
- data/sig/datadog/ci/test_visibility/null_recorder.rbs +0 -45
- data/sig/datadog/ci/test_visibility/recorder.rbs +0 -85
- data/sig/datadog/ci/test_visibility/serializers/base.rbs +0 -94
- data/sig/datadog/ci/test_visibility/serializers/factories/test_level.rbs +0 -13
- data/sig/datadog/ci/test_visibility/serializers/factories/test_suite_level.rbs +0 -13
- data/sig/datadog/ci/test_visibility/serializers/span.rbs +0 -18
- data/sig/datadog/ci/test_visibility/serializers/test_module.rbs +0 -26
- data/sig/datadog/ci/test_visibility/serializers/test_session.rbs +0 -26
- data/sig/datadog/ci/test_visibility/serializers/test_suite.rbs +0 -26
- data/sig/datadog/ci/test_visibility/serializers/test_v1.rbs +0 -23
- data/sig/datadog/ci/test_visibility/serializers/test_v2.rbs +0 -25
- data/sig/datadog/ci/test_visibility/transport.rbs +0 -35
- data/sig/datadog/ci/transport/api/base.rbs +0 -21
- data/sig/datadog/ci/transport/api/builder.rbs +0 -12
- data/sig/datadog/ci/transport/api/ci_test_cycle.rbs +0 -21
- data/sig/datadog/ci/transport/api/evp_proxy.rbs +0 -19
- data/sig/datadog/ci/transport/gzip.rbs +0 -9
- data/sig/datadog/ci/transport/http.rbs +0 -36
- data/sig/datadog/ci/utils/git.rbs +0 -11
- data/sig/datadog/ci/utils/test_run.rbs +0 -11
- data/sig/datadog/ci/utils/url.rbs +0 -9
- data/sig/datadog/ci/version.rbs +0 -16
- data/sig/datadog/ci.rbs +0 -37
@@ -1,9 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "open3"
|
4
|
-
|
5
3
|
require_relative "base"
|
6
|
-
require_relative "
|
4
|
+
require_relative "../../../utils/git"
|
7
5
|
|
8
6
|
module Datadog
|
9
7
|
module CI
|
@@ -13,7 +11,7 @@ module Datadog
|
|
13
11
|
# As a fallback we try to fetch git information from the local git repository
|
14
12
|
class LocalGit < Base
|
15
13
|
def git_repository_url
|
16
|
-
exec_git_command("git ls-remote --get-url")
|
14
|
+
Utils::Git.exec_git_command("git ls-remote --get-url")
|
17
15
|
rescue => e
|
18
16
|
Datadog.logger.debug(
|
19
17
|
"Unable to read git repository url: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
@@ -22,7 +20,7 @@ module Datadog
|
|
22
20
|
end
|
23
21
|
|
24
22
|
def git_commit_sha
|
25
|
-
exec_git_command("git rev-parse HEAD")
|
23
|
+
Utils::Git.exec_git_command("git rev-parse HEAD")
|
26
24
|
rescue => e
|
27
25
|
Datadog.logger.debug(
|
28
26
|
"Unable to read git commit SHA: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
@@ -31,7 +29,7 @@ module Datadog
|
|
31
29
|
end
|
32
30
|
|
33
31
|
def git_branch
|
34
|
-
exec_git_command("git rev-parse --abbrev-ref HEAD")
|
32
|
+
Utils::Git.exec_git_command("git rev-parse --abbrev-ref HEAD")
|
35
33
|
rescue => e
|
36
34
|
Datadog.logger.debug(
|
37
35
|
"Unable to read git branch: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
@@ -40,7 +38,7 @@ module Datadog
|
|
40
38
|
end
|
41
39
|
|
42
40
|
def git_tag
|
43
|
-
exec_git_command("git tag --points-at HEAD")
|
41
|
+
Utils::Git.exec_git_command("git tag --points-at HEAD")
|
44
42
|
rescue => e
|
45
43
|
Datadog.logger.debug(
|
46
44
|
"Unable to read git tag: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
@@ -49,7 +47,7 @@ module Datadog
|
|
49
47
|
end
|
50
48
|
|
51
49
|
def git_commit_message
|
52
|
-
exec_git_command("git show -s --format=%s")
|
50
|
+
Utils::Git.exec_git_command("git show -s --format=%s")
|
53
51
|
rescue => e
|
54
52
|
Datadog.logger.debug(
|
55
53
|
"Unable to read git commit message: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
@@ -82,7 +80,7 @@ module Datadog
|
|
82
80
|
end
|
83
81
|
|
84
82
|
def workspace_path
|
85
|
-
exec_git_command("git rev-parse --show-toplevel")
|
83
|
+
Utils::Git.exec_git_command("git rev-parse --show-toplevel")
|
86
84
|
rescue => e
|
87
85
|
Datadog.logger.debug(
|
88
86
|
"Unable to read git base directory: #{e.class.name} #{e.message} at #{Array(e.backtrace).first}"
|
@@ -92,25 +90,6 @@ module Datadog
|
|
92
90
|
|
93
91
|
private
|
94
92
|
|
95
|
-
def exec_git_command(cmd)
|
96
|
-
out, status = Open3.capture2e(cmd)
|
97
|
-
|
98
|
-
raise "Failed to run git command #{cmd}: #{out}" unless status.success?
|
99
|
-
|
100
|
-
# Sometimes Encoding.default_external is somehow set to US-ASCII which breaks
|
101
|
-
# commit messages with UTF-8 characters like emojis
|
102
|
-
# We force output's encoding to be UTF-8 in this case
|
103
|
-
# This is safe to do as UTF-8 is compatible with US-ASCII
|
104
|
-
if Encoding.default_external == Encoding::US_ASCII
|
105
|
-
out = out.force_encoding(Encoding::UTF_8)
|
106
|
-
end
|
107
|
-
out.strip! # There's always a "\n" at the end of the command output
|
108
|
-
|
109
|
-
return nil if out.empty?
|
110
|
-
|
111
|
-
out
|
112
|
-
end
|
113
|
-
|
114
93
|
def author
|
115
94
|
return @author if defined?(@author)
|
116
95
|
|
@@ -127,7 +106,7 @@ module Datadog
|
|
127
106
|
|
128
107
|
def set_git_commit_users
|
129
108
|
# Get committer and author information in one command.
|
130
|
-
output = exec_git_command("git show -s --format='%an\t%ae\t%at\t%cn\t%ce\t%ct'")
|
109
|
+
output = Utils::Git.exec_git_command("git show -s --format='%an\t%ae\t%at\t%cn\t%ce\t%ct'")
|
131
110
|
unless output
|
132
111
|
Datadog.logger.debug(
|
133
112
|
"Unable to read git commit users: git command output is nil"
|
@@ -9,6 +9,8 @@ module Datadog
|
|
9
9
|
ENV_AGENTLESS_MODE_ENABLED = "DD_CIVISIBILITY_AGENTLESS_ENABLED"
|
10
10
|
ENV_AGENTLESS_URL = "DD_CIVISIBILITY_AGENTLESS_URL"
|
11
11
|
ENV_EXPERIMENTAL_TEST_SUITE_LEVEL_VISIBILITY_ENABLED = "DD_CIVISIBILITY_EXPERIMENTAL_TEST_SUITE_LEVEL_VISIBILITY_ENABLED"
|
12
|
+
ENV_FORCE_TEST_LEVEL_VISIBILITY = "DD_CIVISIBILITY_FORCE_TEST_LEVEL_VISIBILITY"
|
13
|
+
ENV_ITR_ENABLED = "DD_CIVISIBILITY_ITR_ENABLED"
|
12
14
|
|
13
15
|
# Source: https://docs.datadoghq.com/getting_started/site/
|
14
16
|
DD_SITE_ALLOWLIST = [
|
data/lib/datadog/ci/ext/test.rb
CHANGED
@@ -12,24 +12,33 @@ module Datadog
|
|
12
12
|
TAG_FRAMEWORK = "test.framework"
|
13
13
|
TAG_FRAMEWORK_VERSION = "test.framework_version"
|
14
14
|
TAG_NAME = "test.name"
|
15
|
-
TAG_SKIP_REASON = "test.skip_reason"
|
15
|
+
TAG_SKIP_REASON = "test.skip_reason"
|
16
16
|
TAG_STATUS = "test.status"
|
17
17
|
TAG_SUITE = "test.suite"
|
18
18
|
TAG_MODULE = "test.module"
|
19
|
-
TAG_TRAITS = "test.traits"
|
20
19
|
TAG_TYPE = "test.type"
|
21
20
|
TAG_COMMAND = "test.command"
|
21
|
+
TAG_SOURCE_FILE = "test.source.file"
|
22
|
+
TAG_SOURCE_START = "test.source.start"
|
23
|
+
TAG_CODEOWNERS = "test.codeowners"
|
24
|
+
TAG_PARAMETERS = "test.parameters"
|
22
25
|
|
23
|
-
|
26
|
+
# ITR tags
|
27
|
+
TAG_ITR_TEST_SKIPPING_ENABLED = "test.itr.tests_skipping.enabled"
|
28
|
+
TAG_ITR_TEST_SKIPPING_TYPE = "test.itr.tests_skipping.type"
|
24
29
|
|
25
|
-
#
|
30
|
+
# Code coverage tags
|
31
|
+
TAG_CODE_COVERAGE_ENABLED = "test.code_coverage.enabled"
|
32
|
+
|
33
|
+
# those tags are special and used to correlate tests with the test sessions, suites, and modules
|
34
|
+
# they are transient and not sent to the backend
|
26
35
|
TAG_TEST_SESSION_ID = "_test.session_id"
|
27
36
|
TAG_TEST_MODULE_ID = "_test.module_id"
|
28
37
|
TAG_TEST_SUITE_ID = "_test.suite_id"
|
29
|
-
|
38
|
+
TRANSIENT_TAGS = [TAG_TEST_SESSION_ID, TAG_TEST_MODULE_ID, TAG_TEST_SUITE_ID].freeze
|
30
39
|
|
31
|
-
# tags that can be inherited from the test session
|
32
|
-
INHERITABLE_TAGS = [TAG_FRAMEWORK, TAG_FRAMEWORK_VERSION
|
40
|
+
# tags that are common for the whole session and can be inherited from the test session
|
41
|
+
INHERITABLE_TAGS = [TAG_FRAMEWORK, TAG_FRAMEWORK_VERSION].freeze
|
33
42
|
|
34
43
|
# Environment runtime tags
|
35
44
|
TAG_OS_ARCHITECTURE = "os.architecture"
|
@@ -37,13 +46,26 @@ module Datadog
|
|
37
46
|
TAG_RUNTIME_NAME = "runtime.name"
|
38
47
|
TAG_RUNTIME_VERSION = "runtime.version"
|
39
48
|
|
49
|
+
# internal APM tag to mark a span as a test span
|
40
50
|
TAG_SPAN_KIND = "span.kind"
|
51
|
+
SPAN_KIND_TEST = "test"
|
52
|
+
|
53
|
+
# could be either "test" or "suite" depending on whether we skip individual tests or whole suites
|
54
|
+
# we use test skipping for Ruby
|
55
|
+
ITR_TEST_SKIPPING_MODE = "test"
|
41
56
|
|
57
|
+
# test status as recognized by Datadog
|
42
58
|
module Status
|
43
59
|
PASS = "pass"
|
44
60
|
FAIL = "fail"
|
45
61
|
SKIP = "skip"
|
46
62
|
end
|
63
|
+
|
64
|
+
# test types (e.g. test, benchmark, browser)
|
65
|
+
module Type
|
66
|
+
TEST = "test"
|
67
|
+
BENCHMARK = "benchmark" # DEV: not used yet, will be used when benchmarks are supported
|
68
|
+
end
|
47
69
|
end
|
48
70
|
end
|
49
71
|
end
|
@@ -12,11 +12,29 @@ module Datadog
|
|
12
12
|
HEADER_EVP_SUBDOMAIN = "X-Datadog-EVP-Subdomain"
|
13
13
|
HEADER_CONTAINER_ID = "Datadog-Container-ID"
|
14
14
|
|
15
|
-
|
15
|
+
EVP_PROXY_V2_PATH_PREFIX = "/evp_proxy/v2/"
|
16
|
+
EVP_PROXY_V4_PATH_PREFIX = "/evp_proxy/v4/"
|
17
|
+
EVP_PROXY_PATH_PREFIXES = [EVP_PROXY_V4_PATH_PREFIX, EVP_PROXY_V2_PATH_PREFIX].freeze
|
18
|
+
EVP_PROXY_COMPRESSION_SUPPORTED = {
|
19
|
+
EVP_PROXY_V4_PATH_PREFIX => true,
|
20
|
+
EVP_PROXY_V2_PATH_PREFIX => false
|
21
|
+
}
|
22
|
+
|
16
23
|
TEST_VISIBILITY_INTAKE_HOST_PREFIX = "citestcycle-intake"
|
17
24
|
TEST_VISIBILITY_INTAKE_PATH = "/api/v2/citestcycle"
|
18
25
|
|
26
|
+
DD_API_HOST_PREFIX = "api"
|
27
|
+
DD_API_SETTINGS_PATH = "/api/v2/libraries/tests/services/setting"
|
28
|
+
DD_API_SETTINGS_TYPE = "ci_app_test_service_libraries_settings"
|
29
|
+
DD_API_SETTINGS_RESPONSE_DIG_KEYS = %w[data attributes].freeze
|
30
|
+
DD_API_SETTINGS_RESPONSE_ITR_ENABLED_KEY = "itr_enabled"
|
31
|
+
DD_API_SETTINGS_RESPONSE_CODE_COVERAGE_KEY = "code_coverage"
|
32
|
+
DD_API_SETTINGS_RESPONSE_TESTS_SKIPPING_KEY = "tests_skipping"
|
33
|
+
DD_API_SETTINGS_RESPONSE_REQUIRE_GIT_KEY = "require_git"
|
34
|
+
DD_API_SETTINGS_RESPONSE_DEFAULT = {DD_API_SETTINGS_RESPONSE_ITR_ENABLED_KEY => false}.freeze
|
35
|
+
|
19
36
|
CONTENT_TYPE_MESSAGEPACK = "application/msgpack"
|
37
|
+
CONTENT_TYPE_JSON = "application/json"
|
20
38
|
CONTENT_ENCODING_GZIP = "gzip"
|
21
39
|
end
|
22
40
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../ext/test"
|
4
|
+
require_relative "../ext/transport"
|
5
|
+
|
6
|
+
module Datadog
|
7
|
+
module CI
|
8
|
+
module ITR
|
9
|
+
# Intelligent test runner implementation
|
10
|
+
# Integrates with backend to provide test impact analysis data and
|
11
|
+
# skip tests that are not impacted by the changes
|
12
|
+
class Runner
|
13
|
+
def initialize(
|
14
|
+
enabled: false
|
15
|
+
)
|
16
|
+
@enabled = enabled
|
17
|
+
@test_skipping_enabled = false
|
18
|
+
@code_coverage_enabled = false
|
19
|
+
|
20
|
+
Datadog.logger.debug("ITR Runner initialized with enabled: #{@enabled}")
|
21
|
+
end
|
22
|
+
|
23
|
+
def configure(remote_configuration, test_session)
|
24
|
+
Datadog.logger.debug("Configuring ITR Runner with remote configuration: #{remote_configuration}")
|
25
|
+
|
26
|
+
@enabled = convert_to_bool(
|
27
|
+
remote_configuration.fetch(Ext::Transport::DD_API_SETTINGS_RESPONSE_ITR_ENABLED_KEY, false)
|
28
|
+
)
|
29
|
+
@test_skipping_enabled = @enabled && convert_to_bool(
|
30
|
+
remote_configuration.fetch(Ext::Transport::DD_API_SETTINGS_RESPONSE_TESTS_SKIPPING_KEY, false)
|
31
|
+
)
|
32
|
+
@code_coverage_enabled = @enabled && convert_to_bool(
|
33
|
+
remote_configuration.fetch(Ext::Transport::DD_API_SETTINGS_RESPONSE_CODE_COVERAGE_KEY, false)
|
34
|
+
)
|
35
|
+
|
36
|
+
test_session.set_tag(Ext::Test::TAG_ITR_TEST_SKIPPING_ENABLED, @test_skipping_enabled)
|
37
|
+
# currently we set this tag when ITR requires collecting code coverage
|
38
|
+
# this will change as soon as we implement total code coverage support in this library
|
39
|
+
test_session.set_tag(Ext::Test::TAG_CODE_COVERAGE_ENABLED, @code_coverage_enabled)
|
40
|
+
|
41
|
+
# we skip tests, not suites
|
42
|
+
test_session.set_tag(Ext::Test::TAG_ITR_TEST_SKIPPING_TYPE, Ext::Test::ITR_TEST_SKIPPING_MODE)
|
43
|
+
|
44
|
+
Datadog.logger.debug("Configured ITR Runner with enabled: #{@enabled}, skipping_tests: #{@test_skipping_enabled}, code_coverage: #{@code_coverage_enabled}")
|
45
|
+
end
|
46
|
+
|
47
|
+
def enabled?
|
48
|
+
@enabled
|
49
|
+
end
|
50
|
+
|
51
|
+
def skipping_tests?
|
52
|
+
@test_skipping_enabled
|
53
|
+
end
|
54
|
+
|
55
|
+
def code_coverage?
|
56
|
+
@code_coverage_enabled
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def convert_to_bool(value)
|
62
|
+
value.to_s == "true"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/datadog/ci/span.rb
CHANGED
@@ -32,7 +32,7 @@ module Datadog
|
|
32
32
|
end
|
33
33
|
|
34
34
|
# @return [String] the type of the span (for example "test" or type that was provided to [Datadog::CI.trace]).
|
35
|
-
def
|
35
|
+
def type
|
36
36
|
tracer_span.type
|
37
37
|
end
|
38
38
|
|
@@ -121,6 +121,48 @@ module Datadog
|
|
121
121
|
tracer_span.set_tags(tags)
|
122
122
|
end
|
123
123
|
|
124
|
+
# Returns the git repository URL extracted from the environment.
|
125
|
+
# @return [String] the repository URL.
|
126
|
+
def git_repository_url
|
127
|
+
tracer_span.get_tag(Ext::Git::TAG_REPOSITORY_URL)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Returns the latest commit SHA extracted from the environment.
|
131
|
+
# @return [String] the commit SHA of the last commit.
|
132
|
+
def git_commit_sha
|
133
|
+
tracer_span.get_tag(Ext::Git::TAG_COMMIT_SHA)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Returns the git branch name extracted from the environment.
|
137
|
+
# @return [String] the branch.
|
138
|
+
def git_branch
|
139
|
+
tracer_span.get_tag(Ext::Git::TAG_BRANCH)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Returns the OS architecture extracted from the environment.
|
143
|
+
# @return [String] OS arch.
|
144
|
+
def os_architecture
|
145
|
+
tracer_span.get_tag(Ext::Test::TAG_OS_ARCHITECTURE)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Returns the OS platform extracted from the environment.
|
149
|
+
# @return [String] OS platform.
|
150
|
+
def os_platform
|
151
|
+
tracer_span.get_tag(Ext::Test::TAG_OS_PLATFORM)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Returns the runtime name extracted from the environment.
|
155
|
+
# @return [String] runtime name.
|
156
|
+
def runtime_name
|
157
|
+
tracer_span.get_tag(Ext::Test::TAG_RUNTIME_NAME)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Returns the runtime version extracted from the environment.
|
161
|
+
# @return [String] runtime version.
|
162
|
+
def runtime_version
|
163
|
+
tracer_span.get_tag(Ext::Test::TAG_RUNTIME_VERSION)
|
164
|
+
end
|
165
|
+
|
124
166
|
def set_environment_runtime_tags
|
125
167
|
tracer_span.set_tag(Ext::Test::TAG_OS_ARCHITECTURE, ::RbConfig::CONFIG["host_cpu"])
|
126
168
|
tracer_span.set_tag(Ext::Test::TAG_OS_PLATFORM, ::RbConfig::CONFIG["host_os"])
|
@@ -130,12 +172,19 @@ module Datadog
|
|
130
172
|
end
|
131
173
|
|
132
174
|
def set_default_tags
|
133
|
-
tracer_span.set_tag(Ext::Test::TAG_SPAN_KIND, Ext::
|
175
|
+
tracer_span.set_tag(Ext::Test::TAG_SPAN_KIND, Ext::Test::SPAN_KIND_TEST)
|
134
176
|
end
|
135
177
|
|
136
178
|
def to_s
|
137
179
|
"#{self.class}(name:#{name},tracer_span:#{@tracer_span})"
|
138
180
|
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
# provides access to global CI recorder for CI models to deactivate themselves
|
185
|
+
def recorder
|
186
|
+
Datadog.send(:components).ci_recorder
|
187
|
+
end
|
139
188
|
end
|
140
189
|
end
|
141
190
|
end
|
data/lib/datadog/ci/test.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "json"
|
4
|
+
|
3
5
|
require_relative "span"
|
4
6
|
|
5
7
|
module Datadog
|
@@ -18,7 +20,7 @@ module Datadog
|
|
18
20
|
def finish
|
19
21
|
super
|
20
22
|
|
21
|
-
|
23
|
+
recorder.deactivate_test
|
22
24
|
end
|
23
25
|
|
24
26
|
# Running test suite that this test is part of (if any).
|
@@ -35,6 +37,8 @@ module Datadog
|
|
35
37
|
get_tag(Ext::Test::TAG_TEST_SUITE_ID)
|
36
38
|
end
|
37
39
|
|
40
|
+
# Name of the running test suite this test belongs to.
|
41
|
+
# @return [String] the name of the test suite.
|
38
42
|
def test_suite_name
|
39
43
|
get_tag(Ext::Test::TAG_SUITE)
|
40
44
|
end
|
@@ -45,11 +49,72 @@ module Datadog
|
|
45
49
|
get_tag(Ext::Test::TAG_TEST_MODULE_ID)
|
46
50
|
end
|
47
51
|
|
48
|
-
# Span id of the running test
|
52
|
+
# Span id of the running test session this test belongs to.
|
49
53
|
# @return [String] the span id of the test session.
|
50
54
|
def test_session_id
|
51
55
|
get_tag(Ext::Test::TAG_TEST_SESSION_ID)
|
52
56
|
end
|
57
|
+
|
58
|
+
# Source file path of the test relative to git repository root.
|
59
|
+
# @return [String] the source file path of the test
|
60
|
+
# @return [nil] if the source file path is not found
|
61
|
+
def source_file
|
62
|
+
get_tag(Ext::Test::TAG_SOURCE_FILE)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Sets the status of the span to "pass".
|
66
|
+
# @return [void]
|
67
|
+
def passed!
|
68
|
+
super
|
69
|
+
|
70
|
+
record_test_result(Ext::Test::Status::PASS)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Sets the status of the span to "fail".
|
74
|
+
# @param [Exception] exception the exception that caused the test to fail.
|
75
|
+
# @return [void]
|
76
|
+
def failed!(exception: nil)
|
77
|
+
super
|
78
|
+
|
79
|
+
record_test_result(Ext::Test::Status::FAIL)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Sets the status of the span to "skip".
|
83
|
+
# @param [Exception] exception the exception that caused the test to fail.
|
84
|
+
# @param [String] reason the reason why the test was skipped.
|
85
|
+
# @return [void]
|
86
|
+
def skipped!(exception: nil, reason: nil)
|
87
|
+
super
|
88
|
+
|
89
|
+
record_test_result(Ext::Test::Status::SKIP)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Sets the parameters for this test (e.g. Cucumber example or RSpec shared specs).
|
93
|
+
# Parameters are needed to compute test fingerprint to distinguish between different tests having same names.
|
94
|
+
#
|
95
|
+
# @param [Hash] arguments the arguments that test accepts as key-value hash
|
96
|
+
# @param [Hash] metadata optional metadata
|
97
|
+
# @return [void]
|
98
|
+
def set_parameters(arguments, metadata = {})
|
99
|
+
return if arguments.nil?
|
100
|
+
|
101
|
+
set_tag(
|
102
|
+
Ext::Test::TAG_PARAMETERS,
|
103
|
+
JSON.generate(
|
104
|
+
{
|
105
|
+
arguments: arguments,
|
106
|
+
metadata: metadata
|
107
|
+
}
|
108
|
+
)
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def record_test_result(datadog_status)
|
115
|
+
suite = test_suite
|
116
|
+
suite.record_test_result(datadog_status) if suite
|
117
|
+
end
|
53
118
|
end
|
54
119
|
end
|
55
120
|
end
|
@@ -17,7 +17,7 @@ module Datadog
|
|
17
17
|
def finish
|
18
18
|
super
|
19
19
|
|
20
|
-
|
20
|
+
recorder.deactivate_test_session
|
21
21
|
end
|
22
22
|
|
23
23
|
# Return the test session's name which is equal to test command used
|
@@ -26,13 +26,21 @@ module Datadog
|
|
26
26
|
get_tag(Ext::Test::TAG_COMMAND)
|
27
27
|
end
|
28
28
|
|
29
|
+
def skipping_tests?
|
30
|
+
get_tag(Ext::Test::TAG_ITR_TEST_SKIPPING_ENABLED) == "true"
|
31
|
+
end
|
32
|
+
|
33
|
+
def code_coverage?
|
34
|
+
get_tag(Ext::Test::TAG_CODE_COVERAGE_ENABLED) == "true"
|
35
|
+
end
|
36
|
+
|
29
37
|
# Return the test session tags that could be inherited by sub-spans
|
30
38
|
# @return [Hash] the tags to be inherited by sub-spans.
|
31
39
|
def inheritable_tags
|
32
40
|
return @inheritable_tags if defined?(@inheritable_tags)
|
33
41
|
|
34
42
|
# this method is not synchronized because it does not iterate over the tags collection, but rather
|
35
|
-
# uses synchronized method to get each tag value
|
43
|
+
# uses synchronized method #get_tag to get each tag value
|
36
44
|
res = {}
|
37
45
|
Ext::Test::INHERITABLE_TAGS.each do |tag|
|
38
46
|
res[tag] = get_tag(tag)
|
@@ -13,12 +13,63 @@ module Datadog
|
|
13
13
|
#
|
14
14
|
# @public_api
|
15
15
|
class TestSuite < ConcurrentSpan
|
16
|
+
def initialize(tracer_span)
|
17
|
+
super
|
18
|
+
|
19
|
+
@test_suite_stats = Hash.new(0)
|
20
|
+
end
|
21
|
+
|
16
22
|
# Finishes this test suite.
|
17
23
|
# @return [void]
|
18
24
|
def finish
|
19
|
-
|
25
|
+
synchronize do
|
26
|
+
# we try to derive test suite status from execution stats if no status was set explicitly
|
27
|
+
set_status_from_stats! if undefined?
|
28
|
+
|
29
|
+
super
|
30
|
+
|
31
|
+
recorder.deactivate_test_suite(name)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# @internal
|
36
|
+
def record_test_result(datadog_test_status)
|
37
|
+
synchronize do
|
38
|
+
@test_suite_stats[datadog_test_status] += 1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# @internal
|
43
|
+
def passed_tests_count
|
44
|
+
synchronize do
|
45
|
+
@test_suite_stats[Ext::Test::Status::PASS]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @internal
|
50
|
+
def skipped_tests_count
|
51
|
+
synchronize do
|
52
|
+
@test_suite_stats[Ext::Test::Status::SKIP]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# @internal
|
57
|
+
def failed_tests_count
|
58
|
+
synchronize do
|
59
|
+
@test_suite_stats[Ext::Test::Status::FAIL]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
20
64
|
|
21
|
-
|
65
|
+
def set_status_from_stats!
|
66
|
+
if failed_tests_count > 0
|
67
|
+
failed!
|
68
|
+
elsif passed_tests_count == 0
|
69
|
+
skipped!
|
70
|
+
else
|
71
|
+
passed!
|
72
|
+
end
|
22
73
|
end
|
23
74
|
end
|
24
75
|
end
|
@@ -11,7 +11,7 @@ module Datadog
|
|
11
11
|
self.active_test = nil
|
12
12
|
end
|
13
13
|
|
14
|
-
def activate_test
|
14
|
+
def activate_test(test)
|
15
15
|
raise "Nested tests are not supported. Currently active test: #{active_test}" unless active_test.nil?
|
16
16
|
|
17
17
|
if block_given?
|
@@ -26,14 +26,8 @@ module Datadog
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
def deactivate_test
|
30
|
-
|
31
|
-
|
32
|
-
if active_test == test
|
33
|
-
self.active_test = nil
|
34
|
-
else
|
35
|
-
raise "Trying to deactivate test #{test}, but currently active test is #{active_test}"
|
36
|
-
end
|
29
|
+
def deactivate_test
|
30
|
+
self.active_test = nil
|
37
31
|
end
|
38
32
|
|
39
33
|
def active_test
|
@@ -23,7 +23,7 @@ module Datadog
|
|
23
23
|
skip_tracing(block)
|
24
24
|
end
|
25
25
|
|
26
|
-
def trace(
|
26
|
+
def trace(type, span_name, tags: {}, &block)
|
27
27
|
skip_tracing(block)
|
28
28
|
end
|
29
29
|
|
@@ -42,30 +42,10 @@ module Datadog
|
|
42
42
|
def active_test_suite(test_suite_name)
|
43
43
|
end
|
44
44
|
|
45
|
-
def deactivate_test(test)
|
46
|
-
end
|
47
|
-
|
48
|
-
def deactivate_test_session
|
49
|
-
end
|
50
|
-
|
51
|
-
def deactivate_test_module
|
52
|
-
end
|
53
|
-
|
54
|
-
def deactivate_test_suite(test_suite_name)
|
55
|
-
end
|
56
|
-
|
57
45
|
private
|
58
46
|
|
59
47
|
def skip_tracing(block = nil)
|
60
|
-
if block
|
61
|
-
block.call(null_span)
|
62
|
-
else
|
63
|
-
null_span
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def null_span
|
68
|
-
@null_span ||= NullSpan.new
|
48
|
+
block.call(nil) if block
|
69
49
|
end
|
70
50
|
end
|
71
51
|
end
|