capistrano-s3 1.2.0 → 2.0.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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.gitignore +2 -1
- data/.travis.yml +4 -0
- data/CHANGELOG.md +6 -0
- data/README.md +24 -3
- data/capistrano-s3.gemspec +1 -1
- data/lib/capistrano/s3/defaults.rb +2 -2
- data/lib/capistrano/s3/publisher.rb +41 -23
- data/lib/capistrano/s3/version.rb +1 -1
- data/lib/capistrano/tasks/capistrano_2.rb +7 -2
- data/lib/capistrano/tasks/capistrano_3.rb +7 -2
- data/spec/publisher_spec.rb +16 -25
- data/spec/spec_helper.rb +2 -2
- metadata +4 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e58eac78f1006adb9c1dc9ee60f4f34443a5a71e
|
4
|
+
data.tar.gz: 7214a8ede096b2186a2f8f526172390f81a3790c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 146e8d2dfa08cd96f99c6ef87bbb07dbe4f2ff05b38804d1a93c373cbf8ef01721c4630a53f9348e23acd2f7d8c04a9d1423a392760fdc3a9bda3f4ff4a8432e
|
7
|
+
data.tar.gz: 420bcb2f854a5e6c7d507a105228082e54848830c089691d19694fbbdd6b614c0e08011e0147c50d43f86abbfbd1e56d9897fe86635f1dbecaa68e63a56fe1a7
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## v2.0.0
|
4
|
+
|
5
|
+
Major change : AWS SDK dependency was upgragred to 2.6, see migration guide at bottom of README to upgrade from v1.
|
6
|
+
Feature : Add wait_for_invalidation task (#32) @exoszajzbuk
|
7
|
+
Improvement : Simpler way to set deployment_path (#33) @j15e
|
8
|
+
|
3
9
|
## v1.2.0
|
4
10
|
|
5
11
|
Feature : Add exclusions (#30) @exoszajzbuk
|
data/README.md
CHANGED
@@ -77,14 +77,14 @@ Add content to your public folder and run deploy command:
|
|
77
77
|
|
78
78
|
## Advanced options
|
79
79
|
|
80
|
-
### Custom
|
80
|
+
### Custom region
|
81
81
|
|
82
82
|
If your bucket is not in the default US Standard region,
|
83
|
-
set [
|
83
|
+
set [region](http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region)
|
84
84
|
with:
|
85
85
|
|
86
86
|
```ruby
|
87
|
-
set :
|
87
|
+
set :region, 'eu-west-1'
|
88
88
|
```
|
89
89
|
|
90
90
|
### Write options
|
@@ -139,6 +139,8 @@ set :distribution_id, "CHANGETHIS"
|
|
139
139
|
set :invalidations, [ "/index.html", "/assets/*" ]
|
140
140
|
```
|
141
141
|
|
142
|
+
If you want to wait until the invalidation batch is completed (e.g. on a CI server), you can run `cap <stage> deploy:s3:wait_for_invalidation`. The command will wait indefinitely until the invalidation is completed.
|
143
|
+
|
142
144
|
### Exclude files and directories
|
143
145
|
|
144
146
|
You can set a list of files or directories to exclude from upload. The path must relative to `deployment_path` and use the `dir/**/*` pattern to exclude directories.
|
@@ -169,6 +171,25 @@ See our boilerplate
|
|
169
171
|
[sinatra-static-bp](https://github.com/hooktstudios/sinatra-static-bp)
|
170
172
|
for an example of the complete setup.
|
171
173
|
|
174
|
+
## Migration guide
|
175
|
+
|
176
|
+
### From `< 2.0.0`
|
177
|
+
|
178
|
+
If you have customized `deployment_path` from 2.0 use a simplified format
|
179
|
+
|
180
|
+
```diff
|
181
|
+
# config/deploy.rb
|
182
|
+
-set :deployment_path, proc { Dir.pwd.gsub('\n', '') + '/build' }
|
183
|
+
+set :deployment_path, 'build'
|
184
|
+
```
|
185
|
+
|
186
|
+
If you have configured `s3_endpoint` to something other than the default switch to new syntax using [region](http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region) identifiers
|
187
|
+
|
188
|
+
```diff
|
189
|
+
-set :s3_endpoint, 's3-eu-west-1.amazonaws.com'
|
190
|
+
+set :region, 'eu-west-1'
|
191
|
+
```
|
192
|
+
|
172
193
|
## Contributing
|
173
194
|
|
174
195
|
See [CONTRIBUTING.md](https://github.com/hooktstudios/capistrano-s3/blob/master/CONTRIBUTING.md) for more details on contributing and running test.
|
data/capistrano-s3.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.required_ruby_version = ">= 2.1"
|
23
23
|
|
24
24
|
# Gem dependencies
|
25
|
-
s.add_runtime_dependency 'aws-sdk', '~>
|
25
|
+
s.add_runtime_dependency 'aws-sdk', '~> 2.6'
|
26
26
|
s.add_runtime_dependency 'capistrano', '>= 2'
|
27
27
|
s.add_runtime_dependency 'mime-types', '~> 1.23'
|
28
28
|
s.add_runtime_dependency 'net-ssh', '~> 2.9'
|
@@ -2,9 +2,9 @@ module Capistrano
|
|
2
2
|
module S3
|
3
3
|
module Defaults
|
4
4
|
DEFAULTS = {
|
5
|
-
:deployment_path =>
|
5
|
+
:deployment_path => "public",
|
6
6
|
:bucket_write_options => { :acl => :public_read },
|
7
|
-
:
|
7
|
+
:region => 'us-east-1',
|
8
8
|
:redirect_options => {},
|
9
9
|
:only_gzip => false,
|
10
10
|
:invalidations => [],
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'aws
|
1
|
+
require 'aws-sdk'
|
2
2
|
require 'mime/types'
|
3
3
|
require 'fileutils'
|
4
4
|
|
@@ -6,17 +6,19 @@ module Capistrano
|
|
6
6
|
module S3
|
7
7
|
module Publisher
|
8
8
|
LAST_PUBLISHED_FILE = '.last_published'
|
9
|
+
LAST_INVALIDATION_FILE = '.last_invalidation'
|
9
10
|
|
10
|
-
def self.publish!(
|
11
|
-
|
11
|
+
def self.publish!(region, key, secret, bucket, deployment_path, distribution_id, invalidations, exclusions, only_gzip, extra_options)
|
12
|
+
deployment_path_absolute = File.expand_path(deployment_path, Dir.pwd)
|
13
|
+
s3 = self.establish_s3_client_connection!(region, key, secret)
|
12
14
|
updated = false
|
13
15
|
|
14
|
-
self.files(
|
16
|
+
self.files(deployment_path_absolute, exclusions).each do |file|
|
15
17
|
if !File.directory?(file)
|
16
18
|
next if self.published?(file)
|
17
19
|
next if only_gzip && self.has_gzipped_version?(file)
|
18
20
|
|
19
|
-
path = self.base_file_path(
|
21
|
+
path = self.base_file_path(deployment_path_absolute, file)
|
20
22
|
path.gsub!(/^\//, "") # Remove preceding slash for S3
|
21
23
|
|
22
24
|
self.put_object(s3, bucket, path, file, only_gzip, extra_options)
|
@@ -25,9 +27,9 @@ module Capistrano
|
|
25
27
|
|
26
28
|
# invalidate CloudFront distribution if needed
|
27
29
|
if distribution_id && !invalidations.empty?
|
28
|
-
cf = self.establish_cf_client_connection!(key, secret)
|
30
|
+
cf = self.establish_cf_client_connection!(region, key, secret)
|
29
31
|
|
30
|
-
cf.create_invalidation({
|
32
|
+
response = cf.create_invalidation({
|
31
33
|
:distribution_id => distribution_id,
|
32
34
|
:invalidation_batch => {
|
33
35
|
:paths => {
|
@@ -37,41 +39,57 @@ module Capistrano
|
|
37
39
|
:caller_reference => SecureRandom.hex
|
38
40
|
}
|
39
41
|
})
|
42
|
+
|
43
|
+
if response && response.successful?
|
44
|
+
File.open(LAST_INVALIDATION_FILE, 'w') { |file| file.write(response[:invalidation][:id]) }
|
45
|
+
end
|
40
46
|
end
|
41
47
|
|
42
48
|
FileUtils.touch(LAST_PUBLISHED_FILE)
|
43
49
|
end
|
44
50
|
|
45
|
-
def self.clear!(
|
46
|
-
s3 = self.establish_s3_connection!(
|
51
|
+
def self.clear!(region, key, secret, bucket)
|
52
|
+
s3 = self.establish_s3_connection!(region, key, secret)
|
47
53
|
s3.buckets[bucket].clear!
|
48
54
|
|
49
55
|
FileUtils.rm(LAST_PUBLISHED_FILE)
|
56
|
+
FileUtils.rm(LAST_INVALIDATION_FILE)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.check_invalidation(region, key, secret, distribution_id)
|
60
|
+
last_invalidation_id = File.read(LAST_INVALIDATION_FILE).strip
|
61
|
+
|
62
|
+
cf = self.establish_cf_client_connection!(region, key, secret)
|
63
|
+
cf.wait_until(:invalidation_completed, distribution_id: distribution_id, id: last_invalidation_id) do |w|
|
64
|
+
w.max_attempts = nil
|
65
|
+
w.delay = 30
|
66
|
+
end
|
50
67
|
end
|
51
68
|
|
52
69
|
private
|
53
70
|
|
54
71
|
# Establishes the connection to Amazon S3
|
55
|
-
def self.establish_connection!(klass,
|
72
|
+
def self.establish_connection!(klass, region, key, secret)
|
56
73
|
# Send logging to STDOUT
|
57
|
-
|
74
|
+
Aws.config[:logger] = ::Logger.new(STDOUT)
|
75
|
+
Aws.config[:log_formatter] = Aws::Log::Formatter.colored
|
58
76
|
klass.new(
|
59
|
-
:
|
77
|
+
:region => region,
|
60
78
|
:access_key_id => key,
|
61
79
|
:secret_access_key => secret
|
62
80
|
)
|
63
81
|
end
|
64
82
|
|
65
|
-
def self.establish_cf_client_connection!(key, secret)
|
66
|
-
self.establish_connection!(
|
83
|
+
def self.establish_cf_client_connection!(region, key, secret)
|
84
|
+
self.establish_connection!(Aws::CloudFront::Client, region, key, secret)
|
67
85
|
end
|
68
86
|
|
69
|
-
def self.establish_s3_client_connection!(
|
70
|
-
self.establish_connection!(
|
87
|
+
def self.establish_s3_client_connection!(region, key, secret)
|
88
|
+
self.establish_connection!(Aws::S3::Client, region, key, secret)
|
71
89
|
end
|
72
90
|
|
73
|
-
def self.establish_s3_connection!(
|
74
|
-
self.establish_connection!(
|
91
|
+
def self.establish_s3_connection!(region, key, secret)
|
92
|
+
self.establish_connection!(Aws::S3, region, key, secret)
|
75
93
|
end
|
76
94
|
|
77
95
|
def self.base_file_path(root, file)
|
@@ -79,7 +97,7 @@ module Capistrano
|
|
79
97
|
end
|
80
98
|
|
81
99
|
def self.files(deployment_path, exclusions)
|
82
|
-
Dir.glob("#{deployment_path}/**/*") - Dir.glob(exclusions.map{ |e| "#{deployment_path}/#{e}" })
|
100
|
+
Dir.glob("#{deployment_path}/**/*") - Dir.glob(exclusions.map { |e| "#{deployment_path}/#{e}" })
|
83
101
|
end
|
84
102
|
|
85
103
|
def self.published?(file)
|
@@ -91,10 +109,10 @@ module Capistrano
|
|
91
109
|
base_name = File.basename(file)
|
92
110
|
mime_type = mime_type_for_file(base_name)
|
93
111
|
options = {
|
94
|
-
:
|
95
|
-
:key
|
96
|
-
:
|
97
|
-
:acl
|
112
|
+
:bucket => bucket,
|
113
|
+
:key => path,
|
114
|
+
:body => open(file),
|
115
|
+
:acl => :public_read,
|
98
116
|
}
|
99
117
|
|
100
118
|
options.merge!(build_redirect_hash(path, extra_options[:redirect]))
|
@@ -11,13 +11,18 @@ module Capistrano
|
|
11
11
|
namespace :s3 do
|
12
12
|
desc "Empties bucket of all files. Caution when using this command, as it cannot be undone!"
|
13
13
|
task :empty do
|
14
|
-
S3::Publisher.clear!(
|
14
|
+
S3::Publisher.clear!(region, access_key_id, secret_access_key, bucket)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Waits until the last CloudFront invalidation batch is completed"
|
18
|
+
task :wait_for_invalidation do
|
19
|
+
S3::Publisher.check_invalidation(region, access_key_id, secret_access_key, distribution_id)
|
15
20
|
end
|
16
21
|
|
17
22
|
desc "Upload files to the bucket in the current state"
|
18
23
|
task :upload_files do
|
19
24
|
extra_options = { :write => bucket_write_options, :redirect => redirect_options }
|
20
|
-
S3::Publisher.publish!(
|
25
|
+
S3::Publisher.publish!(region, access_key_id, secret_access_key,
|
21
26
|
bucket, deployment_path, distribution_id, invalidations, exclusions, only_gzip, extra_options)
|
22
27
|
end
|
23
28
|
end
|
@@ -8,13 +8,18 @@ namespace :deploy do
|
|
8
8
|
namespace :s3 do
|
9
9
|
desc "Empties bucket of all files. Caution when using this command, as it cannot be undone!"
|
10
10
|
task :empty do
|
11
|
-
Capistrano::S3::Publisher.clear!(fetch(:
|
11
|
+
Capistrano::S3::Publisher.clear!(fetch(:region), fetch(:access_key_id), fetch(:secret_access_key), fetch(:bucket))
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Waits until the last CloudFront invalidation batch is completed"
|
15
|
+
task :wait_for_invalidation do
|
16
|
+
Capistrano::S3::Publisher.check_invalidation(fetch(:region), fetch(:access_key_id), fetch(:secret_access_key), fetch(:distribution_id))
|
12
17
|
end
|
13
18
|
|
14
19
|
desc "Upload files to the bucket in the current state"
|
15
20
|
task :upload_files do
|
16
21
|
extra_options = { :write => fetch(:bucket_write_options), :redirect => fetch(:redirect_options) }
|
17
|
-
Capistrano::S3::Publisher.publish!(fetch(:
|
22
|
+
Capistrano::S3::Publisher.publish!(fetch(:region), fetch(:access_key_id), fetch(:secret_access_key),
|
18
23
|
fetch(:bucket), fetch(:deployment_path), fetch(:distribution_id), fetch(:invalidations), fetch(:exclusions), fetch(:only_gzip), extra_options)
|
19
24
|
end
|
20
25
|
end
|
data/spec/publisher_spec.rb
CHANGED
@@ -9,60 +9,51 @@ describe Capistrano::S3::Publisher do
|
|
9
9
|
|
10
10
|
context "on publish!" do
|
11
11
|
it "publish all files" do
|
12
|
-
|
13
|
-
|
14
|
-
path = File.join(@root, 'sample')
|
15
|
-
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com', path, 'cf123', [], [], false, {})
|
12
|
+
Aws::S3::Client.any_instance.expects(:put_object).times(8)
|
13
|
+
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com', './spec/sample', 'cf123', [], [], false, {})
|
16
14
|
end
|
17
15
|
|
18
16
|
it "publish only gzip files when option is enabled" do
|
19
|
-
|
20
|
-
|
21
|
-
path = File.join(@root, 'sample')
|
22
|
-
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com', path, 'cf123', [], [], true, {})
|
17
|
+
Aws::S3::Client.any_instance.expects(:put_object).times(4)
|
18
|
+
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com', 'spec/sample', 'cf123', [], [], true, {})
|
23
19
|
end
|
24
20
|
|
25
21
|
context "invalidations" do
|
26
22
|
it "publish all files with invalidations" do
|
27
|
-
|
28
|
-
|
23
|
+
Aws::S3::Client.any_instance.expects(:put_object).times(8)
|
24
|
+
Aws::CloudFront::Client.any_instance.expects(:create_invalidation).once
|
29
25
|
|
30
|
-
|
31
|
-
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com', path, 'cf123', ['*'], [], false, {})
|
26
|
+
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com', 'spec/sample/', 'cf123', ['*'], [], false, {})
|
32
27
|
end
|
33
28
|
|
34
29
|
it "publish all files without invalidations" do
|
35
|
-
|
36
|
-
|
30
|
+
Aws::S3::Client.any_instance.expects(:put_object).times(8)
|
31
|
+
Aws::CloudFront::Client.any_instance.expects(:create_invalidation).never
|
37
32
|
|
38
|
-
|
39
|
-
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com', path, 'cf123', [], [], false, {})
|
33
|
+
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com', './spec/sample/', 'cf123', [], [], false, {})
|
40
34
|
end
|
41
35
|
end
|
42
36
|
|
43
37
|
context "exclusions" do
|
44
38
|
it "exclude one files" do
|
45
|
-
|
39
|
+
Aws::S3::Client.any_instance.expects(:put_object).times(7)
|
46
40
|
|
47
|
-
path = File.join(@root, 'sample')
|
48
41
|
exclude_paths = ['fonts/cantarell-regular-webfont.svg']
|
49
|
-
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com',
|
42
|
+
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com', 'spec/sample', 'cf123', [], exclude_paths, false, {})
|
50
43
|
end
|
51
44
|
|
52
45
|
it "exclude multiple files" do
|
53
|
-
|
46
|
+
Aws::S3::Client.any_instance.expects(:put_object).times(6)
|
54
47
|
|
55
|
-
path = File.join(@root, 'sample')
|
56
48
|
exclude_paths = ['fonts/cantarell-regular-webfont.svg', 'fonts/cantarell-regular-webfont.svg.gz']
|
57
|
-
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com',
|
49
|
+
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com', 'spec/sample', 'cf123', [], exclude_paths, false, {})
|
58
50
|
end
|
59
51
|
|
60
52
|
it "exclude directory" do
|
61
|
-
|
53
|
+
Aws::S3::Client.any_instance.expects(:put_object).times(0)
|
62
54
|
|
63
|
-
path = File.join(@root, 'sample')
|
64
55
|
exclude_paths = ['fonts/**/*']
|
65
|
-
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com',
|
56
|
+
Capistrano::S3::Publisher.publish!('s3.amazonaws.com', 'abc', '123', 'mybucket.amazonaws.com', 'spec/sample', 'cf123', [], exclude_paths, false, {})
|
66
57
|
end
|
67
58
|
end
|
68
59
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano-s3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean-Philippe Doyle
|
@@ -36,7 +36,7 @@ cert_chain:
|
|
36
36
|
t/JsZnAlWYkJIees2SFV5X/t34oeMu04yY2u9y2YBqKovR97m5YF7zqgx0JODV0x
|
37
37
|
ytwUJvEjznBnJV4OoDE=
|
38
38
|
-----END CERTIFICATE-----
|
39
|
-
date: 2017-01-
|
39
|
+
date: 2017-01-26 00:00:00.000000000 Z
|
40
40
|
dependencies:
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: aws-sdk
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '2.6'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '2.6'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: capistrano
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
metadata.gz.sig
CHANGED
Binary file
|