dpl 2.0.3.beta.4 → 2.0.3.beta.5
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/Gemfile +15 -3
- data/Gemfile.lock +444 -211
- data/Rakefile +36 -34
- data/bin/dpl +3 -1
- data/dpl.gemspec +25 -0
- data/lib/dpl/cli.rb +19 -14
- data/lib/dpl/ctx/bash.rb +18 -12
- data/lib/dpl/ctx/test.rb +21 -15
- data/lib/dpl/ctx.rb +2 -0
- data/lib/dpl/helper/assets.rb +4 -2
- data/lib/dpl/helper/cmd.rb +20 -18
- data/lib/dpl/helper/config_file.rb +5 -3
- data/lib/dpl/helper/cookbook_site_streaming_uploader.rb +249 -0
- data/lib/dpl/helper/env.rb +26 -22
- data/lib/dpl/helper/github.rb +2 -0
- data/lib/dpl/helper/interpolate.rb +8 -4
- data/lib/dpl/helper/memoize.rb +4 -1
- data/lib/dpl/helper/squiggle.rb +3 -1
- data/lib/dpl/helper/transliterate.rb +3 -1
- data/lib/dpl/helper/wrap.rb +3 -1
- data/lib/dpl/helper/zip.rb +3 -1
- data/lib/dpl/provider/dsl.rb +18 -4
- data/lib/dpl/provider/examples.rb +6 -2
- data/lib/dpl/provider/status.rb +26 -24
- data/lib/dpl/providers/anynines.rb +22 -20
- data/lib/dpl/providers/azure_web_apps.rb +21 -19
- data/lib/dpl/providers/bintray.rb +44 -37
- data/lib/dpl/providers/bluemixcloudfoundry.rb +38 -36
- data/lib/dpl/providers/boxfuse.rb +12 -10
- data/lib/dpl/providers/cargo.rb +7 -5
- data/lib/dpl/providers/chef_supermarket.rb +82 -80
- data/lib/dpl/providers/cloud66.rb +17 -15
- data/lib/dpl/providers/cloudfiles.rb +8 -6
- data/lib/dpl/providers/cloudformation.rb +191 -187
- data/lib/dpl/providers/cloudfoundry.rb +32 -30
- data/lib/dpl/providers/codedeploy.rb +35 -33
- data/lib/dpl/providers/convox.rb +32 -25
- data/lib/dpl/providers/datica.rb +30 -28
- data/lib/dpl/providers/ecr.rb +66 -64
- data/lib/dpl/providers/elasticbeanstalk.rb +14 -12
- data/lib/dpl/providers/engineyard.rb +60 -58
- data/lib/dpl/providers/firebase.rb +6 -4
- data/lib/dpl/providers/flynn.rb +8 -6
- data/lib/dpl/providers/gae.rb +28 -25
- data/lib/dpl/providers/gcs.rb +59 -57
- data/lib/dpl/providers/git_push.rb +199 -195
- data/lib/dpl/providers/gleis.rb +19 -17
- data/lib/dpl/providers/hackage.rb +15 -13
- data/lib/dpl/providers/hephy.rb +18 -16
- data/lib/dpl/providers/heroku/api.rb +72 -70
- data/lib/dpl/providers/heroku/git.rb +15 -13
- data/lib/dpl/providers/heroku.rb +40 -38
- data/lib/dpl/providers/lambda.rb +134 -134
- data/lib/dpl/providers/launchpad.rb +45 -43
- data/lib/dpl/providers/netlify.rb +7 -5
- data/lib/dpl/providers/npm.rb +61 -58
- data/lib/dpl/providers/nuget.rb +8 -6
- data/lib/dpl/providers/openshift.rb +8 -6
- data/lib/dpl/providers/opsworks.rb +23 -21
- data/lib/dpl/providers/pages/api.rb +14 -14
- data/lib/dpl/providers/pages/git.rb +53 -47
- data/lib/dpl/providers/pages.rb +3 -1
- data/lib/dpl/providers/puppetforge.rb +6 -4
- data/lib/dpl/providers/pypi.rb +55 -54
- data/lib/dpl/providers/releases.rb +30 -23
- data/lib/dpl/providers/rubygems.rb +35 -31
- data/lib/dpl/providers/s3.rb +148 -142
- data/lib/dpl/providers/scalingo.rb +18 -16
- data/lib/dpl/providers/script.rb +4 -2
- data/lib/dpl/providers/snap.rb +12 -9
- data/lib/dpl/providers/surge.rb +7 -5
- data/lib/dpl/providers/testfairy.rb +47 -43
- data/lib/dpl/providers/transifex.rb +20 -18
- data/lib/dpl/providers.rb +3 -1
- data/lib/dpl/string_ext.rb +3 -1
- data/lib/dpl/support/aws_sdk_patch.rb +4 -1
- data/lib/dpl/support/gems.rb +7 -3
- data/lib/dpl/support/gstore_patch.rb +3 -1
- data/lib/dpl/support/version.rb +13 -12
- data/lib/dpl/version.rb +3 -1
- data/lib/dpl.rb +2 -0
- data/status.json +237 -0
- metadata +32 -15
- /data/lib/dpl/providers/{packagecloud.rb → packagecloud.rb_} +0 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'dpl/helper/github'
|
|
2
4
|
|
|
3
5
|
module Dpl
|
|
@@ -11,17 +13,17 @@ module Dpl
|
|
|
11
13
|
|
|
12
14
|
full_name 'GitHub Releases'
|
|
13
15
|
|
|
14
|
-
description sq(<<-
|
|
16
|
+
description sq(<<-STR)
|
|
15
17
|
tbd
|
|
16
|
-
|
|
18
|
+
STR
|
|
17
19
|
|
|
18
|
-
gem 'octokit', '~>
|
|
19
|
-
gem 'mime-types', '~> 3.
|
|
20
|
-
gem 'public_suffix', '~>
|
|
20
|
+
gem 'octokit', '~> 7'
|
|
21
|
+
gem 'mime-types', '~> 3.4.1'
|
|
22
|
+
gem 'public_suffix', '~> 5'
|
|
21
23
|
|
|
22
24
|
env :github, :releases
|
|
23
25
|
|
|
24
|
-
required :token, [
|
|
26
|
+
required :token, %i[username password]
|
|
25
27
|
|
|
26
28
|
opt '--token TOKEN', 'GitHub oauth token (needs public_repo or repo permission)', secret: true, alias: :api_key
|
|
27
29
|
opt '--username LOGIN', 'GitHub login name', alias: :user
|
|
@@ -42,24 +44,24 @@ module Dpl
|
|
|
42
44
|
|
|
43
45
|
needs :git
|
|
44
46
|
|
|
45
|
-
msgs deploy:
|
|
46
|
-
local_tag:
|
|
47
|
-
login:
|
|
48
|
-
insufficient_scopes:
|
|
49
|
-
insufficient_perm:
|
|
50
|
-
overwrite_existing:
|
|
51
|
-
skip_existing:
|
|
52
|
-
upload_file:
|
|
53
|
-
set_tag_name:
|
|
47
|
+
msgs deploy: 'Deploying to repo: %{slug}',
|
|
48
|
+
local_tag: 'Current tag is: %{local_tag}',
|
|
49
|
+
login: 'Authenticated as %s',
|
|
50
|
+
insufficient_scopes: 'Dpl does not have permission to upload assets. Make sure your token has the repo or public_repo scope.',
|
|
51
|
+
insufficient_perm: 'Release resource not found. Make sure your token belongs to an account which has push permission to this repo.',
|
|
52
|
+
overwrite_existing: 'File %s already exists, overwriting.',
|
|
53
|
+
skip_existing: 'File %s already exists, skipping.',
|
|
54
|
+
upload_file: 'Uploading file %s ...',
|
|
55
|
+
set_tag_name: 'Setting tag_name to %s',
|
|
54
56
|
set_target_commitish: 'Setting target_commitish to %s',
|
|
55
|
-
missing_file:
|
|
56
|
-
not_a_file:
|
|
57
|
+
missing_file: 'File %s does not exist.',
|
|
58
|
+
not_a_file: '%s is not a file, skipping.'
|
|
57
59
|
|
|
58
60
|
cmds git_fetch_tags: 'git fetch --tags'
|
|
59
61
|
|
|
60
62
|
URL = 'https://api.github.com/repos/%s/releases/%s'
|
|
61
63
|
|
|
62
|
-
OCTOKIT_OPTS = %i
|
|
64
|
+
OCTOKIT_OPTS = %i[
|
|
63
65
|
repo
|
|
64
66
|
name
|
|
65
67
|
body
|
|
@@ -67,12 +69,12 @@ module Dpl
|
|
|
67
69
|
release_number
|
|
68
70
|
tag_name
|
|
69
71
|
target_commitish
|
|
70
|
-
|
|
72
|
+
].freeze
|
|
71
73
|
|
|
72
74
|
TIMEOUTS = {
|
|
73
75
|
timeout: 180,
|
|
74
76
|
open_timeout: 180
|
|
75
|
-
}
|
|
77
|
+
}.freeze
|
|
76
78
|
|
|
77
79
|
def validate
|
|
78
80
|
info :deploy
|
|
@@ -99,6 +101,7 @@ module Dpl
|
|
|
99
101
|
file = normalize_filename(path)
|
|
100
102
|
asset = asset(file)
|
|
101
103
|
return info :skip_existing, file if asset && !overwrite?
|
|
104
|
+
|
|
102
105
|
delete(asset, file) if asset
|
|
103
106
|
info :upload_file, file
|
|
104
107
|
api.upload_asset(url, path, name: file, content_type: content_type(path))
|
|
@@ -119,12 +122,14 @@ module Dpl
|
|
|
119
122
|
|
|
120
123
|
def with_tag(opts)
|
|
121
124
|
return opts if tag_name? || draft?
|
|
125
|
+
|
|
122
126
|
info :set_tag_name, local_tag
|
|
123
127
|
opts.merge(tag_name: local_tag)
|
|
124
128
|
end
|
|
125
129
|
|
|
126
130
|
def with_target_commitish(opts)
|
|
127
131
|
return opts if target_commitish? || !same_repo?
|
|
132
|
+
|
|
128
133
|
info :set_target_commitish, git_sha
|
|
129
134
|
opts.merge(target_commitish: git_sha)
|
|
130
135
|
end
|
|
@@ -137,7 +142,7 @@ module Dpl
|
|
|
137
142
|
|
|
138
143
|
def url
|
|
139
144
|
if release_number?
|
|
140
|
-
URL
|
|
145
|
+
format(URL, slug, release_number)
|
|
141
146
|
elsif release
|
|
142
147
|
release.rels[:self].href
|
|
143
148
|
else
|
|
@@ -202,7 +207,7 @@ module Dpl
|
|
|
202
207
|
end
|
|
203
208
|
|
|
204
209
|
def creds
|
|
205
|
-
username && password ? { login: username, password:
|
|
210
|
+
username && password ? { login: username, password: } : { access_token: token }
|
|
206
211
|
end
|
|
207
212
|
|
|
208
213
|
def files
|
|
@@ -212,13 +217,15 @@ module Dpl
|
|
|
212
217
|
end
|
|
213
218
|
|
|
214
219
|
def exists?(file)
|
|
215
|
-
return true if File.
|
|
220
|
+
return true if File.exist?(file)
|
|
221
|
+
|
|
216
222
|
error :missing_file, file
|
|
217
223
|
false
|
|
218
224
|
end
|
|
219
225
|
|
|
220
226
|
def file?(file)
|
|
221
227
|
return true if File.file?(file)
|
|
228
|
+
|
|
222
229
|
warn :not_a_file, file
|
|
223
230
|
false
|
|
224
231
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Dpl
|
|
2
4
|
module Providers
|
|
3
5
|
class Rubygems < Provider
|
|
@@ -5,15 +7,15 @@ module Dpl
|
|
|
5
7
|
|
|
6
8
|
status :stable
|
|
7
9
|
|
|
8
|
-
description sq(<<-
|
|
10
|
+
description sq(<<-STR)
|
|
9
11
|
tbd
|
|
10
|
-
|
|
12
|
+
STR
|
|
11
13
|
|
|
12
14
|
gem 'gems', '~> 1.1.1'
|
|
13
15
|
|
|
14
16
|
env :rubygems
|
|
15
17
|
|
|
16
|
-
required :api_key, [
|
|
18
|
+
required :api_key, %i[username password]
|
|
17
19
|
|
|
18
20
|
opt '--api_key KEY', 'Rubygems api key', secret: true
|
|
19
21
|
opt '--username USER', 'Rubygems user name', alias: :user
|
|
@@ -24,12 +26,12 @@ module Dpl
|
|
|
24
26
|
opt '--host URL'
|
|
25
27
|
|
|
26
28
|
msgs login_api_key: 'Authenticating with api key %{api_key}',
|
|
27
|
-
login_creds:
|
|
28
|
-
setup:
|
|
29
|
-
gem_lookup:
|
|
30
|
-
gem_found:
|
|
29
|
+
login_creds: 'Authenticating with username %{username} and password %{password}',
|
|
30
|
+
setup: 'Setting up host %{host}',
|
|
31
|
+
gem_lookup: 'Looking up gem %{gem} ... ',
|
|
32
|
+
gem_found: 'found.',
|
|
31
33
|
gem_not_found: 'no such gem.',
|
|
32
|
-
gem_push:
|
|
34
|
+
gem_push: 'Pushing gem %{gem}'
|
|
33
35
|
|
|
34
36
|
cmds gem_build: 'gem build %{gemspec}'
|
|
35
37
|
|
|
@@ -37,6 +39,7 @@ module Dpl
|
|
|
37
39
|
|
|
38
40
|
def setup
|
|
39
41
|
return unless host?
|
|
42
|
+
|
|
40
43
|
info :setup
|
|
41
44
|
Gems.host = host
|
|
42
45
|
end
|
|
@@ -58,36 +61,37 @@ module Dpl
|
|
|
58
61
|
|
|
59
62
|
private
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
def login_api_key
|
|
65
|
+
info :login_api_key
|
|
66
|
+
Gems.key = api_key
|
|
67
|
+
end
|
|
65
68
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
def login_creds
|
|
70
|
+
info :login_creds
|
|
71
|
+
Gems.username = username
|
|
72
|
+
Gems.password = password
|
|
73
|
+
end
|
|
70
74
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
end
|
|
75
|
+
def build
|
|
76
|
+
Dir[gemspec_glob].each do |gemspec|
|
|
77
|
+
shell :gem_build, gemspec: gemspec.whitelist
|
|
75
78
|
end
|
|
79
|
+
end
|
|
76
80
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
end
|
|
81
|
+
def push
|
|
82
|
+
Dir["#{gem}-*.gem"].each do |file|
|
|
83
|
+
info :gem_push, gem: file.whitelist
|
|
84
|
+
info Gems.push(File.new(file), *[host].compact)
|
|
82
85
|
end
|
|
86
|
+
end
|
|
83
87
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
def gemspec_glob
|
|
89
|
+
super || "#{gemspec || gem}.gemspec"
|
|
90
|
+
end
|
|
87
91
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
def gemspec
|
|
93
|
+
super.gsub('.gemspec', '') if gemspec?
|
|
94
|
+
end
|
|
91
95
|
end
|
|
92
96
|
end
|
|
93
97
|
end
|
data/lib/dpl/providers/s3.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'uri'
|
|
2
4
|
|
|
3
5
|
# we want this, don't we?
|
|
@@ -12,12 +14,12 @@ module Dpl
|
|
|
12
14
|
|
|
13
15
|
full_name 'AWS S3'
|
|
14
16
|
|
|
15
|
-
description sq(<<-
|
|
17
|
+
description sq(<<-STR)
|
|
16
18
|
tbd
|
|
17
|
-
|
|
19
|
+
STR
|
|
18
20
|
|
|
19
|
-
gem 'aws-sdk-s3', '~> 1
|
|
20
|
-
gem 'mime-types', '~> 3.
|
|
21
|
+
gem 'aws-sdk-s3', '~> 1'
|
|
22
|
+
gem 'mime-types', '~> 3.4.1'
|
|
21
23
|
|
|
22
24
|
env :aws, :s3
|
|
23
25
|
config '~/.aws/credentials', '~/.aws/config', prefix: 'aws'
|
|
@@ -31,12 +33,12 @@ module Dpl
|
|
|
31
33
|
opt '--local_dir DIR', 'Local directory to upload from', default: '.', example: '~/travis/build (absolute path) or ./build (relative path)'
|
|
32
34
|
opt '--glob GLOB', 'Files to upload', default: '**/*'
|
|
33
35
|
opt '--dot_match', 'Upload hidden files starting with a dot'
|
|
34
|
-
opt '--acl ACL', 'Access control for the uploaded objects', default: 'private', enum: %w
|
|
36
|
+
opt '--acl ACL', 'Access control for the uploaded objects', default: 'private', enum: %w[private public_read public_read_write authenticated_read bucket_owner_read bucket_owner_full_control]
|
|
35
37
|
opt '--detect_encoding', 'HTTP header Content-Encoding for files compressed with gzip and compress utilities'
|
|
36
38
|
opt '--cache_control STR', 'HTTP header Cache-Control to suggest that the browser cache the file', type: :array, default: 'no-cache', enum: [/^no-cache.*/, /^no-store.*/, /^max-age=\d+.*/, /^s-maxage=\d+.*/, /^no-transform/, /^public/, /^private/], note: 'accepts mapping values to globs', eg: 'public: *.css,*.js'
|
|
37
39
|
opt '--expires DATE', 'Date and time that the cached object expires', type: :array, format: /^"?\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} .+"?.*$/, note: 'accepts mapping values to globs', eg: '2020-01-01 00:00:00 UTC: *.css,*.js'
|
|
38
40
|
opt '--default_text_charset CHARSET', 'Default character set to append to the content-type of text files'
|
|
39
|
-
opt '--storage_class CLASS', 'S3 storage class to upload as', default: 'STANDARD', enum: %w
|
|
41
|
+
opt '--storage_class CLASS', 'S3 storage class to upload as', default: 'STANDARD', enum: %w[STANDARD STANDARD_IA REDUCED_REDUNDANCY]
|
|
40
42
|
opt '--server_side_encryption', 'Use S3 Server Side Encryption (SSE-AES256)'
|
|
41
43
|
opt '--index_document_suffix SUFFIX', 'Index document suffix of a S3 website'
|
|
42
44
|
opt '--overwrite', 'Whether or not to overwrite existing files', default: true
|
|
@@ -44,15 +46,15 @@ module Dpl
|
|
|
44
46
|
opt '--max_threads NUM', 'The number of threads to use for S3 file uploads', default: 5, max: 15, type: :integer
|
|
45
47
|
opt '--verbose', 'Be verbose about uploading files'
|
|
46
48
|
|
|
47
|
-
msgs login:
|
|
48
|
-
default_uri_schema:
|
|
49
|
-
access_denied:
|
|
50
|
-
checksum_error:
|
|
49
|
+
msgs login: 'Using Access Key: %{access_key_id}',
|
|
50
|
+
default_uri_schema: 'S3 endpoint does not specify a scheme; defaulting to https',
|
|
51
|
+
access_denied: 'It looks like you tried to write to a bucket that is not yours or does not exist. Please create the bucket before trying to write to it.',
|
|
52
|
+
checksum_error: 'AWS secret key does not match the access key id',
|
|
51
53
|
invalid_access_key_id: 'Invalid S3 access key id',
|
|
52
|
-
upload:
|
|
53
|
-
upload_file:
|
|
54
|
-
upload_skipped:
|
|
55
|
-
upload_failed:
|
|
54
|
+
upload: 'Uploading %s files with up to %s threads ...',
|
|
55
|
+
upload_file: 'Uploading %s to %s with %s',
|
|
56
|
+
upload_skipped: 'Skipping %{file}, already exists',
|
|
57
|
+
upload_failed: 'Failed to upload %s',
|
|
56
58
|
index_document_suffix: 'Setting index document suffix to %s'
|
|
57
59
|
|
|
58
60
|
DEFAULT_CONTENT_TYPE = 'application/octet-stream'
|
|
@@ -80,166 +82,170 @@ module Dpl
|
|
|
80
82
|
|
|
81
83
|
private
|
|
82
84
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
def upload
|
|
86
|
+
info :upload, files.length, max_threads
|
|
87
|
+
threads = max_threads.times.map { |_i| Thread.new(&method(:upload_files)) }
|
|
88
|
+
threads.each(&:join)
|
|
89
|
+
info "\n" unless verbose?
|
|
90
|
+
end
|
|
89
91
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
end
|
|
92
|
+
def upload_files
|
|
93
|
+
while file = files.pop
|
|
94
|
+
opts = upload_opts(file)
|
|
95
|
+
progress(file, opts)
|
|
96
|
+
upload_file(file, opts)
|
|
96
97
|
end
|
|
98
|
+
end
|
|
97
99
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
end
|
|
100
|
+
def progress(file, data)
|
|
101
|
+
if verbose?
|
|
102
|
+
info :upload_file, file, upload_dir || '/', to_pairs(data)
|
|
103
|
+
else
|
|
104
|
+
print '.'
|
|
104
105
|
end
|
|
106
|
+
end
|
|
105
107
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
info :upload_file, file, upload_dir || '/', to_pairs(opts)
|
|
110
|
-
object.upload_file(file, opts) || warn(:upload_failed, file)
|
|
111
|
-
end
|
|
108
|
+
def upload_file(file, opts)
|
|
109
|
+
object = bucket.object(upload_path(file))
|
|
110
|
+
return warn :upload_skipped, file: file if !overwrite && object.exists?
|
|
112
111
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
bucket.website.put(body)
|
|
117
|
-
end
|
|
112
|
+
info :upload_file, file, upload_dir || '/', to_pairs(opts)
|
|
113
|
+
object.upload_file(file, opts) || warn(:upload_failed, file)
|
|
114
|
+
end
|
|
118
115
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
116
|
+
def index_document_suffix
|
|
117
|
+
info :index_document_suffix, super
|
|
118
|
+
body = { website_configuration: { index_document: { suffix: super } } }
|
|
119
|
+
bucket.website.put(body)
|
|
120
|
+
end
|
|
122
121
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
content_type: content_type(file),
|
|
127
|
-
content_encoding: detect_encoding? ? encoding(file) : nil,
|
|
128
|
-
cache_control: match_opt(cache_control, file),
|
|
129
|
-
expires: match_opt(expires, file),
|
|
130
|
-
storage_class: storage_class,
|
|
131
|
-
server_side_encryption: server_side_encryption
|
|
132
|
-
)
|
|
133
|
-
end
|
|
122
|
+
def upload_path(file)
|
|
123
|
+
[upload_dir, file].compact.join('/')
|
|
124
|
+
end
|
|
134
125
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
126
|
+
def upload_opts(file)
|
|
127
|
+
compact(
|
|
128
|
+
acl:,
|
|
129
|
+
content_type: content_type(file),
|
|
130
|
+
content_encoding: detect_encoding? ? encoding(file) : nil,
|
|
131
|
+
cache_control: match_opt(cache_control, file),
|
|
132
|
+
expires: match_opt(expires, file),
|
|
133
|
+
storage_class:,
|
|
134
|
+
server_side_encryption:
|
|
135
|
+
)
|
|
136
|
+
end
|
|
138
137
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
def files
|
|
139
|
+
@files ||= Dir.glob(*glob).reject { |path| File.directory?(path) }
|
|
140
|
+
end
|
|
142
141
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
def glob
|
|
143
|
+
[super, dot_match? ? File::FNM_DOTMATCH : nil].compact
|
|
144
|
+
end
|
|
146
145
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
def acl
|
|
147
|
+
super.gsub(/_/, '-') if acl?
|
|
148
|
+
end
|
|
150
149
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
type.to_s
|
|
155
|
-
end
|
|
150
|
+
def server_side_encryption
|
|
151
|
+
'AES256' if server_side_encryption?
|
|
152
|
+
end
|
|
156
153
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
end
|
|
154
|
+
def content_type(file)
|
|
155
|
+
return DEFAULT_CONTENT_TYPE unless type = MIME::Types.type_for(file).first
|
|
160
156
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
157
|
+
type = "#{type}; charset=#{default_text_charset}" if encoding(file) == 'text' && default_text_charset?
|
|
158
|
+
type.to_s
|
|
159
|
+
end
|
|
164
160
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
info :default_uri_scheme
|
|
169
|
-
URI.parse("https://#{url}")
|
|
170
|
-
end
|
|
161
|
+
def compact(hash)
|
|
162
|
+
hash.reject { |_, value| value.nil? }.to_h
|
|
163
|
+
end
|
|
171
164
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
error :invalid_access_key_id
|
|
176
|
-
when Aws::S3::Errors::ChecksumError
|
|
177
|
-
error :checksum_error
|
|
178
|
-
when Aws::S3::Errors::AccessDenied
|
|
179
|
-
error :access_denied
|
|
180
|
-
else
|
|
181
|
-
error e.message
|
|
182
|
-
end
|
|
183
|
-
end
|
|
165
|
+
def endpoint
|
|
166
|
+
@endpoint ||= normalize_endpoint(super) if endpoint?
|
|
167
|
+
end
|
|
184
168
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
169
|
+
def normalize_endpoint(url)
|
|
170
|
+
uri = URI.parse(url)
|
|
171
|
+
return uri if uri.scheme
|
|
188
172
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
173
|
+
info :default_uri_scheme
|
|
174
|
+
URI.parse("https://#{url}")
|
|
175
|
+
end
|
|
192
176
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
177
|
+
def handle_error(err)
|
|
178
|
+
case err
|
|
179
|
+
when Aws::S3::Errors::InvalidAccessKeyId
|
|
180
|
+
error :invalid_access_key_id
|
|
181
|
+
when Aws::S3::Errors::ChecksumError
|
|
182
|
+
error :checksum_error
|
|
183
|
+
when Aws::S3::Errors::AccessDenied
|
|
184
|
+
error :access_denied
|
|
185
|
+
else
|
|
186
|
+
error err.message
|
|
200
187
|
end
|
|
188
|
+
end
|
|
201
189
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
190
|
+
def bucket
|
|
191
|
+
@bucket ||= Aws::S3::Resource.new(client:).bucket(super)
|
|
192
|
+
end
|
|
205
193
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
194
|
+
def client
|
|
195
|
+
Aws::S3::Client.new(s3_opts)
|
|
196
|
+
end
|
|
209
197
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
198
|
+
def s3_opts
|
|
199
|
+
compact(
|
|
200
|
+
region:,
|
|
201
|
+
credentials:,
|
|
202
|
+
endpoint:,
|
|
203
|
+
force_path_style: force_path_style?
|
|
204
|
+
)
|
|
205
|
+
end
|
|
214
206
|
|
|
215
|
-
|
|
216
|
-
|
|
207
|
+
def credentials
|
|
208
|
+
Aws::Credentials.new(access_key_id, secret_access_key)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def to_pairs(hash)
|
|
212
|
+
hash.map { |pair| pair.join('=') }.join(' ')
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def match_opt(strs, file)
|
|
216
|
+
maps = Array(strs).map { |str| Mapping.new(str, file) }
|
|
217
|
+
maps.map(&:value).compact.first
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
class Mapping < Struct.new(:str, :file)
|
|
221
|
+
MATCH = File::FNM_DOTMATCH | File::FNM_EXTGLOB
|
|
217
222
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
223
|
+
def value
|
|
224
|
+
str, glob = parse
|
|
225
|
+
unquote(str) if match?(glob)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
private
|
|
222
229
|
|
|
223
|
-
|
|
230
|
+
def unquote(str)
|
|
231
|
+
str =~ /^"(.*)"$/ && ::Regexp.last_match(1) || str
|
|
232
|
+
end
|
|
224
233
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
234
|
+
def match?(glob)
|
|
235
|
+
glob.nil? || File.fnmatch?(normalize(glob), file, MATCH)
|
|
236
|
+
end
|
|
228
237
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
end
|
|
238
|
+
def normalize(glob)
|
|
239
|
+
return glob if glob.include?('{')
|
|
232
240
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
"{#{glob.split(',').map(&:strip).join(',')}}"
|
|
236
|
-
end
|
|
241
|
+
"{#{glob.split(',').map(&:strip).join(',')}}"
|
|
242
|
+
end
|
|
237
243
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
end
|
|
244
|
+
def parse
|
|
245
|
+
parts = str.split(': ')
|
|
246
|
+
parts.size > 1 ? [parts[0..-2].join(': '), parts.last] : parts
|
|
242
247
|
end
|
|
248
|
+
end
|
|
243
249
|
end
|
|
244
250
|
end
|
|
245
251
|
end
|