forked from getsentry/sentry
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwad
executable file
·334 lines (279 loc) · 7.85 KB
/
wad
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
#!/usr/bin/env ruby
# Generated on: 20-09-2013 at 12:38
require 'time'
require 'net/http'
require 'net/https'
require 'digest/md5'
require 'digest/sha1'
require 'fileutils'
require 'openssl'
require 'base64'
require 'cgi'
class Presss
# Computes the Authorization header for a AWS request based on a message,
# the access key ID and secret access key.
class Authorization
attr_accessor :access_key_id, :secret_access_key
def initialize(access_key_id, secret_access_key)
@access_key_id, @secret_access_key = access_key_id, secret_access_key
end
# Returns the value for the Authorization header for a message contents.
def header(string)
'AWS ' + access_key_id + ':' + sign(string)
end
# Returns a signature for a AWS request message.
def sign(string)
Base64.encode64(hmac_sha1(string)).strip
end
def hmac_sha1(string)
OpenSSL::HMAC.digest('sha1', secret_access_key, string)
end
end
class HTTP
attr_accessor :config
def initialize(config)
@config = config
end
# Returns the configured bucket name.
def bucket_name
config[:bucket_name]
end
def region
config[:region] || 'us-east-1'
end
def domain
case region
when 'us-east-1'
's3.amazonaws.com'
else
's3-%s.amazonaws.com' % region
end
end
def bucket_in_hostname?
config[:bucket_in_hostname]
end
def url_prefix
if bucket_in_hostname?
"https://#{bucket_name}.#{domain}"
else
"https://#{domain}/#{bucket_name}"
end
end
# Returns the absolute path based on the key for the object.
def absolute_path(path)
path.start_with?('/') ? path : '/' + path
end
# Returns the canonicalized resource used in the authorization
# signature for an absolute path to an object.
def canonicalized_resource(path)
if bucket_name.nil?
raise ArgumentError, "Please configure a bucket_name: Presss.config = { bucket_name: 'my-bucket-name }"
else
'/' + bucket_name + absolute_path(path)
end
end
# Returns a Presss::Authorization instance for the configured
# AWS credentials.
def authorization
@authorization ||= Presss::Authorization.new(
config[:access_key_id],
config[:secret_access_key]
)
end
def signed_url(verb, expires, headers, path)
path = absolute_path(path)
canonical_path = canonicalized_resource(path)
signature = [ verb.to_s.upcase, nil, nil, expires, [ headers, canonical_path ].flatten.compact ].flatten.join("\n")
signed = authorization.sign(signature)
"#{url_prefix}#{path}?Signature=#{CGI.escape(signed)}&Expires=#{expires}&AWSAccessKeyId=#{CGI.escape(authorization.access_key_id)}"
end
def download(path, destination)
url = signed_url(:get, Time.now.to_i + 600, nil, path)
Presss.log "signed_url=#{url}"
system 'curl', '-f', '-S', '-o', destination, url
$?.success?
end
# Puts an object with a key using a file or string. Optionally pass in
# the content-type if you want to set a specific one.
def put(path, file)
header = 'x-amz-storage-class:REDUCED_REDUNDANCY'
url = signed_url(:put, Time.now.to_i + 600, header, path)
Presss.log "signed_url=#{url}"
system 'curl', '-f', '-S', '-H', header, '-T', file, url
$?.success?
end
end
class << self
attr_accessor :config
attr_accessor :logger
end
self.config = {}
# Get a object with a certain key.
def self.download(path, destination)
t0 = Time.now
request = Presss::HTTP.new(config)
log("Trying to GET #{path}")
if request.download(path, destination)
puts("[wad] Downloaded in #{(Time.now - t0).to_i} seconds")
true
else
nil
end
end
# Puts an object with a key using a file or string. Optionally pass in
# the content-type if you want to set a specific one.
def self.put(path, filename, content_type='application/x-download')
request = Presss::HTTP.new(config)
log("Trying to PUT #{path}")
request.put(path, filename)
end
# Logs to the configured logger if a logger was configured.
def self.log(message)
if logger
logger.info('[Presss] ' + message)
end
end
end
# Utility class to push and fetch Bundler directories to speed up
# test runs on Travis-CI
class Wad
class Key
def default_environment_variables
[]
end
def default_files
[ "#{ENV['BUNDLE_GEMFILE']}.lock" ]
end
def environment_variables
if ENV['WAD_ENVIRONMENT_VARIABLES']
ENV['WAD_ENVIRONMENT_VARIABLES'].split(',')
else
default_environment_variables
end
end
def files
ENV['WAD_FILES'] ? ENV['WAD_FILES'].split(',') : default_files
end
def environment_variable_contents
environment_variables.map { |v| ENV[v] }
end
def file_contents
files.map { |f| File.read(f) rescue nil }
end
def contents
segments = [ RUBY_VERSION, RUBY_PLATFORM ] + environment_variable_contents + file_contents
Digest::SHA1.hexdigest(segments.join("\n"))
end
end
def initialize
s3_configure
end
def project_root
Dir.pwd
end
def artifact_name
@artifact_name ||= Key.new.contents
end
def bzip_filename
File.join(project_root, "tmp/#{artifact_name}.tar.bz2")
end
def cache_path
ENV['WAD_CACHE_PATH'] ? ENV['WAD_CACHE_PATH'].split(",") : [ '.bundle' ]
end
def s3_bucket_name
if bucket = ENV['WAD_S3_BUCKET_NAME'] || ENV['S3_BUCKET_NAME']
bucket
end
end
def s3_credentials
if creds = ENV['WAD_S3_CREDENTIALS'] || ENV['S3_CREDENTIALS']
creds.split(':')
end
end
def s3_access_key_id
s3_credentials && s3_credentials[0]
end
def s3_secret_access_key
s3_credentials && s3_credentials[1]
end
def s3_path
"#{artifact_name}.tar.bz2"
end
def s3_configure
Presss.config = {
:bucket_name => s3_bucket_name,
:access_key_id => s3_access_key_id,
:secret_access_key => s3_secret_access_key,
:region => ENV['WAD_AWS_REGION'],
:bucket_in_hostname => (ENV['WAD_BUCKET_IN_HOSTNAME'] == 'true')
}
end
def s3_write
log "Trying to write Wad to S3"
if Presss.put(s3_path, bzip_filename)
log "Wrote Wad to S3"
else
log "Failed to write to S3, debug with `wad -v'"
end
end
def s3_read
if File.exist?(bzip_filename)
log "Removing bundle from filesystem"
FileUtils.rm_f(bzip_filename)
end
log "Trying to fetch Wad from S3"
FileUtils.mkdir_p(File.dirname(bzip_filename))
Presss.download(s3_path, bzip_filename)
end
def zip
log "Creating artifact with tar (#{File.basename(bzip_filename)})"
system("cd #{project_root} && tar -cPjf #{bzip_filename} #{cache_path.join(' ')}")
$?.success?
end
def unzip
log "Unpacking artifact with tar (#{File.basename(bzip_filename)})"
system("cd #{project_root} && tar -xPjf #{bzip_filename}")
$?.success?
end
def put
zip
s3_write
end
def get
if s3_read
unzip
end
end
def default_command
bundle_without = ENV['WAD_BUNDLE_WITHOUT'] || "development production"
"bundle install --path .bundle --without='#{bundle_without}'"
end
def install
log "Installing..."
command = ENV['WAD_INSTALL_COMMAND'] || default_command
puts command
system(command)
$?.success?
end
def setup
if !s3_credentials || !s3_bucket_name
log "No S3 credentials defined. Set WAD_S3_CREDENTIALS= and WAD_S3_BUCKET_NAME= for caching."
install
elsif get
install
elsif install
put
else
abort "Failed properly fetch or install. Please review the logs."
end
end
def log(message)
puts "[wad] #{message}"
end
end
if ARGV.index('-v')
require 'logger'
Presss.logger = Logger.new($stdout)
end
Wad.new.setup
__END__