capistrano-s3 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cb5552bb93390a37dfef42b1c2f04ab86f8c24b2
4
- data.tar.gz: 7e90088960110cc77b870709ab8e1b7cc1d00af0
3
+ metadata.gz: e58eac78f1006adb9c1dc9ee60f4f34443a5a71e
4
+ data.tar.gz: 7214a8ede096b2186a2f8f526172390f81a3790c
5
5
  SHA512:
6
- metadata.gz: 96b33af80859e1be1a7df56b268d6f8f6bf6a9061c16fd006ff4d2d702571bbfaa36803a7bc228db9385d088ac6cacc3b6a3e5dcbd35400467f00da5ac88ec05
7
- data.tar.gz: aaeec8a903a3e4e1c1d44246108217e33b6a80046df824ed12a86b71e90c4ddb84941166b9c1465f37eed448e5c0ad85d6c87e7b9a7e85e18ef95db26884388f
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
@@ -1,3 +1,4 @@
1
1
  *.gem
2
2
  .last_published
3
- Gemfile.lock
3
+ .last_invalidation
4
+ Gemfile.lock
data/.travis.yml CHANGED
@@ -1,3 +1,7 @@
1
+ notifications:
2
+ email:
3
+ on_success: never
4
+ on_failure: change
1
5
  language: ruby
2
6
  dist: trusty
3
7
  bundler_args: --without debug release
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 endpoint
80
+ ### Custom region
81
81
 
82
82
  If your bucket is not in the default US Standard region,
83
- set [endpoint](http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region)
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 :s3_endpoint, 's3-eu-west-1.amazonaws.com'
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.
@@ -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', '~> 1.11'
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 => proc { Dir.pwd.gsub("\n", "") + "/public" },
5
+ :deployment_path => "public",
6
6
  :bucket_write_options => { :acl => :public_read },
7
- :s3_endpoint => "s3.amazonaws.com",
7
+ :region => 'us-east-1',
8
8
  :redirect_options => {},
9
9
  :only_gzip => false,
10
10
  :invalidations => [],
@@ -1,4 +1,4 @@
1
- require 'aws/s3'
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!(s3_endpoint, key, secret, bucket, source, distribution_id, invalidations, exclusions, only_gzip, extra_options)
11
- s3 = self.establish_s3_client_connection!(s3_endpoint, key, secret)
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(source, exclusions).each do |file|
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(source, file)
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!(s3_endpoint, key, secret, bucket)
46
- s3 = self.establish_s3_connection!(s3_endpoint, key, secret)
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, s3_endpoint, key, secret)
72
+ def self.establish_connection!(klass, region, key, secret)
56
73
  # Send logging to STDOUT
57
- AWS.config(:logger => ::Logger.new(STDOUT))
74
+ Aws.config[:logger] = ::Logger.new(STDOUT)
75
+ Aws.config[:log_formatter] = Aws::Log::Formatter.colored
58
76
  klass.new(
59
- :s3_endpoint => s3_endpoint,
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!(AWS::CloudFront::Client, nil, key, secret)
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!(s3_endpoint, key, secret)
70
- self.establish_connection!(AWS::S3::Client, s3_endpoint, key, secret)
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!(s3_endpoint, key, secret)
74
- self.establish_connection!(AWS::S3, s3_endpoint, key, secret)
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
- :bucket_name => bucket,
95
- :key => path,
96
- :data => open(file),
97
- :acl => :public_read,
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]))
@@ -1,5 +1,5 @@
1
1
  module Capistrano
2
2
  module S3
3
- VERSION = "1.2.0"
3
+ VERSION = "2.0.0"
4
4
  end
5
5
  end
@@ -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!(s3_endpoint, access_key_id, secret_access_key, bucket)
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!(s3_endpoint, access_key_id, secret_access_key,
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(:s3_endpoint), fetch(:access_key_id), fetch(:secret_access_key), fetch(:bucket))
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(:s3_endpoint), fetch(:access_key_id), fetch(:secret_access_key),
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
@@ -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
- AWS::S3::Client::V20060301.any_instance.expects(:put_object).times(8)
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
- AWS::S3::Client::V20060301.any_instance.expects(:put_object).times(4)
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
- AWS::S3::Client::V20060301.any_instance.expects(:put_object).times(8)
28
- AWS::CloudFront::Client::V20141106.any_instance.expects(:create_invalidation).once
23
+ Aws::S3::Client.any_instance.expects(:put_object).times(8)
24
+ Aws::CloudFront::Client.any_instance.expects(:create_invalidation).once
29
25
 
30
- path = File.join(@root, 'sample')
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
- AWS::S3::Client::V20060301.any_instance.expects(:put_object).times(8)
36
- AWS::CloudFront::Client::V20141106.any_instance.expects(:create_invalidation).never
30
+ Aws::S3::Client.any_instance.expects(:put_object).times(8)
31
+ Aws::CloudFront::Client.any_instance.expects(:create_invalidation).never
37
32
 
38
- path = File.join(@root, 'sample')
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
- AWS::S3::Client::V20060301.any_instance.expects(:put_object).times(7)
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', path, 'cf123', [], exclude_paths, false, {})
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
- AWS::S3::Client::V20060301.any_instance.expects(:put_object).times(6)
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', path, 'cf123', [], exclude_paths, false, {})
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
- AWS::S3::Client::V20060301.any_instance.expects(:put_object).times(0)
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', path, 'cf123', [], exclude_paths, false, {})
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
@@ -1,8 +1,8 @@
1
1
  require 'capistrano/s3/publisher'
2
2
  require 'mocha/api'
3
3
 
4
- AWS.stub!
4
+ Aws.config[:stub_responses] = true
5
5
 
6
6
  RSpec.configure do |config|
7
7
  config.mock_framework = :mocha
8
- end
8
+ end
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: 1.2.0
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-25 00:00:00.000000000 Z
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: '1.11'
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: '1.11'
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