s3_deployer 0.6.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 +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/README.md +142 -0
- data/Rakefile +1 -0
- data/lib/s3_deployer/color.rb +22 -0
- data/lib/s3_deployer/config.rb +36 -0
- data/lib/s3_deployer/tasks.rb +28 -0
- data/lib/s3_deployer/version.rb +3 -0
- data/lib/s3_deployer.rb +251 -0
- data/s3_deployer.gemspec +28 -0
- metadata +138 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 844de0917a0347758d662fe6dc799217dc7d16c5
|
|
4
|
+
data.tar.gz: 3ea7e007d1c486ed7186fc76703de849a138b984
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 3b7f997173a27444996997c954c2d75c3c6dc9ee8766841d9ffb146da5d7fb588d15bcabf9420118a1a6f9548327fb7d536db96832227019b9fe38591a870453
|
|
7
|
+
data.tar.gz: 6d8cc55576a7c732503dfa014b6a69f3c3e3c880d6499a7208cc5578694c98afbbf6cc6007710915d0e15c5569ac1708ad38a67b4d37a51cc6f7aa265b92381a
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# S3Deployer
|
|
2
|
+
|
|
3
|
+
Tool for versioned deploying of client-side apps (or literally anything) to S3
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
gem 's3_deployer'
|
|
10
|
+
|
|
11
|
+
And then execute:
|
|
12
|
+
|
|
13
|
+
$ bundle
|
|
14
|
+
|
|
15
|
+
Or install it yourself as:
|
|
16
|
+
|
|
17
|
+
$ gem install s3_deployer
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
You need to specify s3_deployer_config.rb file in your home directory, which may look like this:
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
S3Deployer.configure do
|
|
25
|
+
bucket "some-bucket"
|
|
26
|
+
region 'us-east-1'
|
|
27
|
+
app_name "devastator"
|
|
28
|
+
app_path "path/to/#{app_name}#{"-#{version}" if version && version != ""}"
|
|
29
|
+
dist_dir "dist"
|
|
30
|
+
gzip [/\.js$/, /\.css$/] # or just use 'true' to gzip everything
|
|
31
|
+
colorize true
|
|
32
|
+
time_zone "America/Los_Angeles" # Useful when you develop from different timezones (e.g. for distributed team,
|
|
33
|
+
# or when deploy from some build server), to be consistent with revision numbers
|
|
34
|
+
|
|
35
|
+
before_stage ->(version) do
|
|
36
|
+
# Some custom code to execute before deploy or stage
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
after_stage ->(version) do
|
|
40
|
+
# Some custom code to execute after deploy or stage
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
before_switch ->(version) do
|
|
44
|
+
# Some custom code to execute before deploy or switch
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
after_switch ->(version) do
|
|
48
|
+
# Some custom code to execute after deploy or switch
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
before_deploy ->(version) do
|
|
52
|
+
# Some custom code to execute before deploy
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
after_deploy ->(version) do
|
|
56
|
+
# Some custom code to execute after deploy
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# You also can specify environment-specific settings, the default environment is 'production'
|
|
60
|
+
environment(:development) do
|
|
61
|
+
bucket "some-bucket-dev"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
access_key_id 'your S3 access key id'
|
|
65
|
+
secret_access_key 'your S3 secret access key'
|
|
66
|
+
end
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Note the 'dist_dir' setting, you should put all the necessary files to there, which should be sent to S3, before deploy.
|
|
70
|
+
|
|
71
|
+
Then, you need to include Deployer's tasks to your Rakefile, like:
|
|
72
|
+
|
|
73
|
+
```ruby
|
|
74
|
+
require 'rubygems'
|
|
75
|
+
require 'bundler'
|
|
76
|
+
Bundler.setup
|
|
77
|
+
|
|
78
|
+
require 's3_deployer/tasks'
|
|
79
|
+
require './s3_deployer_config'
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
There are 3 main tasks - for deploy, switch and stage. When you stage, it gets all the files from the dist_dir,
|
|
83
|
+
and copies them to S3. It creates a directories structure on S3, like:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
/path
|
|
87
|
+
/to
|
|
88
|
+
/app
|
|
89
|
+
/20130809134509
|
|
90
|
+
/20130809140328
|
|
91
|
+
...
|
|
92
|
+
SHAS
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
These '20130809134509'-like directories are actually 'staged' versions of the app. Directory name is just
|
|
96
|
+
a revision name, in the format "%Y%m%d%H%M%S".
|
|
97
|
+
|
|
98
|
+
Then, you have to do 'switch', which just copies the selected revision directory into 'current'.
|
|
99
|
+
So, after 'switch' e.g. to 20130809134509, the directory structure will be like
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
/path
|
|
103
|
+
/to
|
|
104
|
+
/app
|
|
105
|
+
/20130809134509
|
|
106
|
+
/20130809140328
|
|
107
|
+
...
|
|
108
|
+
/current
|
|
109
|
+
CURRENT_REVISION
|
|
110
|
+
SHAS
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
'current' contains the currently used copy of the app. Your app should use files from this directory.
|
|
114
|
+
|
|
115
|
+
You also could do "deploy", it is basically "stage", and then "switch" to just staged revision.
|
|
116
|
+
|
|
117
|
+
So, use it like this:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
$ rake s3_deployer:stage # only creates timestamp dir, like 20130809134509, but doesn't override the 'current' dir
|
|
121
|
+
$ rake s3_deployer:switch REVISION=20130809140330
|
|
122
|
+
$ rake s3_deployer:deploy
|
|
123
|
+
$ rake s3_deployer:deploy VERSION=new-stuff # check the example of deployer.rb above to see how it is used
|
|
124
|
+
$ rake s3_deployer:current # get the currently deployed revision
|
|
125
|
+
$ rake s3_deployer:list # get the list of all deployed revisions and their SHAs and commit subjects
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
If you want to run s3_deployer in some specific environment, use ENV variable:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
$ ENV=development rake s3_deployer:deploy
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Default environment is 'production'
|
|
135
|
+
|
|
136
|
+
## Contributing
|
|
137
|
+
|
|
138
|
+
1. Clone it
|
|
139
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
140
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
141
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
142
|
+
5. Create new Pull Request pointing to master
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class S3Deployer
|
|
2
|
+
class Color
|
|
3
|
+
class << self
|
|
4
|
+
def green(text)
|
|
5
|
+
self.new(32).wrap(text)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def yellow(text)
|
|
9
|
+
self.new(33).wrap(text)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(color)
|
|
14
|
+
@color = color
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def wrap(text)
|
|
18
|
+
"\e[#{@color}m#{text}\e[0m"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
class S3Deployer
|
|
2
|
+
class Config
|
|
3
|
+
attr_reader :version, :revision, :env
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
@version = ENV["VERSION"] || ""
|
|
7
|
+
@revision = ENV["REVISION"] || ""
|
|
8
|
+
@env = ENV["ENV"] || "production"
|
|
9
|
+
@env_settings = {}
|
|
10
|
+
colorize true
|
|
11
|
+
time_zone "GMT"
|
|
12
|
+
current_path "current"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
%w{
|
|
16
|
+
region bucket app_name app_path mixbook_host dist_dir access_key_id secret_access_key
|
|
17
|
+
gzip colorize time_zone current_path cache_control
|
|
18
|
+
before_deploy after_deploy before_stage after_stage before_switch after_switch
|
|
19
|
+
}.each do |method|
|
|
20
|
+
define_method method do |value = :omitted|
|
|
21
|
+
instance_variable_set("@#{method}", value) unless value == :omitted
|
|
22
|
+
instance_variable_get("@#{method}")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def environment(name, &block)
|
|
27
|
+
@env_settings[name.to_s] = block
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def apply_environment_settings!
|
|
31
|
+
if @env_settings[@env.to_s]
|
|
32
|
+
instance_eval(&@env_settings[@env.to_s])
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 's3_deployer'
|
|
2
|
+
|
|
3
|
+
namespace :s3_deployer do
|
|
4
|
+
desc "Deploy"
|
|
5
|
+
task :deploy do
|
|
6
|
+
S3Deployer.deploy!
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
desc "Deploy the revision, but don't change it to the 'current' revision"
|
|
10
|
+
task :stage do
|
|
11
|
+
S3Deployer.stage!
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
desc "Switch"
|
|
15
|
+
task :switch do
|
|
16
|
+
S3Deployer.switch!
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
desc "Get current revision number"
|
|
20
|
+
task :current do
|
|
21
|
+
S3Deployer.current
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
desc "Get the list of deployed revisions"
|
|
25
|
+
task :list do
|
|
26
|
+
S3Deployer.list
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/s3_deployer.rb
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'zlib'
|
|
3
|
+
require 'stringio'
|
|
4
|
+
require 'tzinfo'
|
|
5
|
+
require 'rexml/document'
|
|
6
|
+
require 'parallel'
|
|
7
|
+
require 'aws-sdk'
|
|
8
|
+
|
|
9
|
+
require "s3_deployer/config"
|
|
10
|
+
require "s3_deployer/color"
|
|
11
|
+
require "s3_deployer/version"
|
|
12
|
+
|
|
13
|
+
class S3Deployer
|
|
14
|
+
DATE_FORMAT = "%Y%m%d%H%M%S"
|
|
15
|
+
CURRENT_REVISION = "CURRENT_REVISION"
|
|
16
|
+
class << self
|
|
17
|
+
attr_reader :config
|
|
18
|
+
|
|
19
|
+
def configure(&block)
|
|
20
|
+
@config = Config.new
|
|
21
|
+
@config.instance_eval(&block)
|
|
22
|
+
@config.apply_environment_settings!
|
|
23
|
+
|
|
24
|
+
Aws.config.update({
|
|
25
|
+
region: config.region,
|
|
26
|
+
credentials: Aws::Credentials.new(config.access_key_id, config.secret_access_key),
|
|
27
|
+
})
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def execute(cmd)
|
|
31
|
+
puts "Running '#{cmd}'"
|
|
32
|
+
system(cmd, out: $stdout, err: :out)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def deploy!
|
|
36
|
+
revision = time_zone.now.strftime(DATE_FORMAT)
|
|
37
|
+
config.before_deploy[revision] if config.before_deploy
|
|
38
|
+
stage!(revision)
|
|
39
|
+
switch!(revision)
|
|
40
|
+
config.after_deploy[revision] if config.after_deploy
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def stage!(revision = time_zone.now.strftime(DATE_FORMAT))
|
|
44
|
+
puts "Staging #{colorize(:green, revision)}"
|
|
45
|
+
config.before_stage[revision] if config.before_stage
|
|
46
|
+
copy_files_to_s3(revision)
|
|
47
|
+
store_git_hash(revision)
|
|
48
|
+
config.after_stage[revision] if config.after_stage
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def switch!(revision = config.revision)
|
|
52
|
+
current_revision = get_current_revision
|
|
53
|
+
current_sha = sha_of_revision(current_revision)
|
|
54
|
+
sha = sha_of_revision(revision)
|
|
55
|
+
puts "Switching from #{colorize(:green, current_revision)} (#{colorize(:yellow, current_sha && current_sha[0..7])}) " +
|
|
56
|
+
"to #{colorize(:green, revision)} (#{colorize(:yellow, sha && sha[0..7])})"
|
|
57
|
+
if !revision || revision.strip.empty?
|
|
58
|
+
warn "You must specify the revision by REVISION env variable"
|
|
59
|
+
exit(1)
|
|
60
|
+
end
|
|
61
|
+
revision = normalize_revision(revision)
|
|
62
|
+
config.before_switch[current_revision, revision] if config.before_switch
|
|
63
|
+
prefix = config.app_path.empty? ? revision : File.join(config.app_path, revision)
|
|
64
|
+
list_of_objects = []
|
|
65
|
+
Aws::S3::Resource.new.bucket(config.bucket).objects(prefix: prefix).each do |object_summary|
|
|
66
|
+
list_of_objects << object_summary
|
|
67
|
+
end
|
|
68
|
+
Parallel.each(list_of_objects, in_threads: 20) do |object_summary|
|
|
69
|
+
object = object_summary.object
|
|
70
|
+
target_path = config.app_path.empty? ? @config.current_path : File.join(config.app_path, @config.current_path)
|
|
71
|
+
path = object.key.gsub(prefix, target_path)
|
|
72
|
+
value = object.get.body.read
|
|
73
|
+
value = object.content_encoding == "gzip" ? decompress(value) : value
|
|
74
|
+
store_value(path, value)
|
|
75
|
+
end
|
|
76
|
+
store_current_revision(revision)
|
|
77
|
+
config.after_switch[current_revision, revision] if config.after_switch
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def current
|
|
81
|
+
current_revision = get_current_revision
|
|
82
|
+
if current_revision
|
|
83
|
+
puts "Current revision: #{current_revision} - #{get_datetime_from_revision(current_revision)}"
|
|
84
|
+
else
|
|
85
|
+
puts "There is no information about the current revision"
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def normalize_revision(revision)
|
|
90
|
+
if revision && !revision.empty?
|
|
91
|
+
datetime = get_datetime_from_revision(revision)
|
|
92
|
+
if datetime
|
|
93
|
+
revision
|
|
94
|
+
else
|
|
95
|
+
shas_by_revisions.detect { |k, v| v.start_with?(revision) }.first
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def list
|
|
101
|
+
puts "Getting the list of deployed revisions..."
|
|
102
|
+
current_revision = get_current_revision
|
|
103
|
+
get_list_of_revisions.each do |rev|
|
|
104
|
+
datetime = get_datetime_from_revision(rev)
|
|
105
|
+
sha = shas_by_revisions[rev]
|
|
106
|
+
title = sha ? `git show -s --format=%s #{sha}`.strip : nil
|
|
107
|
+
string = "#{rev} - #{datetime} #{sha ? " - #{sha[0..7]}" : ""} #{title ? "(#{title})" : ""} #{" <= current" if rev == current_revision}"
|
|
108
|
+
puts string
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def changes(from, to)
|
|
113
|
+
from_sha = sha_of_revision(from)
|
|
114
|
+
to_sha = sha_of_revision(to)
|
|
115
|
+
if from_sha && to_sha
|
|
116
|
+
`git log --oneline --reverse #{from_sha}...#{to_sha}`.split("\n").map(&:strip)
|
|
117
|
+
else
|
|
118
|
+
[]
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def sha_of_revision(revision)
|
|
123
|
+
shas_by_revisions[normalize_revision(revision)]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
private
|
|
127
|
+
|
|
128
|
+
def copy_files_to_s3(rev)
|
|
129
|
+
dir = File.join(config.app_path, rev)
|
|
130
|
+
Parallel.each(source_files_list, in_threads: 20) do |file|
|
|
131
|
+
s3_file = Pathname.new(file).relative_path_from(Pathname.new(config.dist_dir)).to_s
|
|
132
|
+
store_value(File.join(dir, s3_file), File.read(file))
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def get_list_of_revisions
|
|
137
|
+
prefix = File.join(config.app_path)
|
|
138
|
+
body = Aws::S3::Client.new.list_objects({bucket: config.bucket, delimiter: '/', prefix: prefix + "/"})
|
|
139
|
+
body.common_prefixes.map(&:prefix).map { |e| e.gsub(prefix, "").gsub("/", "") }.select do |dir|
|
|
140
|
+
!!(Time.strptime(dir, DATE_FORMAT) rescue nil)
|
|
141
|
+
end.sort
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def app_path_with_bucket
|
|
145
|
+
File.join(config.bucket, config.app_path)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def get_datetime_from_revision(revision)
|
|
149
|
+
date = Time.strptime(revision, DATE_FORMAT) rescue nil
|
|
150
|
+
date.strftime("%m/%d/%Y %H:%M") if date
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def shas_by_revisions
|
|
154
|
+
@shas_by_revisions ||= get_value(File.join(config.app_path, "SHAS")).split("\n").inject({}) do |memo, line|
|
|
155
|
+
revision, sha = line.split(" - ").map(&:strip)
|
|
156
|
+
memo[revision] = sha
|
|
157
|
+
memo
|
|
158
|
+
end
|
|
159
|
+
rescue Aws::S3::Errors::NoSuchKey
|
|
160
|
+
{}
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def current_revision_path
|
|
164
|
+
File.join(config.app_path, CURRENT_REVISION)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def get_value(key)
|
|
168
|
+
puts "Retrieving value #{key} on S3"
|
|
169
|
+
Aws::S3::Resource.new.bucket(config.bucket).object(key).get.body.read
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def store_current_revision(revision)
|
|
173
|
+
store_value(current_revision_path, revision)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def store_git_hash(time)
|
|
177
|
+
value = shas_by_revisions.
|
|
178
|
+
merge(time => `git rev-parse HEAD`.strip).
|
|
179
|
+
map { |sha, rev| "#{sha} - #{rev}" }.join("\n")
|
|
180
|
+
store_value(File.join(config.app_path, "SHAS"), value)
|
|
181
|
+
@shas_by_revisions = nil
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def get_current_revision
|
|
185
|
+
get_value(current_revision_path)
|
|
186
|
+
rescue Aws::S3::Errors::NoSuchKey
|
|
187
|
+
nil
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def store_value(key, value)
|
|
191
|
+
puts "Storing value #{colorize(:yellow, key)} on S3#{", #{colorize(:green, 'gzipped')}" if should_compress?(key)}"
|
|
192
|
+
options = {acl: "public-read"}
|
|
193
|
+
if config.cache_control && !config.cache_control.empty?
|
|
194
|
+
options[:cache_control] = config.cache_control
|
|
195
|
+
end
|
|
196
|
+
if should_compress?(key)
|
|
197
|
+
options[:content_encoding] = "gzip"
|
|
198
|
+
value = compress(value)
|
|
199
|
+
end
|
|
200
|
+
Aws::S3::Resource.new.bucket(config.bucket).object(key).put(options.merge(body: value))
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def should_compress?(key)
|
|
204
|
+
if [true, false, nil].include?(config.gzip)
|
|
205
|
+
!!config.gzip
|
|
206
|
+
else
|
|
207
|
+
key != CURRENT_REVISION && Array(config.gzip).any? { |regexp| key.match(regexp) }
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def compress(source)
|
|
212
|
+
output = Stream.new
|
|
213
|
+
gz = Zlib::GzipWriter.new(output, Zlib::DEFAULT_COMPRESSION, Zlib::DEFAULT_STRATEGY)
|
|
214
|
+
gz.write(source)
|
|
215
|
+
gz.close
|
|
216
|
+
output.string
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def decompress(source)
|
|
220
|
+
begin
|
|
221
|
+
Zlib::GzipReader.new(StringIO.new(source)).read
|
|
222
|
+
rescue Zlib::GzipFile::Error
|
|
223
|
+
source
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def source_files_list
|
|
228
|
+
Dir.glob(File.join(config.dist_dir, "**/*")).select { |f| File.file?(f) }
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def colorize(color, text)
|
|
232
|
+
config.colorize ? Color.send(color, text) : text
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def time_zone
|
|
236
|
+
TZInfo::Timezone.get(config.time_zone)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
class Stream < StringIO
|
|
240
|
+
def initialize(*)
|
|
241
|
+
super
|
|
242
|
+
set_encoding "BINARY"
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def close
|
|
246
|
+
rewind
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
end
|
|
251
|
+
end
|
data/s3_deployer.gemspec
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 's3_deployer/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "s3_deployer"
|
|
8
|
+
spec.version = S3Deployer::VERSION
|
|
9
|
+
spec.authors = ["Anton Astashov"]
|
|
10
|
+
spec.email = ["anton.astashov@gmail.com"]
|
|
11
|
+
spec.description = "Simple gem for deploying client apps to S3"
|
|
12
|
+
spec.summary = "Simple gem for deploying client apps to S3"
|
|
13
|
+
spec.homepage = ""
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files`.split($/)
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
spec.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
spec.add_dependency 'tzinfo'
|
|
22
|
+
spec.add_dependency 'json'
|
|
23
|
+
spec.add_dependency 'parallel'
|
|
24
|
+
spec.add_dependency 'aws-sdk'
|
|
25
|
+
|
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
|
27
|
+
spec.add_development_dependency "rake"
|
|
28
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: s3_deployer
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.6.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Anton Astashov
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-10-30 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: tzinfo
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: json
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: parallel
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: aws-sdk
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: bundler
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '1.3'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '1.3'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rake
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
description: Simple gem for deploying client apps to S3
|
|
98
|
+
email:
|
|
99
|
+
- anton.astashov@gmail.com
|
|
100
|
+
executables: []
|
|
101
|
+
extensions: []
|
|
102
|
+
extra_rdoc_files: []
|
|
103
|
+
files:
|
|
104
|
+
- ".gitignore"
|
|
105
|
+
- Gemfile
|
|
106
|
+
- README.md
|
|
107
|
+
- Rakefile
|
|
108
|
+
- lib/s3_deployer.rb
|
|
109
|
+
- lib/s3_deployer/color.rb
|
|
110
|
+
- lib/s3_deployer/config.rb
|
|
111
|
+
- lib/s3_deployer/tasks.rb
|
|
112
|
+
- lib/s3_deployer/version.rb
|
|
113
|
+
- s3_deployer.gemspec
|
|
114
|
+
homepage: ''
|
|
115
|
+
licenses:
|
|
116
|
+
- MIT
|
|
117
|
+
metadata: {}
|
|
118
|
+
post_install_message:
|
|
119
|
+
rdoc_options: []
|
|
120
|
+
require_paths:
|
|
121
|
+
- lib
|
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
123
|
+
requirements:
|
|
124
|
+
- - ">="
|
|
125
|
+
- !ruby/object:Gem::Version
|
|
126
|
+
version: '0'
|
|
127
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - ">="
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '0'
|
|
132
|
+
requirements: []
|
|
133
|
+
rubyforge_project:
|
|
134
|
+
rubygems_version: 2.2.2
|
|
135
|
+
signing_key:
|
|
136
|
+
specification_version: 4
|
|
137
|
+
summary: Simple gem for deploying client apps to S3
|
|
138
|
+
test_files: []
|