capistrano-releases 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +95 -3
- data/lib/capistrano/releases/manager.rb +67 -13
- data/lib/capistrano/releases/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59d6dff6482631156eba519cee7dc7205baa6953
|
4
|
+
data.tar.gz: 82fa108d36ff56bc11d2606ad3fd34764fea3ba2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f6ed45f6baeda7c996f49ca855c061c521e6680bbfae80c96bffbaa55ea5f77467785295c0a1c8c727ad4ab8532331b757136e9b2b6de1933f34ebc639ccc26
|
7
|
+
data.tar.gz: 5b8d7226a89243e6c079cf69eeef4999a9fbb889a55001b4d45aa2e24024b21db89e757b0dd7e9394bd65b2beb6608add9137bb3dde1486b1a56171d8a501bdb
|
data/README.md
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
# Capistrano::Releases
|
2
|
-
|
3
|
-
This gem
|
4
|
-
|
2
|
+
|
3
|
+
This gem simplifies working with [Auto scaling for AWS EC2](https://aws.amazon.com/autoscaling/) and [Capistrano](http://capistranorb.com). It does this by storing your releases in AWS S3 and synchronizing them when needed (after deploy, instance reboot, and after a new instance is created).
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
* Ruby 2.X or greater
|
8
|
+
* aws-sdk 2.X or greater
|
9
|
+
* An AWS S3 bucket to store releases
|
10
|
+
* Read and write API permissions to the S3 bucket
|
11
|
+
* Capistrano installed and configured properly with deploys already working
|
5
12
|
|
6
13
|
## Installation
|
7
14
|
|
@@ -21,8 +28,93 @@ Or install it yourself as:
|
|
21
28
|
|
22
29
|
## Usage
|
23
30
|
|
31
|
+
It is assumed that you have already setup a S3 bucket and granted API read/write permissions to it.
|
32
|
+
You should test to make sure your instances are able to read/write to the bucket before continuing.
|
33
|
+
|
34
|
+
You normally interact with the gem through the command line (see below for flag details):
|
35
|
+
|
24
36
|
$ releases --help
|
25
37
|
|
38
|
+
The general idea is that after each deploy, you 'push' the new release to S3.
|
39
|
+
Then, after each boot (or reboot) your instances 'pull' the latest releases from S3.
|
40
|
+
|
41
|
+
For 'push' you need to edit your *deploy.rb* and add something like this:
|
42
|
+
|
43
|
+
namespace :releases do
|
44
|
+
bucket = 'your-bucket-name-goes-here'
|
45
|
+
|
46
|
+
desc 'Push releases'
|
47
|
+
task :push do
|
48
|
+
on roles(:all, primary: true) do
|
49
|
+
execute "releases -b #{bucket} -d #{fetch(:deploy_to)} -m push"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
after 'deploy:finished', 'releases:push'
|
54
|
+
|
55
|
+
For 'pull' you need to configure your server to run a command **before** your Rails processes (Puma, Thin, Sidekiq, etc) start:
|
56
|
+
|
57
|
+
$ releases -b your-bucket-name-goes-here -d /your/deploy/to/name/goes/here -m pull
|
58
|
+
|
59
|
+
You must now write a boot script for your Rails processes.
|
60
|
+
These tend to be very specific to your environment and the set of Capistrano gems you are using.
|
61
|
+
An example is provided below.
|
62
|
+
|
63
|
+
## Flags
|
64
|
+
|
65
|
+
#### --mode
|
66
|
+
|
67
|
+
You must pick a mode to run in: 'push' or 'pull'.
|
68
|
+
|
69
|
+
The push mode compare your local releases to those stored in S3.
|
70
|
+
Any missing releases will get compressed and uploaded.
|
71
|
+
The 'current' symlink version will also get uploaded.
|
72
|
+
|
73
|
+
The pull mode compares the releases stored in S3 to your local releases.
|
74
|
+
Any missing releases will get downloaded and uncompressed.
|
75
|
+
Finally, the 'current' symlink will get updated to match the remote version.
|
76
|
+
|
77
|
+
#### --bucket
|
78
|
+
|
79
|
+
Your instances must have read/write access to the specified S3 bucket.
|
80
|
+
Make sure your instances have the correct permissions with an IAM role
|
81
|
+
or make sure you specify the ````AWS_ACCESS_KEY_ID```` and ````AWS_SECRET_ACCESS_KEY```` environment variables.
|
82
|
+
Under the hood this gem uses the [aws-sdk](https://github.com/aws/aws-sdk-ruby) gem for all API calls.
|
83
|
+
|
84
|
+
#### --deploy-to
|
85
|
+
|
86
|
+
This flag must be set to match the Capistrano configuration variable of the same name.
|
87
|
+
You can normally find it in your *deploy.rb*. An example from a stock config:
|
88
|
+
|
89
|
+
set :deploy_to, "/var/www/my_app_name"
|
90
|
+
|
91
|
+
## Rails boot script
|
92
|
+
|
93
|
+
This is just a sample.
|
94
|
+
You will need to modify it based on your Capistrano configuration.
|
95
|
+
Watch the commands that are executed when you run ````cap production deploy```` to see what commands are executed.
|
96
|
+
Also make sure you run it as ````:deploy_user```` as specified in your *deploy.rb*.
|
97
|
+
|
98
|
+
#!/bin/bash
|
99
|
+
|
100
|
+
echo '***** pulling releases *****' &&
|
101
|
+
releases -b my-releases-bucket -d /apps/my-app -m pull &&
|
102
|
+
|
103
|
+
echo '***** Deleting old PID files *****' &&
|
104
|
+
rm -rf /apps/my-app/shared/tmp/pids/* &&
|
105
|
+
|
106
|
+
echo '***** Installing gems *****' &&
|
107
|
+
bundle install --path /apps/my-app/shared/bundle --without development test --deployment --quiet &&
|
108
|
+
|
109
|
+
echo '***** Precompiling assets *****' &&
|
110
|
+
bundle exec rake assets:precompile &&
|
111
|
+
|
112
|
+
echo '***** Starting web server *****' &&
|
113
|
+
echo 'put your web server command here' &&
|
114
|
+
|
115
|
+
echo '***** Starting job server *****' &&
|
116
|
+
echo 'put your job server command here'
|
117
|
+
|
26
118
|
## Development
|
27
119
|
|
28
120
|
After checking out the repo, run `bin/setup` to install dependencies.
|
@@ -27,29 +27,45 @@ module Capistrano
|
|
27
27
|
|
28
28
|
def push
|
29
29
|
make_dirs
|
30
|
+
|
30
31
|
remotes = Set.new(remote_releases)
|
31
|
-
|
32
|
-
|
32
|
+
puts "Remote releases: #{remotes.to_a.inspect}"
|
33
|
+
|
34
|
+
to_upload_releases = local_releases.reject { |r| remotes.include?(r) }
|
35
|
+
to_upload_releases.each do |r|
|
36
|
+
puts "Uploading release: #{r}"
|
37
|
+
upload_release(r)
|
38
|
+
end
|
39
|
+
|
40
|
+
puts "Setting remote current to: #{remote_current}"
|
33
41
|
self.remote_current = local_current
|
34
42
|
|
35
|
-
|
43
|
+
upload_bundle
|
44
|
+
|
45
|
+
to_upload_releases
|
36
46
|
end
|
37
47
|
|
38
48
|
def pull
|
39
49
|
make_dirs
|
50
|
+
|
40
51
|
locals = Set.new(local_releases)
|
41
52
|
puts "Local releases: #{locals.to_a.inspect}"
|
42
|
-
|
43
|
-
|
44
|
-
|
53
|
+
|
54
|
+
to_download_releases = remote_releases.last(params[:keep_releases])
|
55
|
+
.reject { |r| locals.include?(r) }
|
56
|
+
to_download_releases.each do |r|
|
45
57
|
puts "Downloading release: #{r}"
|
46
|
-
|
58
|
+
download_release(r)
|
47
59
|
end
|
60
|
+
|
48
61
|
self.local_current = remote_current
|
62
|
+
|
49
63
|
puts "Setting local current to: #{local_current}"
|
50
64
|
Dir.chdir(File.join(params[:deploy_to], 'current'))
|
51
65
|
|
52
|
-
|
66
|
+
download_bundle
|
67
|
+
|
68
|
+
to_download_releases
|
53
69
|
end
|
54
70
|
|
55
71
|
private
|
@@ -86,6 +102,10 @@ module Capistrano
|
|
86
102
|
File.join(params[:deploy_to], 'releases')
|
87
103
|
end
|
88
104
|
|
105
|
+
def local_shared_path
|
106
|
+
File.join(params[:deploy_to], 'shared')
|
107
|
+
end
|
108
|
+
|
89
109
|
def local_releases
|
90
110
|
Dir.glob("#{local_releases_path}/*")
|
91
111
|
.sort
|
@@ -95,7 +115,7 @@ module Capistrano
|
|
95
115
|
def remote_releases
|
96
116
|
bucket.objects
|
97
117
|
.map(&:key)
|
98
|
-
.select { |k| k
|
118
|
+
.select { |k| k =~ /\A\d+.*\.tar\.gz\z/ }
|
99
119
|
.map { |k| k.gsub(/\.tar\.gz\z/, '') }
|
100
120
|
.sort
|
101
121
|
end
|
@@ -124,8 +144,8 @@ module Capistrano
|
|
124
144
|
nil
|
125
145
|
end
|
126
146
|
|
127
|
-
def
|
128
|
-
tmp = Tempfile.new(["capistrano-releases_upload-#{release}", '.tar.gz'],
|
147
|
+
def upload_release(release)
|
148
|
+
tmp = Tempfile.new(["capistrano-releases_upload-release-#{release}", '.tar.gz'],
|
129
149
|
Dir.tmpdir, encoding: 'BINARY')
|
130
150
|
|
131
151
|
begin
|
@@ -137,8 +157,8 @@ module Capistrano
|
|
137
157
|
end
|
138
158
|
end
|
139
159
|
|
140
|
-
def
|
141
|
-
tmp = Tempfile.new(["capistrano-releases_download-#{release}", '.tar.gz'],
|
160
|
+
def download_release(release)
|
161
|
+
tmp = Tempfile.new(["capistrano-releases_download-release-#{release}", '.tar.gz'],
|
142
162
|
Dir.tmpdir, encoding: 'BINARY')
|
143
163
|
|
144
164
|
begin
|
@@ -150,6 +170,40 @@ module Capistrano
|
|
150
170
|
end
|
151
171
|
end
|
152
172
|
|
173
|
+
def upload_bundle
|
174
|
+
return unless Dir.exist?(File.join(local_shared_path, 'bundle'))
|
175
|
+
|
176
|
+
puts 'Uploading bundle'
|
177
|
+
|
178
|
+
tmp = Tempfile.new(['capistrano-releases_upload-bundle', '.tar.gz'],
|
179
|
+
Dir.tmpdir, encoding: 'BINARY')
|
180
|
+
|
181
|
+
begin
|
182
|
+
system!(['tar', 'Ccfz', local_shared_path, tmp.path, 'bundle'])
|
183
|
+
bucket.object('bundle.tar.gz').put(body: tmp)
|
184
|
+
ensure
|
185
|
+
tmp.close
|
186
|
+
tmp.unlink
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def download_bundle
|
191
|
+
return if Dir.exist?(File.join(local_shared_path, 'bundle'))
|
192
|
+
|
193
|
+
puts 'Downloading bundle'
|
194
|
+
|
195
|
+
tmp = Tempfile.new(['capistrano-releases_download-bundle', '.tar.gz'],
|
196
|
+
Dir.tmpdir, encoding: 'BINARY')
|
197
|
+
|
198
|
+
begin
|
199
|
+
bucket.object('bundle.tar.gz').get(response_target: tmp)
|
200
|
+
system!(['tar', 'Cxfz', local_shared_path, tmp.path])
|
201
|
+
ensure
|
202
|
+
tmp.close
|
203
|
+
tmp.unlink
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
153
207
|
def bucket
|
154
208
|
@bucket ||= Aws::S3::Bucket.new(params[:bucket])
|
155
209
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano-releases
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chad Remesch
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|