s3_asset_deploy 0.1.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +21 -15
- data/README.md +104 -4
- data/lib/s3_asset_deploy/asset_helper.rb +1 -1
- data/lib/s3_asset_deploy/manager.rb +6 -5
- data/lib/s3_asset_deploy/version.rb +1 -1
- data/s3_asset_deploy.gemspec +6 -2
- metadata +20 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3590e77179d747a7737ad4032877bc1e2f2a219d58005711f70ff737cf107fb5
|
4
|
+
data.tar.gz: cfc9de4221ce547ddc818d1569b70b3c5ffb6184d79108eec3145534a2361304
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a91acae364734b965b2c1176eee978b23fe4244c0ad4c89993f2a52f528a8d2efe6d7652daf4ca50f2e473eab5d9bb153c5af04f1000e3731e3294d0b5737c0
|
7
|
+
data.tar.gz: d1a6dfd9164072da6aa1acbd5a36e280508e291d525a907b9500e5af76e0b07816da5dc6a60ff6d4dba5d95ddc3e891da44627a526189ebb56d723a251063c9c
|
data/CHANGELOG.md
CHANGED
@@ -1 +1,11 @@
|
|
1
1
|
# Changelog
|
2
|
+
|
3
|
+
## [v1.0.1](https://github.com/Loomly/s3_asset_deploy/compare/v1.0.0...v1.0.1) - 2022-02-23
|
4
|
+
- Batch delete API calls with max 1000 keys - [PR #32](https://github.com/Loomly/s3_asset_deploy/pull/32)
|
5
|
+
|
6
|
+
## [v1.0.0](https://github.com/Loomly/s3_asset_deploy/compare/v0.1.1...v1.0.0) - 2021-05-13
|
7
|
+
### Breaking Changes
|
8
|
+
- Remove default `acl` setting when uploading assets to bucket - [PR #25](https://github.com/Loomly/s3_asset_deploy/pull/25)
|
9
|
+
|
10
|
+
## [v0.1.1](https://github.com/Loomly/s3_asset_deploy/compare/v0.1.0...v0.1.1) - 2021-03-22
|
11
|
+
- Fix bug in AssetHelper.remove_fingerprint referencing asset_path - [4f370ad](https://github.com/Loomly/s3_asset_deploy/commit/4f370ad9c0c1c274acb9b1d8585b878f47020277)
|
data/Gemfile.lock
CHANGED
@@ -1,43 +1,48 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
s3_asset_deploy (0.1
|
4
|
+
s3_asset_deploy (1.0.1)
|
5
5
|
aws-sdk-s3 (~> 1.0)
|
6
6
|
mime-types (~> 3.0)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
aws-eventstream (1.
|
12
|
-
aws-partitions (1.
|
13
|
-
aws-sdk-core (3.
|
11
|
+
aws-eventstream (1.2.0)
|
12
|
+
aws-partitions (1.558.0)
|
13
|
+
aws-sdk-core (3.126.2)
|
14
14
|
aws-eventstream (~> 1, >= 1.0.2)
|
15
|
-
aws-partitions (~> 1, >= 1.
|
15
|
+
aws-partitions (~> 1, >= 1.525.0)
|
16
16
|
aws-sigv4 (~> 1.1)
|
17
17
|
jmespath (~> 1.0)
|
18
|
-
aws-sdk-kms (1.
|
19
|
-
aws-sdk-core (~> 3, >= 3.
|
18
|
+
aws-sdk-kms (1.54.0)
|
19
|
+
aws-sdk-core (~> 3, >= 3.126.0)
|
20
20
|
aws-sigv4 (~> 1.1)
|
21
|
-
aws-sdk-s3 (1.
|
22
|
-
aws-sdk-core (~> 3, >= 3.
|
21
|
+
aws-sdk-s3 (1.112.0)
|
22
|
+
aws-sdk-core (~> 3, >= 3.126.0)
|
23
23
|
aws-sdk-kms (~> 1)
|
24
|
-
aws-sigv4 (~> 1.
|
25
|
-
aws-sigv4 (1.
|
24
|
+
aws-sigv4 (~> 1.4)
|
25
|
+
aws-sigv4 (1.4.0)
|
26
26
|
aws-eventstream (~> 1, >= 1.0.2)
|
27
27
|
byebug (11.1.3)
|
28
28
|
coderay (1.1.3)
|
29
29
|
diff-lcs (1.4.4)
|
30
|
-
jmespath (1.
|
30
|
+
jmespath (1.6.0)
|
31
31
|
method_source (1.0.0)
|
32
|
-
mime-types (3.
|
32
|
+
mime-types (3.4.1)
|
33
33
|
mime-types-data (~> 3.2015)
|
34
|
-
mime-types-data (3.
|
34
|
+
mime-types-data (3.2022.0105)
|
35
|
+
mini_portile2 (2.8.0)
|
36
|
+
nokogiri (1.13.3)
|
37
|
+
mini_portile2 (~> 2.8.0)
|
38
|
+
racc (~> 1.4)
|
35
39
|
pry (0.13.1)
|
36
40
|
coderay (~> 1.1)
|
37
41
|
method_source (~> 1.0)
|
38
42
|
pry-byebug (3.9.0)
|
39
43
|
byebug (~> 11.0)
|
40
44
|
pry (~> 0.13.0)
|
45
|
+
racc (1.6.0)
|
41
46
|
rake (13.0.3)
|
42
47
|
rspec (3.10.0)
|
43
48
|
rspec-core (~> 3.10.0)
|
@@ -60,6 +65,7 @@ PLATFORMS
|
|
60
65
|
ruby
|
61
66
|
|
62
67
|
DEPENDENCIES
|
68
|
+
nokogiri (~> 1.13)
|
63
69
|
pry (~> 0.13)
|
64
70
|
pry-byebug (~> 3.9)
|
65
71
|
rake (~> 13.0)
|
@@ -69,4 +75,4 @@ DEPENDENCIES
|
|
69
75
|
timecop (~> 0.9)
|
70
76
|
|
71
77
|
BUNDLED WITH
|
72
|
-
2.2.
|
78
|
+
2.2.32
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# S3AssetDeploy
|
2
2
|
|
3
3
|
[![CircleCI](https://circleci.com/gh/Loomly/s3_asset_deploy.svg?style=shield)](https://circleci.com/gh/Loomly/s3_asset_deploy)
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/s3_asset_deploy.svg)](https://badge.fury.io/rb/s3_asset_deploy)
|
4
5
|
|
5
6
|
During rolling deploys to our web instances, this is what we use at
|
6
7
|
[Loomly](https://www.loomly.com) to safely deploy our web assets to S3 to be served via Cloudfront.
|
@@ -41,7 +42,7 @@ Before using `S3AssetDeploy` you want to make sure to compile your assets. Asset
|
|
41
42
|
|
42
43
|
|
43
44
|
```ruby
|
44
|
-
manager = S3AssetDeploy::Manager("my-s3-bucket")
|
45
|
+
manager = S3AssetDeploy::Manager.new("my-s3-bucket")
|
45
46
|
manager.deploy do
|
46
47
|
# Perform deploy to web instances in this block
|
47
48
|
end
|
@@ -60,7 +61,7 @@ You'll need to initialize `S3AssetDeploy::Manager` with an S3 bucket name and **
|
|
60
61
|
- **s3_client_options** (Hash) -> A hash that is passed directly to [`Aws::S3::Client#initialize`](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#initialize-instance_method) to configure the S3 client. By default the region is set to `us-east-1`.
|
61
62
|
- **logger** (Logger) -> A custom logger. By default things are logged to `STDOUT`.
|
62
63
|
- **local_asset_collector** (S3AssetDeploy::LocalAssetCollector) -> A custom instance of `S3AssetDeploy::LocalAssetCollector`. This allows you to customize how locally compiled assets are collected.
|
63
|
-
- **upload_options** (Hash) -> A hash consisting of options that are passed directly to [`Aws::S3::Client#put_object`](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#put_object-instance_method) when each asset is uploaded. By default `
|
64
|
+
- **upload_options** (Hash) -> A hash consisting of options that are passed directly to [`Aws::S3::Client#put_object`](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#put_object-instance_method) when each asset is uploaded. By default `cache_control` is set to `public, max-age=31536000`.
|
64
65
|
- **remove_fingerprint** (Lambda) -> Lambda for overriding how fingerprints are removed from asset paths. Fingerprints need to be removed during the cleaning process in order to group versions of the same file. If no Lambda is provided, [`S3AssetDeploy::AssetHelper.remove_fingerprint`](https://github.com/Loomly/s3_asset_deploy/blob/main/lib/s3_asset_deploy/asset_helper.rb#L8) is used by default.
|
65
66
|
|
66
67
|
Here's an example:
|
@@ -107,6 +108,46 @@ manager.clean
|
|
107
108
|
`S3AssetDeploy::Manager#deploy` and `S3AssetDeploy::Manager#clean` both accept `dry_run` as a keyword argument.
|
108
109
|
`S3AssetDeploy::Manager#clean` also accepts `version_limit`, `version_ttl`, and `removed_ttl` just like `S3AssetDeploy::Manager#deploy`.
|
109
110
|
|
111
|
+
### Practical Example of Usage
|
112
|
+
There are many ways to use and invoke `S3AssetDeploy`. How you use it will depend on your deploy process and pipeline. At Loomly, we have some rake tasks that are invoked from our CI/CD pipeline to perform deploys.
|
113
|
+
Here's a basic example of how we use `S3AssetDeploy`:
|
114
|
+
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
# lib/tasks/deploy.rake
|
118
|
+
|
119
|
+
require "s3_asset_deploy"
|
120
|
+
|
121
|
+
namespace :deploy do
|
122
|
+
task precompile: :environment do
|
123
|
+
puts "Precompiling assets..."
|
124
|
+
sh("RAILS_ENV=production SECRET_KEY_BASE='secret key' bundle exec rake assets:precompile")
|
125
|
+
end
|
126
|
+
|
127
|
+
task clobber_assets: :environment do
|
128
|
+
puts "Clobbering assets..."
|
129
|
+
sh("RAILS_ENV=production SECRET_KEY_BASE='secret key' bundle exec rake assets:clobber")
|
130
|
+
end
|
131
|
+
|
132
|
+
task :production do
|
133
|
+
Rake::Task["deploy:precompile"].invoke
|
134
|
+
|
135
|
+
manager = S3AssetDeploy::Manager.new("my-s3-bucket")
|
136
|
+
manager.deploy do
|
137
|
+
# Perform deploy to web instances in this block.
|
138
|
+
# How you do this will depend on where you are hosting your application and what tools you use to deploy.
|
139
|
+
end
|
140
|
+
|
141
|
+
Rake::Task["deploy:clobber_assets"].invoke # <-- If you are running on CI where the precompiled assets directory is ephemeral, this may be unnecessary
|
142
|
+
end
|
143
|
+
end
|
144
|
+
```
|
145
|
+
|
146
|
+
Given the example above, we can perform a deploy by running `bundle exec rake deploy:production`. This task will:
|
147
|
+
1. Precompile assets
|
148
|
+
2. Upload any new assets to S3 using `S3AssetDeploy`
|
149
|
+
3. Deploy a new version of our application
|
150
|
+
4. Clean any outdated or unused assets from S3 using `S3AssetDeploy`
|
110
151
|
|
111
152
|
## Customizing local asset collection
|
112
153
|
By default, `S3AssetDeploy::Manager` will use [`S3AssetDeploy::RailsLocalAssetCollector`](https://github.com/Loomly/s3_asset_deploy/blob/main/lib/s3_asset_deploy/rails_local_asset_collector.rb) to collect locally compiled assets. This will use the `Sprockets::Manifest` and `Webpacker` config (if `Webpacker` is installed) to locate the compiled assets. `S3AssetDeploy::RailsLocalAssetCollector` inherits from the [`S3AssetDeploy::LocalAssetCollector`](https://github.com/Loomly/s3_asset_deploy/blob/main/lib/s3_asset_deploy/local_asset_collector.rb) base class. You can completely customize how your local assets are collected for deploys by creating your own class that inherits from `S3AssetDeploy::LocalAssetCollector` and passing it into the manager. You'll want override `S3AssetDeploy::LocalAssetCollector#assets` in your custom collector such that it returns an array of `S3AssetDeploy::LocalAsset` instances. Here's a basic example:
|
@@ -133,7 +174,7 @@ This will skip any write or delete operations and only perform read opeartions w
|
|
133
174
|
This is helpful for debugging or planning purposes.
|
134
175
|
|
135
176
|
```ruby
|
136
|
-
> manager = S3AssetDeploy::Manager("my-s3-bucket")
|
177
|
+
> manager = S3AssetDeploy::Manager.new("my-s3-bucket")
|
137
178
|
> manager.deploy(dry_run: true)
|
138
179
|
|
139
180
|
I, [2021-02-17T16:12:23.703677 #65335] INFO -- : S3AssetDeploy::Manager: Cleaning assets from test-bucket S3 bucket. Dry run: true
|
@@ -142,7 +183,7 @@ I, [2021-02-17T16:12:23.703677 #65335] INFO -- : S3AssetDeploy::Manager: Determ
|
|
142
183
|
```
|
143
184
|
|
144
185
|
## AWS IAM Permissions
|
145
|
-
`S3AsetDeploy` requires the following AWS IAM permissions:
|
186
|
+
`S3AsetDeploy` requires the following AWS IAM permissions to list, put, and delete objects in your S3 Bucket:
|
146
187
|
|
147
188
|
```json
|
148
189
|
"Statement": [
|
@@ -161,6 +202,65 @@ I, [2021-02-17T16:12:23.703677 #65335] INFO -- : S3AssetDeploy::Manager: Determ
|
|
161
202
|
]
|
162
203
|
```
|
163
204
|
|
205
|
+
## Configuration with Cloudfront
|
206
|
+
|
207
|
+
### Restricting Access with Origin Access Identity
|
208
|
+
If you want to setup Cloudfront to serve your assets, you can [restrict access to the bucket by using an Origin Access Identity](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html#private-content-granting-permissions-to-oai) so that only Cloudfront can access the objects in your bucket.
|
209
|
+
|
210
|
+
If you do this, your bucket policy will look something like this:
|
211
|
+
|
212
|
+
```json
|
213
|
+
{
|
214
|
+
"Version": "2012-10-17",
|
215
|
+
"Statement": [
|
216
|
+
{
|
217
|
+
"Sid": "AllowGetObject",
|
218
|
+
"Effect": "Allow",
|
219
|
+
"Principal": {
|
220
|
+
"AWS": [
|
221
|
+
"arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity #{YOUR_OAI_ID}"
|
222
|
+
]
|
223
|
+
},
|
224
|
+
"Action": "s3:GetObject",
|
225
|
+
"Resource": "arn:aws:s3:::#{YOUR_BUCKET}/*"
|
226
|
+
},
|
227
|
+
{
|
228
|
+
"Sid": "DenyGetObject",
|
229
|
+
"Effect": "Deny",
|
230
|
+
"Principal": {
|
231
|
+
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity #{YOUR_OAI_ID}"
|
232
|
+
},
|
233
|
+
"Action": "s3:GetObject",
|
234
|
+
"Resource": "arn:aws:s3:::#{YOUR_BUCKET}/s3-asset-deploy-removal-manifest.json"
|
235
|
+
}
|
236
|
+
]
|
237
|
+
}
|
238
|
+
```
|
239
|
+
|
240
|
+
This policy allows Cloudfront to access everything **except** the removal manifest uploaded and maintained by this gem since this manifest does not need to be served to clients.
|
241
|
+
|
242
|
+
### CORS
|
243
|
+
Your CORS configuration on the bucket might look something like this:
|
244
|
+
|
245
|
+
```json
|
246
|
+
[
|
247
|
+
{
|
248
|
+
"AllowedHeaders": [
|
249
|
+
"Authorization"
|
250
|
+
],
|
251
|
+
"AllowedMethods": [
|
252
|
+
"GET",
|
253
|
+
"HEAD"
|
254
|
+
],
|
255
|
+
"AllowedOrigins": [
|
256
|
+
"https://*.#{YOUR_SITE}.com"
|
257
|
+
],
|
258
|
+
"ExposeHeaders": [],
|
259
|
+
"MaxAgeSeconds": 3000
|
260
|
+
}
|
261
|
+
]
|
262
|
+
```
|
263
|
+
|
164
264
|
## Development
|
165
265
|
|
166
266
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -168,7 +168,6 @@ class S3AssetDeploy::Manager
|
|
168
168
|
bucket: bucket_name,
|
169
169
|
key: asset.path,
|
170
170
|
body: file_handle,
|
171
|
-
acl: "public-read",
|
172
171
|
content_type: asset.mime_type,
|
173
172
|
cache_control: "public, max-age=31536000"
|
174
173
|
}.merge(@upload_options)
|
@@ -194,10 +193,12 @@ class S3AssetDeploy::Manager
|
|
194
193
|
|
195
194
|
def delete_objects(keys = [])
|
196
195
|
return if keys.empty?
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
196
|
+
keys.each_slice(1000) do |key_slice|
|
197
|
+
s3.delete_objects(
|
198
|
+
bucket: bucket_name,
|
199
|
+
delete: { objects: key_slice.map { |key| { key: key }} }
|
200
|
+
)
|
201
|
+
end
|
201
202
|
end
|
202
203
|
|
203
204
|
def log(msg)
|
data/s3_asset_deploy.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.authors = ["Loomly"]
|
9
9
|
spec.email = ["contact@loomly.com"]
|
10
10
|
|
11
|
-
spec.summary = "
|
12
|
-
spec.homepage = "https://
|
11
|
+
spec.summary = "Deploy & manage static assets on S3 with rolling deploys & rollbacks in mind."
|
12
|
+
spec.homepage = "https://github.com/Loomly/s3_asset_deploy"
|
13
13
|
spec.license = "MIT"
|
14
14
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
|
15
15
|
|
@@ -36,6 +36,10 @@ Gem::Specification.new do |spec|
|
|
36
36
|
spec.add_development_dependency "pry-byebug", "~> 3.9"
|
37
37
|
spec.add_development_dependency "rspec_junit_formatter", "~> 0.4"
|
38
38
|
|
39
|
+
# Required for aws-sdk-ruby.
|
40
|
+
# See https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-core/lib/aws-sdk-core/xml/parser.rb#L74
|
41
|
+
spec.add_development_dependency "nokogiri", "~> 1.13"
|
42
|
+
|
39
43
|
# For more information and examples about making a new gem, checkout our
|
40
44
|
# guide at: https://bundler.io/guides/creating_gem.html
|
41
45
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: s3_asset_deploy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Loomly
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-s3
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0.4'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: nokogiri
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.13'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1.13'
|
125
139
|
description:
|
126
140
|
email:
|
127
141
|
- contact@loomly.com
|
@@ -154,11 +168,11 @@ files:
|
|
154
168
|
- lib/s3_asset_deploy/removal_manifest.rb
|
155
169
|
- lib/s3_asset_deploy/version.rb
|
156
170
|
- s3_asset_deploy.gemspec
|
157
|
-
homepage: https://
|
171
|
+
homepage: https://github.com/Loomly/s3_asset_deploy
|
158
172
|
licenses:
|
159
173
|
- MIT
|
160
174
|
metadata:
|
161
|
-
homepage_uri: https://
|
175
|
+
homepage_uri: https://github.com/Loomly/s3_asset_deploy
|
162
176
|
source_code_uri: https://github.com/Loomly/s3_asset_deploy
|
163
177
|
changelog_uri: https://github.com/Loomly/s3_asset_deploy/CHANGELOG.md
|
164
178
|
post_install_message:
|
@@ -176,8 +190,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
176
190
|
- !ruby/object:Gem::Version
|
177
191
|
version: '0'
|
178
192
|
requirements: []
|
179
|
-
rubygems_version: 3.
|
193
|
+
rubygems_version: 3.2.32
|
180
194
|
signing_key:
|
181
195
|
specification_version: 4
|
182
|
-
summary:
|
196
|
+
summary: Deploy & manage static assets on S3 with rolling deploys & rollbacks in mind.
|
183
197
|
test_files: []
|