capistrano-releases 0.1.1 → 0.2.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
- 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
|