ddtrace 0.12.0 → 0.12.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +456 -0
- data/.circleci/images/primary/Dockerfile-1.9.3 +69 -0
- data/.circleci/images/primary/Dockerfile-2.0.0 +69 -0
- data/.circleci/images/primary/Dockerfile-2.1.10 +69 -0
- data/.circleci/images/primary/Dockerfile-2.2.10 +69 -0
- data/.circleci/images/primary/Dockerfile-2.3.7 +73 -0
- data/.circleci/images/primary/Dockerfile-2.4.4 +73 -0
- data/.env +21 -11
- data/.rubocop.yml +4 -1
- data/Appraisals +439 -66
- data/CHANGELOG.md +25 -2
- data/Rakefile +256 -75
- data/ddtrace.gemspec +6 -6
- data/docker-compose.yml +222 -37
- data/docs/GettingStarted.md +13 -1
- data/gemfiles/contrib_old.gemfile +1 -0
- data/gemfiles/rails30_postgres.gemfile +1 -0
- data/gemfiles/rails30_postgres_sidekiq.gemfile +1 -0
- data/gemfiles/rails32_mysql2.gemfile +1 -0
- data/gemfiles/rails32_postgres.gemfile +1 -0
- data/gemfiles/rails32_postgres_redis.gemfile +1 -0
- data/gemfiles/rails32_postgres_sidekiq.gemfile +1 -0
- data/gemfiles/rails5_mysql2.gemfile +1 -1
- data/gemfiles/rails5_postgres.gemfile +1 -1
- data/gemfiles/rails5_postgres_redis.gemfile +1 -1
- data/gemfiles/rails5_postgres_sidekiq.gemfile +1 -1
- data/lib/ddtrace/configuration.rb +2 -2
- data/lib/ddtrace/contrib/active_record/patcher.rb +10 -10
- data/lib/ddtrace/contrib/aws/instrumentation.rb +2 -2
- data/lib/ddtrace/contrib/elasticsearch/patcher.rb +2 -2
- data/lib/ddtrace/contrib/http/patcher.rb +18 -16
- data/lib/ddtrace/contrib/rails/action_controller_patch.rb +77 -0
- data/lib/ddtrace/contrib/rails/action_view.rb +0 -65
- data/lib/ddtrace/contrib/rails/active_support.rb +9 -8
- data/lib/ddtrace/contrib/rails/core_extensions.rb +74 -115
- data/lib/ddtrace/tracer.rb +4 -1
- data/lib/ddtrace/utils.rb +10 -2
- data/lib/ddtrace/version.rb +1 -1
- metadata +11 -4
- data/circle.yml +0 -69
@@ -6,6 +6,11 @@ module Datadog
|
|
6
6
|
module RailsRendererPatcher
|
7
7
|
include Datadog::Patcher
|
8
8
|
|
9
|
+
SPAN_NAME_RENDER_PARTIAL = 'rails.render_partial'.freeze
|
10
|
+
SPAN_NAME_RENDER_TEMPLATE = 'rails.render_template'.freeze
|
11
|
+
TAG_LAYOUT = 'rails.layout'.freeze
|
12
|
+
TAG_TEMPLATE_NAME = 'rails.template_name'.freeze
|
13
|
+
|
9
14
|
module_function
|
10
15
|
|
11
16
|
def patch_renderer
|
@@ -24,25 +29,22 @@ module Datadog
|
|
24
29
|
end
|
25
30
|
|
26
31
|
def patch_template_renderer(klass)
|
32
|
+
# rubocop:disable Metrics/BlockLength
|
27
33
|
do_once(:patch_template_renderer) do
|
28
34
|
klass.class_eval do
|
29
35
|
def render_with_datadog(*args, &block)
|
30
|
-
#
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
# NOTE: This check exists purely for Rails 3.0 compatibility.
|
37
|
+
# The 'if' part can be removed when support for Rails 3.0 is removed.
|
38
|
+
if active_datadog_span
|
39
|
+
render_without_datadog(*args, &block)
|
40
|
+
else
|
41
|
+
datadog_tracer.trace(
|
42
|
+
Datadog::RailsRendererPatcher::SPAN_NAME_RENDER_TEMPLATE,
|
43
|
+
span_type: Datadog::Ext::HTTP::TEMPLATE
|
44
|
+
) do |span|
|
45
|
+
with_datadog_span(span) { render_without_datadog(*args, &block) }
|
46
|
+
end
|
36
47
|
end
|
37
|
-
|
38
|
-
render_without_datadog(*args, &block)
|
39
|
-
rescue Exception => e
|
40
|
-
# attach the exception to the tracing context if any
|
41
|
-
@tracing_context[:exception] = e
|
42
|
-
raise e
|
43
|
-
ensure
|
44
|
-
# ensure that the template `Span` is finished even during exceptions
|
45
|
-
Datadog::Contrib::Rails::ActionView.finish_render_template(tracing_context: @tracing_context)
|
46
48
|
end
|
47
49
|
|
48
50
|
def render_template_with_datadog(*args)
|
@@ -60,8 +62,19 @@ module Datadog
|
|
60
62
|
else
|
61
63
|
layout_name.try(:[], 'virtual_path')
|
62
64
|
end
|
63
|
-
|
64
|
-
|
65
|
+
if template_name
|
66
|
+
active_datadog_span.set_tag(
|
67
|
+
Datadog::RailsRendererPatcher::TAG_TEMPLATE_NAME,
|
68
|
+
template_name
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
if layout
|
73
|
+
active_datadog_span.set_tag(
|
74
|
+
Datadog::RailsRendererPatcher::TAG_LAYOUT,
|
75
|
+
layout
|
76
|
+
)
|
77
|
+
end
|
65
78
|
rescue StandardError => e
|
66
79
|
Datadog::Tracer.log.debug(e.message)
|
67
80
|
end
|
@@ -70,6 +83,21 @@ module Datadog
|
|
70
83
|
render_template_without_datadog(*args)
|
71
84
|
end
|
72
85
|
|
86
|
+
private
|
87
|
+
|
88
|
+
attr_accessor :active_datadog_span
|
89
|
+
|
90
|
+
def datadog_tracer
|
91
|
+
Datadog.configuration[:rails][:tracer]
|
92
|
+
end
|
93
|
+
|
94
|
+
def with_datadog_span(span)
|
95
|
+
self.active_datadog_span = span
|
96
|
+
yield
|
97
|
+
ensure
|
98
|
+
self.active_datadog_span = nil
|
99
|
+
end
|
100
|
+
|
73
101
|
# method aliasing to patch the class
|
74
102
|
alias_method :render_without_datadog, :render
|
75
103
|
alias_method :render, :render_with_datadog
|
@@ -90,30 +118,23 @@ module Datadog
|
|
90
118
|
do_once(:patch_partial_renderer) do
|
91
119
|
klass.class_eval do
|
92
120
|
def render_with_datadog(*args, &block)
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
rescue Exception => e
|
100
|
-
# attach the exception to the tracing context if any
|
101
|
-
tracing_contexts[current_span_id][:exception] = e
|
102
|
-
raise e
|
103
|
-
ensure
|
104
|
-
# Ensure that the template `Span` is finished even during exceptions
|
105
|
-
# Remove the existing tracing context (to avoid leaks)
|
106
|
-
tracing_contexts.delete(current_span_id)
|
107
|
-
|
108
|
-
# Then finish the span associated with the context
|
109
|
-
Datadog::Contrib::Rails::ActionView.finish_render_partial(tracing_context: tracing_context)
|
121
|
+
datadog_tracer.trace(
|
122
|
+
Datadog::RailsRendererPatcher::SPAN_NAME_RENDER_PARTIAL,
|
123
|
+
span_type: Datadog::Ext::HTTP::TEMPLATE
|
124
|
+
) do |span|
|
125
|
+
with_datadog_span(span) { render_without_datadog(*args) }
|
126
|
+
end
|
110
127
|
end
|
111
128
|
|
112
129
|
def render_partial_with_datadog(*args)
|
113
130
|
begin
|
114
|
-
# update the tracing context with computed values before the rendering
|
115
131
|
template_name = Datadog::Contrib::Rails::Utils.normalize_template_name(@template.try('identifier'))
|
116
|
-
|
132
|
+
if template_name
|
133
|
+
active_datadog_span.set_tag(
|
134
|
+
Datadog::RailsRendererPatcher::TAG_TEMPLATE_NAME,
|
135
|
+
template_name
|
136
|
+
)
|
137
|
+
end
|
117
138
|
rescue StandardError => e
|
118
139
|
Datadog::Tracer.log.debug(e.message)
|
119
140
|
end
|
@@ -122,15 +143,19 @@ module Datadog
|
|
122
143
|
render_partial_without_datadog(*args)
|
123
144
|
end
|
124
145
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
146
|
+
private
|
147
|
+
|
148
|
+
attr_accessor :active_datadog_span
|
149
|
+
|
150
|
+
def datadog_tracer
|
151
|
+
Datadog.configuration[:rails][:tracer]
|
130
152
|
end
|
131
153
|
|
132
|
-
def
|
133
|
-
|
154
|
+
def with_datadog_span(span)
|
155
|
+
self.active_datadog_span = span
|
156
|
+
yield
|
157
|
+
ensure
|
158
|
+
self.active_datadog_span = nil
|
134
159
|
end
|
135
160
|
|
136
161
|
# method aliasing to patch the class
|
@@ -157,79 +182,9 @@ module Datadog
|
|
157
182
|
|
158
183
|
def patch_process_action
|
159
184
|
do_once(:patch_process_action) do
|
160
|
-
|
161
|
-
# Patch Rails controller base class
|
162
|
-
::ActionController::Metal.send(:prepend, ActionControllerPatch)
|
163
|
-
else
|
164
|
-
# Rewrite module that gets composed into the Rails controller base class
|
165
|
-
::ActionController::Instrumentation.class_eval do
|
166
|
-
def process_action_with_datadog(*args)
|
167
|
-
# mutable payload with a tracing context that is used in two different
|
168
|
-
# signals; it propagates the request span so that it can be finished
|
169
|
-
# no matter what
|
170
|
-
payload = {
|
171
|
-
controller: self.class,
|
172
|
-
action: action_name,
|
173
|
-
headers: {
|
174
|
-
# The exception this controller was given in the request,
|
175
|
-
# which is typical if the controller is configured to handle exceptions.
|
176
|
-
request_exception: request.headers['action_dispatch.exception']
|
177
|
-
},
|
178
|
-
tracing_context: {}
|
179
|
-
}
|
180
|
-
|
181
|
-
begin
|
182
|
-
# process and catch request exceptions
|
183
|
-
Datadog::Contrib::Rails::ActionController.start_processing(payload)
|
184
|
-
result = process_action_without_datadog(*args)
|
185
|
-
payload[:status] = response.status
|
186
|
-
result
|
187
|
-
rescue Exception => e
|
188
|
-
payload[:exception] = [e.class.name, e.message]
|
189
|
-
payload[:exception_object] = e
|
190
|
-
raise e
|
191
|
-
end
|
192
|
-
ensure
|
193
|
-
Datadog::Contrib::Rails::ActionController.finish_processing(payload)
|
194
|
-
end
|
185
|
+
require 'ddtrace/contrib/rails/action_controller_patch'
|
195
186
|
|
196
|
-
|
197
|
-
alias_method :process_action, :process_action_with_datadog
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
# ActionController patch for Ruby 2.0+
|
204
|
-
module ActionControllerPatch
|
205
|
-
def process_action(*args)
|
206
|
-
# mutable payload with a tracing context that is used in two different
|
207
|
-
# signals; it propagates the request span so that it can be finished
|
208
|
-
# no matter what
|
209
|
-
payload = {
|
210
|
-
controller: self.class,
|
211
|
-
action: action_name,
|
212
|
-
headers: {
|
213
|
-
# The exception this controller was given in the request,
|
214
|
-
# which is typical if the controller is configured to handle exceptions.
|
215
|
-
request_exception: request.headers['action_dispatch.exception']
|
216
|
-
},
|
217
|
-
tracing_context: {}
|
218
|
-
}
|
219
|
-
|
220
|
-
begin
|
221
|
-
# process and catch request exceptions
|
222
|
-
Datadog::Contrib::Rails::ActionController.start_processing(payload)
|
223
|
-
result = super(*args)
|
224
|
-
payload[:status] = response.status
|
225
|
-
result
|
226
|
-
rescue Exception => e
|
227
|
-
payload[:exception] = [e.class.name, e.message]
|
228
|
-
payload[:exception_object] = e
|
229
|
-
raise e
|
230
|
-
end
|
231
|
-
ensure
|
232
|
-
Datadog::Contrib::Rails::ActionController.finish_processing(payload)
|
187
|
+
::ActionController::Metal.send(:include, Datadog::Contrib::Rails::ActionControllerPatch)
|
233
188
|
end
|
234
189
|
end
|
235
190
|
end
|
@@ -270,6 +225,7 @@ module Datadog
|
|
270
225
|
do_once(:patch_cache_store_read) do
|
271
226
|
cache_store_class(:read).class_eval do
|
272
227
|
alias_method :read_without_datadog, :read
|
228
|
+
|
273
229
|
def read(*args, &block)
|
274
230
|
payload = {
|
275
231
|
action: 'GET',
|
@@ -297,6 +253,7 @@ module Datadog
|
|
297
253
|
do_once(:patch_cache_store_fetch) do
|
298
254
|
cache_store_class(:fetch).class_eval do
|
299
255
|
alias_method :fetch_without_datadog, :fetch
|
256
|
+
|
300
257
|
def fetch(*args, &block)
|
301
258
|
payload = {
|
302
259
|
action: 'GET',
|
@@ -324,6 +281,7 @@ module Datadog
|
|
324
281
|
do_once(:patch_cache_store_write) do
|
325
282
|
cache_store_class(:write).class_eval do
|
326
283
|
alias_method :write_without_datadog, :write
|
284
|
+
|
327
285
|
def write(*args, &block)
|
328
286
|
payload = {
|
329
287
|
action: 'SET',
|
@@ -351,6 +309,7 @@ module Datadog
|
|
351
309
|
do_once(:patch_cache_store_delete) do
|
352
310
|
cache_store_class(:delete).class_eval do
|
353
311
|
alias_method :delete_without_datadog, :delete
|
312
|
+
|
354
313
|
def delete(*args, &block)
|
355
314
|
payload = {
|
356
315
|
action: 'DELETE',
|
data/lib/ddtrace/tracer.rb
CHANGED
@@ -23,6 +23,8 @@ module Datadog
|
|
23
23
|
attr_accessor :enabled, :writer
|
24
24
|
attr_writer :default_service
|
25
25
|
|
26
|
+
ALLOWED_SPAN_OPTIONS = [:service, :resource, :span_type].freeze
|
27
|
+
|
26
28
|
# Global, memoized, lazy initialized instance of a logger that is used within the the Datadog
|
27
29
|
# namespace. This logger outputs to +STDOUT+ by default, and is considered thread-safe.
|
28
30
|
def self.log
|
@@ -204,12 +206,13 @@ module Datadog
|
|
204
206
|
# * +tags+: extra tags which should be added to the span.
|
205
207
|
def start_span(name, options = {})
|
206
208
|
start_time = options.fetch(:start_time, Time.now.utc)
|
209
|
+
|
207
210
|
tags = options.fetch(:tags, {})
|
208
211
|
|
209
212
|
opts = options.select do |k, _v|
|
210
213
|
# Filter options, we want no side effects with unexpected args.
|
211
214
|
# Plus, this documents the code (Ruby 2 named args would be better but we're Ruby 1.9 compatible)
|
212
|
-
|
215
|
+
ALLOWED_SPAN_OPTIONS.include?(k)
|
213
216
|
end
|
214
217
|
|
215
218
|
ctx, parent = guess_context_and_parent(options[:child_of])
|
data/lib/ddtrace/utils.rb
CHANGED
@@ -26,12 +26,20 @@ module Datadog
|
|
26
26
|
|
27
27
|
reset!
|
28
28
|
|
29
|
-
def self.truncate(value, size, omission = '...')
|
29
|
+
def self.truncate(value, size, omission = '...'.freeze)
|
30
30
|
string = value.to_s
|
31
31
|
|
32
32
|
return string if string.size <= size
|
33
33
|
|
34
|
-
string.slice(0, size -
|
34
|
+
string = string.slice(0, size - 1)
|
35
|
+
|
36
|
+
if size < omission.size
|
37
|
+
string[0, size] = omission
|
38
|
+
else
|
39
|
+
string[size - omission.size, size] = omission
|
40
|
+
end
|
41
|
+
|
42
|
+
string
|
35
43
|
end
|
36
44
|
|
37
45
|
def self.utf8_encode(str, options = {})
|
data/lib/ddtrace/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ddtrace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.12.
|
4
|
+
version: 0.12.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Datadog, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -216,6 +216,13 @@ executables: []
|
|
216
216
|
extensions: []
|
217
217
|
extra_rdoc_files: []
|
218
218
|
files:
|
219
|
+
- ".circleci/config.yml"
|
220
|
+
- ".circleci/images/primary/Dockerfile-1.9.3"
|
221
|
+
- ".circleci/images/primary/Dockerfile-2.0.0"
|
222
|
+
- ".circleci/images/primary/Dockerfile-2.1.10"
|
223
|
+
- ".circleci/images/primary/Dockerfile-2.2.10"
|
224
|
+
- ".circleci/images/primary/Dockerfile-2.3.7"
|
225
|
+
- ".circleci/images/primary/Dockerfile-2.4.4"
|
219
226
|
- ".env"
|
220
227
|
- ".gitignore"
|
221
228
|
- ".rspec"
|
@@ -227,7 +234,6 @@ files:
|
|
227
234
|
- LICENSE
|
228
235
|
- README.md
|
229
236
|
- Rakefile
|
230
|
-
- circle.yml
|
231
237
|
- ddtrace.gemspec
|
232
238
|
- docker-compose.yml
|
233
239
|
- docs/GettingStarted.md
|
@@ -283,6 +289,7 @@ files:
|
|
283
289
|
- lib/ddtrace/contrib/rack/middlewares.rb
|
284
290
|
- lib/ddtrace/contrib/rack/patcher.rb
|
285
291
|
- lib/ddtrace/contrib/rails/action_controller.rb
|
292
|
+
- lib/ddtrace/contrib/rails/action_controller_patch.rb
|
286
293
|
- lib/ddtrace/contrib/rails/action_view.rb
|
287
294
|
- lib/ddtrace/contrib/rails/active_support.rb
|
288
295
|
- lib/ddtrace/contrib/rails/core_extensions.rb
|
@@ -357,7 +364,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
357
364
|
version: '0'
|
358
365
|
requirements: []
|
359
366
|
rubyforge_project:
|
360
|
-
rubygems_version: 2.
|
367
|
+
rubygems_version: 2.5.1
|
361
368
|
signing_key:
|
362
369
|
specification_version: 4
|
363
370
|
summary: Datadog tracing code for your Ruby applications
|
data/circle.yml
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
machine:
|
2
|
-
services:
|
3
|
-
- docker
|
4
|
-
ruby:
|
5
|
-
version:
|
6
|
-
2.2.7
|
7
|
-
environment:
|
8
|
-
LAST_STABLE: 2.4.1
|
9
|
-
EARLY_STABLE: 2.2.7
|
10
|
-
MRI_VERSIONS: 2.4.1,2.3.4,2.2.7
|
11
|
-
MRI_OLD_VERSIONS: 2.1.10,2.0.0,1.9.3
|
12
|
-
SIDEKIQ_OLD_VERSIONS: 2.1.10,2.0.0
|
13
|
-
RAILS3_VERSIONS: 2.3.4,2.2.7,2.1.10,2.0.0,1.9.3
|
14
|
-
RAILS4_VERSIONS: 2.3.4,2.2.7,2.1.10
|
15
|
-
RAILS5_VERSIONS: 2.3.4,2.2.7
|
16
|
-
RAILS3_SIDEKIQ_VERSIONS: 2.1.10,2.0.0
|
17
|
-
RAILS4_SIDEKIQ_VERSIONS: 2.3.4,2.2.7
|
18
|
-
JRUBY_VERSIONS: jruby-9.1.13.0
|
19
|
-
AGENT_BUILD_PATH: "/home/ubuntu/agent"
|
20
|
-
TEST_DATADOG_INTEGRATION: 1
|
21
|
-
|
22
|
-
dependencies:
|
23
|
-
cache_directories:
|
24
|
-
# Cache Ruby binaries and gems
|
25
|
-
- "/opt/circleci/.rvm/"
|
26
|
-
- ~/rubies_cache
|
27
|
-
pre:
|
28
|
-
- mkdir -p ~/rubies_cache
|
29
|
-
- rsync -a -v --ignore-existing ~/rubies_cache/ /opt/circleci/.rvm/rubies
|
30
|
-
# we should use an old docker-compose because CircleCI supports
|
31
|
-
# only docker-engine==1.9
|
32
|
-
- pip install docker-compose==1.7.1
|
33
|
-
- docker-compose up -d | cat
|
34
|
-
# installing dev dependencies
|
35
|
-
- |
|
36
|
-
for version in $(echo "$MRI_VERSIONS,$MRI_OLD_VERSIONS,$JRUBY_VERSIONS" | tr "," "\n"); do
|
37
|
-
$(rvm list | grep -q $version) || rvm install $version --rubygems 2.6.11
|
38
|
-
done
|
39
|
-
- gem install bundler
|
40
|
-
# remove line below once `msgpack` have a consistent version for jruby
|
41
|
-
- bundle inject msgpack 1.1.0 && sed -i "y/\"/'/" Gemfile
|
42
|
-
- bundle install
|
43
|
-
override:
|
44
|
-
- rvm $MRI_VERSIONS,$MRI_OLD_VERSIONS,$JRUBY_VERSIONS --verbose do gem install bundler
|
45
|
-
- rvm $MRI_VERSIONS,$MRI_OLD_VERSIONS,$JRUBY_VERSIONS --verbose do bundle install
|
46
|
-
# [FIXME] appraisal does not work with jruby (problem with native ext, eg sqlite3)
|
47
|
-
- rvm $MRI_VERSIONS,$MRI_OLD_VERSIONS --verbose do bundle exec appraisal install || echo FIX-ME: Ignoring non-zero exit status
|
48
|
-
post:
|
49
|
-
- rsync -a -v --ignore-existing /opt/circleci/.rvm/rubies/ ~/rubies_cache
|
50
|
-
|
51
|
-
test:
|
52
|
-
override:
|
53
|
-
- rvm $EARLY_STABLE --verbose do bundle exec rake rubocop
|
54
|
-
# TODO: integration tests should run with the master branch of the agent
|
55
|
-
- bundle exec rake ci:
|
56
|
-
parallel: true
|
57
|
-
|
58
|
-
deployment:
|
59
|
-
develop:
|
60
|
-
branch: /(master)|(develop)/
|
61
|
-
# CircleCI is configured to provide VERSION_SUFFIX=$CIRCLE_BUILD_NUM
|
62
|
-
commands:
|
63
|
-
- S3_DIR=trace-dev bundle exec rake release:docs
|
64
|
-
- S3_DIR=trace-dev bundle exec rake release:gem
|
65
|
-
- cp -r ./rubygems/* $CIRCLE_ARTIFACTS
|
66
|
-
public:
|
67
|
-
tag: /v[0-9]+(\.[0-9]+)*/
|
68
|
-
commands:
|
69
|
-
- S3_DIR=trace bundle exec rake release:docs
|