datadog-ci 1.2.0 → 1.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -2
- data/lib/datadog/ci/configuration/components.rb +30 -3
- data/lib/datadog/ci/contrib/cucumber/formatter.rb +13 -9
- data/lib/datadog/ci/contrib/minitest/runnable.rb +5 -1
- data/lib/datadog/ci/contrib/minitest/runner.rb +6 -2
- data/lib/datadog/ci/contrib/minitest/test.rb +7 -3
- data/lib/datadog/ci/contrib/rspec/example.rb +6 -2
- data/lib/datadog/ci/contrib/rspec/example_group.rb +5 -1
- data/lib/datadog/ci/contrib/rspec/knapsack_pro/runner.rb +6 -2
- data/lib/datadog/ci/contrib/rspec/runner.rb +6 -2
- data/lib/datadog/ci/ext/environment/providers/appveyor.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/aws_code_pipeline.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/azure.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/bitbucket.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/bitrise.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/buddy.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/buildkite.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/circleci.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/codefresh.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/github_actions.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/gitlab.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/jenkins.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/teamcity.rb +1 -1
- data/lib/datadog/ci/ext/environment/providers/travis.rb +1 -1
- data/lib/datadog/ci/ext/environment.rb +17 -0
- data/lib/datadog/ci/ext/telemetry.rb +120 -0
- data/lib/datadog/ci/git/local_repository.rb +116 -25
- data/lib/datadog/ci/git/search_commits.rb +20 -1
- data/lib/datadog/ci/git/telemetry.rb +37 -0
- data/lib/datadog/ci/git/tree_uploader.rb +7 -0
- data/lib/datadog/ci/git/upload_packfile.rb +22 -1
- data/lib/datadog/ci/test.rb +5 -0
- data/lib/datadog/ci/test_optimisation/component.rb +16 -2
- data/lib/datadog/ci/test_optimisation/coverage/transport.rb +10 -1
- data/lib/datadog/ci/test_optimisation/skippable.rb +24 -0
- data/lib/datadog/ci/test_optimisation/telemetry.rb +56 -0
- data/lib/datadog/ci/test_visibility/component.rb +95 -235
- data/lib/datadog/ci/test_visibility/context.rb +274 -0
- data/lib/datadog/ci/test_visibility/{context → store}/global.rb +1 -1
- data/lib/datadog/ci/test_visibility/{context → store}/local.rb +1 -1
- data/lib/datadog/ci/test_visibility/telemetry.rb +69 -0
- data/lib/datadog/ci/test_visibility/transport.rb +8 -9
- data/lib/datadog/ci/transport/adapters/net.rb +42 -11
- data/lib/datadog/ci/transport/adapters/net_http_client.rb +17 -0
- data/lib/datadog/ci/transport/adapters/telemetry_webmock_safe_adapter.rb +28 -0
- data/lib/datadog/ci/transport/event_platform_transport.rb +42 -5
- data/lib/datadog/ci/transport/http.rb +49 -21
- data/lib/datadog/ci/transport/remote_settings_api.rb +39 -1
- data/lib/datadog/ci/transport/telemetry.rb +93 -0
- data/lib/datadog/ci/utils/identity.rb +20 -0
- data/lib/datadog/ci/utils/parsing.rb +2 -1
- data/lib/datadog/ci/utils/telemetry.rb +23 -0
- data/lib/datadog/ci/version.rb +1 -1
- data/lib/datadog/ci.rb +30 -0
- metadata +16 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57da167788887f67dc501a3dc2869c425754fec3cdefa45770af22364003fb20
|
4
|
+
data.tar.gz: ed6645a822db10fbae793c5b226b9d41ca4dbea67449f545135f2571be3894c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4586bbf8a10b5bf2b262bafefd222ef981624ced261755bd9d43652506400f6b939e5cd3595b7af0c66a193581328937aabe5b9246efd4cb3a0fa088b9e0ccf
|
7
|
+
data.tar.gz: 4169cf67306d9d080e264897ed2cffb5103a9b98ca176fea2784ff3293d4b9dd3decd62df3848b2a7ade783f5dfe6925b86fa7d4727b45de51764af5bc6e1b4a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.3.0] - 2024-07-30
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
* Add test_session metric ([#207][])
|
8
|
+
* API metrics ([#206][])
|
9
|
+
* git commands telemetry ([#205][])
|
10
|
+
* implement ITR metrics for internal telemetry ([#204][])
|
11
|
+
* Implement code coverage metrics for internal telemetry ([#203][])
|
12
|
+
* Implement manual_api_events metric ([#202][])
|
13
|
+
* HTTP transport metrics and minor telemetry tweaks ([#201][])
|
14
|
+
* Send event_created and event_finished metrics for internal telemetry ([#200][])
|
15
|
+
|
3
16
|
## [1.2.0] - 2024-07-16
|
4
17
|
|
5
18
|
### Changed
|
@@ -277,7 +290,8 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
277
290
|
|
278
291
|
- Ruby versions < 2.7 no longer supported ([#8][])
|
279
292
|
|
280
|
-
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.
|
293
|
+
[Unreleased]: https://github.com/DataDog/datadog-ci-rb/compare/v1.3.0...main
|
294
|
+
[1.3.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.2.0...v1.3.0
|
281
295
|
[1.2.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.1.0...v1.2.0
|
282
296
|
[1.1.0]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.1...v1.1.0
|
283
297
|
[1.0.1]: https://github.com/DataDog/datadog-ci-rb/compare/v1.0.0...v1.0.1
|
@@ -391,4 +405,12 @@ Currently test suite level visibility is not used by our instrumentation: it wil
|
|
391
405
|
[#189]: https://github.com/DataDog/datadog-ci-rb/issues/189
|
392
406
|
[#190]: https://github.com/DataDog/datadog-ci-rb/issues/190
|
393
407
|
[#193]: https://github.com/DataDog/datadog-ci-rb/issues/193
|
394
|
-
[#197]: https://github.com/DataDog/datadog-ci-rb/issues/197
|
408
|
+
[#197]: https://github.com/DataDog/datadog-ci-rb/issues/197
|
409
|
+
[#200]: https://github.com/DataDog/datadog-ci-rb/issues/200
|
410
|
+
[#201]: https://github.com/DataDog/datadog-ci-rb/issues/201
|
411
|
+
[#202]: https://github.com/DataDog/datadog-ci-rb/issues/202
|
412
|
+
[#203]: https://github.com/DataDog/datadog-ci-rb/issues/203
|
413
|
+
[#204]: https://github.com/DataDog/datadog-ci-rb/issues/204
|
414
|
+
[#205]: https://github.com/DataDog/datadog-ci-rb/issues/205
|
415
|
+
[#206]: https://github.com/DataDog/datadog-ci-rb/issues/206
|
416
|
+
[#207]: https://github.com/DataDog/datadog-ci-rb/issues/207
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "datadog/core/telemetry/ext"
|
4
|
+
|
3
5
|
require_relative "../ext/settings"
|
4
6
|
require_relative "../git/tree_uploader"
|
5
7
|
require_relative "../test_optimisation/component"
|
@@ -11,8 +13,11 @@ require_relative "../test_visibility/null_component"
|
|
11
13
|
require_relative "../test_visibility/serializers/factories/test_level"
|
12
14
|
require_relative "../test_visibility/serializers/factories/test_suite_level"
|
13
15
|
require_relative "../test_visibility/transport"
|
16
|
+
require_relative "../transport/adapters/telemetry_webmock_safe_adapter"
|
14
17
|
require_relative "../transport/api/builder"
|
15
18
|
require_relative "../transport/remote_settings_api"
|
19
|
+
require_relative "../utils/identity"
|
20
|
+
require_relative "../utils/parsing"
|
16
21
|
require_relative "../utils/test_run"
|
17
22
|
require_relative "../worker"
|
18
23
|
|
@@ -59,9 +64,7 @@ module Datadog
|
|
59
64
|
return unless settings.ci.enabled
|
60
65
|
|
61
66
|
# Configure datadog gem for test visibility mode
|
62
|
-
|
63
|
-
# Deactivate telemetry
|
64
|
-
settings.telemetry.enabled = false
|
67
|
+
configure_telemetry(settings)
|
65
68
|
|
66
69
|
# Test visibility uses its own remote settings
|
67
70
|
settings.remote.enabled = false
|
@@ -246,6 +249,30 @@ module Datadog
|
|
246
249
|
end
|
247
250
|
end
|
248
251
|
|
252
|
+
def configure_telemetry(settings)
|
253
|
+
# in development environment Datadog's telemetry is disabled by default
|
254
|
+
# for test visibility we want to enable it by default unless explicitly disabled
|
255
|
+
# NOTE: before agentless mode is released, we only enable telemetry when running with Datadog Agent
|
256
|
+
env_telemetry_enabled = ENV[Core::Telemetry::Ext::ENV_ENABLED]
|
257
|
+
settings.telemetry.enabled = !settings.ci.agentless_mode_enabled &&
|
258
|
+
(env_telemetry_enabled.nil? || Utils::Parsing.convert_to_bool(env_telemetry_enabled))
|
259
|
+
|
260
|
+
return unless settings.telemetry.enabled
|
261
|
+
|
262
|
+
begin
|
263
|
+
require "datadog/core/environment/identity"
|
264
|
+
require "datadog/core/telemetry/http/adapters/net"
|
265
|
+
|
266
|
+
# patch gem's identity to report datadog-ci library version instead of datadog gem version
|
267
|
+
Core::Environment::Identity.include(CI::Utils::Identity)
|
268
|
+
|
269
|
+
# patch gem's telemetry transport layer to use Net::HTTP instead of WebMock's Net::HTTP
|
270
|
+
Core::Telemetry::Http::Adapters::Net.include(CI::Transport::Adapters::TelemetryWebmockSafeAdapter)
|
271
|
+
rescue => e
|
272
|
+
Datadog.logger.warn("Failed to patch Datadog gem's telemetry layer: #{e}")
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
249
276
|
def timecop?
|
250
277
|
Gem.loaded_specs.key?("timecop") || !!defined?(Timecop)
|
251
278
|
end
|
@@ -35,14 +35,14 @@ module Datadog
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def on_test_run_started(event)
|
38
|
-
|
38
|
+
test_visibility_component.start_test_session(
|
39
39
|
tags: {
|
40
40
|
CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
|
41
41
|
CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::Cucumber::Integration.version.to_s
|
42
42
|
},
|
43
43
|
service: configuration[:service_name]
|
44
44
|
)
|
45
|
-
|
45
|
+
test_visibility_component.start_test_module(Ext::FRAMEWORK)
|
46
46
|
end
|
47
47
|
|
48
48
|
def on_test_run_finished(event)
|
@@ -70,7 +70,7 @@ module Datadog
|
|
70
70
|
|
71
71
|
start_test_suite(test_suite_name) unless same_test_suite_as_current?(test_suite_name)
|
72
72
|
|
73
|
-
test_span =
|
73
|
+
test_span = test_visibility_component.trace_test(
|
74
74
|
event.test_case.name,
|
75
75
|
test_suite_name,
|
76
76
|
tags: tags,
|
@@ -82,7 +82,7 @@ module Datadog
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def on_test_case_finished(event)
|
85
|
-
test_span =
|
85
|
+
test_span = test_visibility_component.active_test
|
86
86
|
return if test_span.nil?
|
87
87
|
|
88
88
|
finish_span(test_span, event.result)
|
@@ -90,11 +90,11 @@ module Datadog
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def on_test_step_started(event)
|
93
|
-
|
93
|
+
test_visibility_component.trace(event.test_step.to_s, type: Ext::STEP_SPAN_TYPE)
|
94
94
|
end
|
95
95
|
|
96
96
|
def on_test_step_finished(event)
|
97
|
-
current_step_span =
|
97
|
+
current_step_span = test_visibility_component.active_span
|
98
98
|
return if current_step_span.nil?
|
99
99
|
|
100
100
|
finish_span(current_step_span, event.result)
|
@@ -130,8 +130,8 @@ module Datadog
|
|
130
130
|
def finish_session(result)
|
131
131
|
finish_current_test_suite
|
132
132
|
|
133
|
-
test_session =
|
134
|
-
test_module =
|
133
|
+
test_session = test_visibility_component.active_test_session
|
134
|
+
test_module = test_visibility_component.active_test_module
|
135
135
|
|
136
136
|
return unless test_session && test_module
|
137
137
|
|
@@ -150,7 +150,7 @@ module Datadog
|
|
150
150
|
def start_test_suite(test_suite_name)
|
151
151
|
finish_current_test_suite
|
152
152
|
|
153
|
-
@current_test_suite =
|
153
|
+
@current_test_suite = test_visibility_component.start_test_suite(test_suite_name)
|
154
154
|
end
|
155
155
|
|
156
156
|
def finish_current_test_suite
|
@@ -197,6 +197,10 @@ module Datadog
|
|
197
197
|
def configuration
|
198
198
|
Datadog.configuration.ci[:cucumber]
|
199
199
|
end
|
200
|
+
|
201
|
+
def test_visibility_component
|
202
|
+
Datadog.send(:components).test_visibility
|
203
|
+
end
|
200
204
|
end
|
201
205
|
end
|
202
206
|
end
|
@@ -19,7 +19,7 @@ module Datadog
|
|
19
19
|
|
20
20
|
test_suite_name = Helpers.test_suite_name(self, method)
|
21
21
|
|
22
|
-
test_suite =
|
22
|
+
test_suite = test_visibility_component.start_test_suite(test_suite_name)
|
23
23
|
|
24
24
|
results = super
|
25
25
|
return results unless test_suite
|
@@ -34,6 +34,10 @@ module Datadog
|
|
34
34
|
def datadog_configuration
|
35
35
|
Datadog.configuration.ci[:minitest]
|
36
36
|
end
|
37
|
+
|
38
|
+
def test_visibility_component
|
39
|
+
Datadog.send(:components).test_visibility
|
40
|
+
end
|
37
41
|
end
|
38
42
|
end
|
39
43
|
end
|
@@ -18,14 +18,14 @@ module Datadog
|
|
18
18
|
|
19
19
|
return unless datadog_configuration[:enabled]
|
20
20
|
|
21
|
-
|
21
|
+
test_visibility_component.start_test_session(
|
22
22
|
tags: {
|
23
23
|
CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
|
24
24
|
CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::Minitest::Integration.version.to_s
|
25
25
|
},
|
26
26
|
service: datadog_configuration[:service_name]
|
27
27
|
)
|
28
|
-
|
28
|
+
test_visibility_component.start_test_module(Ext::FRAMEWORK)
|
29
29
|
end
|
30
30
|
|
31
31
|
private
|
@@ -33,6 +33,10 @@ module Datadog
|
|
33
33
|
def datadog_configuration
|
34
34
|
Datadog.configuration.ci[:minitest]
|
35
35
|
end
|
36
|
+
|
37
|
+
def test_visibility_component
|
38
|
+
Datadog.send(:components).test_visibility
|
39
|
+
end
|
36
40
|
end
|
37
41
|
end
|
38
42
|
end
|
@@ -26,12 +26,12 @@ module Datadog
|
|
26
26
|
test_suite_name = "#{test_suite_name} (#{name} concurrently)"
|
27
27
|
|
28
28
|
# for parallel execution we need to start a new test suite for each test
|
29
|
-
|
29
|
+
test_visibility_component.start_test_suite(test_suite_name)
|
30
30
|
end
|
31
31
|
|
32
32
|
source_file, line_number = method(name).source_location
|
33
33
|
|
34
|
-
test_span =
|
34
|
+
test_span = test_visibility_component.trace_test(
|
35
35
|
name,
|
36
36
|
test_suite_name,
|
37
37
|
tags: {
|
@@ -47,7 +47,7 @@ module Datadog
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def after_teardown
|
50
|
-
test_span =
|
50
|
+
test_span = test_visibility_component.active_test
|
51
51
|
return super unless test_span
|
52
52
|
|
53
53
|
finish_with_result(test_span, result_code)
|
@@ -77,6 +77,10 @@ module Datadog
|
|
77
77
|
def datadog_configuration
|
78
78
|
Datadog.configuration.ci[:minitest]
|
79
79
|
end
|
80
|
+
|
81
|
+
def test_visibility_component
|
82
|
+
Datadog.send(:components).test_visibility
|
83
|
+
end
|
80
84
|
end
|
81
85
|
|
82
86
|
module ClassMethods
|
@@ -34,10 +34,10 @@ module Datadog
|
|
34
34
|
|
35
35
|
if ci_queue?
|
36
36
|
suite_name = "#{suite_name} (ci-queue running example [#{test_name}])"
|
37
|
-
test_suite_span =
|
37
|
+
test_suite_span = test_visibility_component.start_test_suite(suite_name)
|
38
38
|
end
|
39
39
|
|
40
|
-
|
40
|
+
test_visibility_component.trace_test(
|
41
41
|
test_name,
|
42
42
|
suite_name,
|
43
43
|
tags: {
|
@@ -99,6 +99,10 @@ module Datadog
|
|
99
99
|
Datadog.configuration.ci[:rspec]
|
100
100
|
end
|
101
101
|
|
102
|
+
def test_visibility_component
|
103
|
+
Datadog.send(:components).test_visibility
|
104
|
+
end
|
105
|
+
|
102
106
|
def ci_queue?
|
103
107
|
!!defined?(::RSpec::Queue::ExampleExtension) &&
|
104
108
|
self.class.ancestors.include?(::RSpec::Queue::ExampleExtension)
|
@@ -21,7 +21,7 @@ module Datadog
|
|
21
21
|
return super unless top_level?
|
22
22
|
|
23
23
|
suite_name = "#{description} at #{file_path}"
|
24
|
-
test_suite =
|
24
|
+
test_suite = test_visibility_component.start_test_suite(suite_name)
|
25
25
|
|
26
26
|
success = super
|
27
27
|
return success unless test_suite
|
@@ -44,6 +44,10 @@ module Datadog
|
|
44
44
|
def datadog_configuration
|
45
45
|
Datadog.configuration.ci[:rspec]
|
46
46
|
end
|
47
|
+
|
48
|
+
def test_visibility_component
|
49
|
+
Datadog.send(:components).test_visibility
|
50
|
+
end
|
47
51
|
end
|
48
52
|
end
|
49
53
|
end
|
@@ -18,7 +18,7 @@ module Datadog
|
|
18
18
|
return super if ::RSpec.configuration.dry_run?
|
19
19
|
return super unless datadog_configuration[:enabled]
|
20
20
|
|
21
|
-
test_session =
|
21
|
+
test_session = test_visibility_component.start_test_session(
|
22
22
|
tags: {
|
23
23
|
CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
|
24
24
|
CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::RSpec::Integration.version.to_s
|
@@ -26,7 +26,7 @@ module Datadog
|
|
26
26
|
service: datadog_configuration[:service_name]
|
27
27
|
)
|
28
28
|
|
29
|
-
test_module =
|
29
|
+
test_module = test_visibility_component.start_test_module(Ext::FRAMEWORK)
|
30
30
|
|
31
31
|
result = super
|
32
32
|
return result unless test_module && test_session
|
@@ -49,6 +49,10 @@ module Datadog
|
|
49
49
|
def datadog_configuration
|
50
50
|
Datadog.configuration.ci[:rspec]
|
51
51
|
end
|
52
|
+
|
53
|
+
def test_visibility_component
|
54
|
+
Datadog.send(:components).test_visibility
|
55
|
+
end
|
52
56
|
end
|
53
57
|
end
|
54
58
|
end
|
@@ -18,7 +18,7 @@ module Datadog
|
|
18
18
|
return super if ::RSpec.configuration.dry_run?
|
19
19
|
return super unless datadog_configuration[:enabled]
|
20
20
|
|
21
|
-
test_session =
|
21
|
+
test_session = test_visibility_component.start_test_session(
|
22
22
|
tags: {
|
23
23
|
CI::Ext::Test::TAG_FRAMEWORK => Ext::FRAMEWORK,
|
24
24
|
CI::Ext::Test::TAG_FRAMEWORK_VERSION => CI::Contrib::RSpec::Integration.version.to_s
|
@@ -26,7 +26,7 @@ module Datadog
|
|
26
26
|
service: datadog_configuration[:service_name]
|
27
27
|
)
|
28
28
|
|
29
|
-
test_module =
|
29
|
+
test_module = test_visibility_component.start_test_module(Ext::FRAMEWORK)
|
30
30
|
|
31
31
|
result = super
|
32
32
|
return result unless test_module && test_session
|
@@ -49,6 +49,10 @@ module Datadog
|
|
49
49
|
def datadog_configuration
|
50
50
|
Datadog.configuration.ci[:rspec]
|
51
51
|
end
|
52
|
+
|
53
|
+
def test_visibility_component
|
54
|
+
Datadog.send(:components).test_visibility
|
55
|
+
end
|
52
56
|
end
|
53
57
|
end
|
54
58
|
end
|
@@ -23,6 +23,23 @@ module Datadog
|
|
23
23
|
TAG_NODE_NAME = "ci.node.name"
|
24
24
|
TAG_CI_ENV_VARS = "_dd.ci.env_vars"
|
25
25
|
|
26
|
+
module Provider
|
27
|
+
APPVEYOR = "appveyor"
|
28
|
+
AZURE = "azurepipelines"
|
29
|
+
AWS = "awscodepipeline"
|
30
|
+
BITBUCKET = "bitbucket"
|
31
|
+
BITRISE = "bitrise"
|
32
|
+
BUDDYCI = "buddy"
|
33
|
+
BUILDKITE = "buildkite"
|
34
|
+
CIRCLECI = "circleci"
|
35
|
+
CODEFRESH = "codefresh"
|
36
|
+
GITHUB = "github"
|
37
|
+
GITLAB = "gitlab"
|
38
|
+
JENKINS = "jenkins"
|
39
|
+
TEAMCITY = "teamcity"
|
40
|
+
TRAVISCI = "travisci"
|
41
|
+
end
|
42
|
+
|
26
43
|
POSSIBLE_BUNDLE_LOCATIONS = %w[vendor/bundle .bundle].freeze
|
27
44
|
|
28
45
|
module_function
|