deployment 0.0.2 → 1.0.3
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.
- data/lib/deployment.rb +0 -3
- data/lib/deployment/deploy.rb +156 -0
- data/lib/deployment/unicorn.rb +53 -0
- metadata +8 -14
- data/.gitignore +0 -17
- data/Gemfile +0 -4
- data/LICENSE.txt +0 -22
- data/README.md +0 -29
- data/Rakefile +0 -1
- data/deployment.gemspec +0 -19
- data/lib/deployment/version.rb +0 -3
data/lib/deployment.rb
CHANGED
@@ -0,0 +1,156 @@
|
|
1
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
2
|
+
|
3
|
+
## Define the roles
|
4
|
+
role :app
|
5
|
+
role :storage
|
6
|
+
|
7
|
+
## Server configuration
|
8
|
+
set :user, `whoami`.chomp
|
9
|
+
set :ssh_options, {:forward_agent => true, :port => 22}
|
10
|
+
|
11
|
+
## Set the `current_revision`
|
12
|
+
set(:current_revision) { capture("cd #{deploy_to} && git log --pretty=%H -n 1", :except => { :no_release => true }).chomp }
|
13
|
+
|
14
|
+
## Return the deployment path
|
15
|
+
def deploy_to
|
16
|
+
fetch(:deploy_to, nil) || "/opt/apps/#{fetch(:application)}"
|
17
|
+
end
|
18
|
+
|
19
|
+
## Return an array of all environments which should be deployed
|
20
|
+
def environments
|
21
|
+
fetch(:environments, nil) || [fetch(:environment, 'production')]
|
22
|
+
end
|
23
|
+
|
24
|
+
## Deployment namespace
|
25
|
+
namespace :deploy do
|
26
|
+
desc 'Deploy the latest revision of the application'
|
27
|
+
task :default do
|
28
|
+
update_code
|
29
|
+
restart
|
30
|
+
end
|
31
|
+
|
32
|
+
desc 'Deploy and migrate the database before restart'
|
33
|
+
task :migrations do
|
34
|
+
set :run_migrations, true
|
35
|
+
default
|
36
|
+
end
|
37
|
+
|
38
|
+
task :update_code, :roles => [:app, :storage] do
|
39
|
+
## Create a branch for previous (pre-deployment)
|
40
|
+
run "cd #{deploy_to} && git branch -d rollback && git branch rollback"
|
41
|
+
## Update remote repository and merge deploy branch into current branch
|
42
|
+
run "cd #{deploy_to} && git fetch origin && git reset --hard origin/#{fetch(:branch)}"
|
43
|
+
finalise
|
44
|
+
end
|
45
|
+
|
46
|
+
task :finalise, :roles => [:app, :storage] do
|
47
|
+
execute = Array.new
|
48
|
+
execute << "cd #{deploy_to}"
|
49
|
+
execute << "git submodule init"
|
50
|
+
execute << "git submodule sync"
|
51
|
+
execute << "git submodule update --recursive"
|
52
|
+
run execute.join(' && ')
|
53
|
+
|
54
|
+
run "cd #{deploy_to} && bundle --deployment --quiet"
|
55
|
+
migrate if fetch(:run_migrations, false)
|
56
|
+
end
|
57
|
+
|
58
|
+
desc 'Setup the repository on the remote server for the first time'
|
59
|
+
task :setup, :roles => [:app, :storage] do
|
60
|
+
run "rm -rf #{deploy_to}"
|
61
|
+
run "git clone -n #{fetch(:repository)} #{deploy_to} --branch #{fetch(:branch)}"
|
62
|
+
run "cd #{deploy_to} && git branch rollback && git checkout -b deploy && git branch -d #{fetch(:branch)}"
|
63
|
+
upload_db_config
|
64
|
+
update_code
|
65
|
+
end
|
66
|
+
|
67
|
+
desc 'Upload the database configuration file'
|
68
|
+
task :upload_db_config, :roles => [:app, :storage] do
|
69
|
+
put "production:\n adapter: mysql2\n encoding: utf8\n reconnect: true\n database: #{fetch(:application, 'databasename')}\n pool: 5\n username: #{fetch(:application, 'dbusernmae')}\n password: #{ENV['DBPASS'] || 'xxxx'}\n host: #{fetch(:database_host, 'db-a-vip.cloud.atechmedia.net')}\n", File.join(deploy_to, 'config', 'database.yml')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
## ==================================================================
|
74
|
+
## Database
|
75
|
+
## ==================================================================
|
76
|
+
desc 'Run database migrations on the remote'
|
77
|
+
task :migrate, :roles => :app, :only => {:database_ops => true} do
|
78
|
+
for environment in environments
|
79
|
+
run "cd #{deploy_to} && RAILS_ENV=#{environment} bundle exec rake db:migrate"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
## ==================================================================
|
84
|
+
## Rollback
|
85
|
+
## ==================================================================
|
86
|
+
desc 'Rollback to the previous deployment'
|
87
|
+
task :rollback, :roles => [:app, :storage] do
|
88
|
+
run "cd #{deploy_to} && git reset --hard rollback"
|
89
|
+
deploy.finalise
|
90
|
+
deploy.restart
|
91
|
+
end
|
92
|
+
|
93
|
+
## ==================================================================
|
94
|
+
## Test
|
95
|
+
## ==================================================================
|
96
|
+
desc 'Test the deployment connection'
|
97
|
+
task :testing do
|
98
|
+
run "whoami"
|
99
|
+
end
|
100
|
+
|
101
|
+
## ==================================================================
|
102
|
+
## init
|
103
|
+
## ==================================================================
|
104
|
+
desc 'Restart the whole remote application'
|
105
|
+
task :restart, :roles => :app do
|
106
|
+
unicorn.restart unless fetch(:skip_unicorn, false)
|
107
|
+
workers.restart if respond_to?(:workers)
|
108
|
+
end
|
109
|
+
|
110
|
+
desc 'Stop the whole remote application'
|
111
|
+
task :stop, :roles => :app do
|
112
|
+
unicorn.stop unless fetch(:skip_unicorn, false)
|
113
|
+
workers.stop if respond_to?(:workers)
|
114
|
+
end
|
115
|
+
|
116
|
+
desc 'Start the whole remote application'
|
117
|
+
task :start, :roles => :app do
|
118
|
+
unicorn.start unless fetch(:skip_unicorn, false)
|
119
|
+
workers.start if respond_to?(:workers)
|
120
|
+
end
|
121
|
+
|
122
|
+
## ==================================================================
|
123
|
+
## Unicorn Management
|
124
|
+
## ==================================================================
|
125
|
+
namespace :unicorn do
|
126
|
+
task :start, :roles => :app do
|
127
|
+
upload_config
|
128
|
+
for environment in environments
|
129
|
+
run "sudo -u app sh -c \"umask 002 && cd #{deploy_to} && bundle exec unicorn_rails -E #{environment} -c #{deploy_to}/config/unicorn.rb -D\""
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
task :stop, :roles => :app do
|
134
|
+
for environment in environments
|
135
|
+
run "sudo -u app sh -c \"kill `cat #{deploy_to}/tmp/pids/unicorn.#{environment}.pid`\""
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
task :restart, :roles => :app do
|
140
|
+
upload_config
|
141
|
+
for environment in environments
|
142
|
+
run "sudo -u app sh -c \"kill -USR2 `cat #{deploy_to}/tmp/pids/unicorn.#{environment}.pid`\""
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
task :upload_config, :roles => :app do
|
147
|
+
unless fetch(:skip_unicorn_config, false)
|
148
|
+
template_config = File.read(File.expand_path('../unicorn.rb', __FILE__))
|
149
|
+
template_config.gsub!('$WORKER_PROCESSES', fetch(:unicorn_workers, 4).to_s)
|
150
|
+
template_config.gsub!('$TIMEOUT', fetch(:unicorn_timeout, 30).to_s)
|
151
|
+
put template_config, File.join(deploy_to, 'config', 'unicorn.rb')
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
rails_env = ENV['RAILS_ENV'] || 'production'
|
2
|
+
|
3
|
+
## Directory to use for stuff
|
4
|
+
rails_root = File.expand_path('../../', __FILE__)
|
5
|
+
FileUtils.mkdir_p(File.join(rails_root, 'tmp', 'sockets'))
|
6
|
+
FileUtils.mkdir_p(File.join(rails_root, 'tmp', 'pids'))
|
7
|
+
FileUtils.mkdir_p(File.join(rails_root, 'log'))
|
8
|
+
|
9
|
+
## Set the number of worker processes which can be spawned
|
10
|
+
worker_processes $WORKER_PROCESSES
|
11
|
+
|
12
|
+
## Preload the application into master for fast worker spawn
|
13
|
+
## times.
|
14
|
+
preload_app true
|
15
|
+
|
16
|
+
## Restart any workers which haven't responded for 30 seconds.
|
17
|
+
timeout $TIMEOUT
|
18
|
+
|
19
|
+
## Store the pid file safely away in the pids folder
|
20
|
+
logger Logger.new(File.join(rails_root, 'log', "unicorn.#{rails_env}.log"))
|
21
|
+
pid File.join(rails_root, 'tmp', 'pids', "unicorn.#{rails_env}.pid")
|
22
|
+
|
23
|
+
## Listen on a unix data socket
|
24
|
+
listen File.join(rails_root, 'tmp', 'sockets', "unicorn.#{rails_env}.sock")
|
25
|
+
|
26
|
+
before_fork do |server, worker|
|
27
|
+
# When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
|
28
|
+
# immediately start loading up a new version of itself (loaded with a new
|
29
|
+
# version of our app). When this new Unicorn is completely loaded
|
30
|
+
# it will begin spawning workers. The first worker spawned will check to
|
31
|
+
# see if an .oldbin pidfile exists. If so, this means we've just booted up
|
32
|
+
# a new Unicorn and need to tell the old one that it can now die. To do so
|
33
|
+
# we send it a QUIT.
|
34
|
+
#
|
35
|
+
# Using this method we get 0 downtime deploys.
|
36
|
+
|
37
|
+
old_pid = File.join(rails_root, 'tmp', 'pids', "unicorn.#{rails_env}.pid.oldbin")
|
38
|
+
if File.exists?(old_pid) && server.pid != old_pid
|
39
|
+
begin
|
40
|
+
Process.kill("QUIT", File.read(old_pid).to_i)
|
41
|
+
rescue Errno::ENOENT, Errno::ESRCH
|
42
|
+
# someone else did our job for us
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
after_fork do |server, worker|
|
48
|
+
# Unicorn master loads the app then forks off workers - because of the way
|
49
|
+
# Unix forking works, we need to make sure we aren't using any of the parent's
|
50
|
+
# sockets, e.g. db connection
|
51
|
+
ActiveRecord::Base.establish_connection
|
52
|
+
srand
|
53
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deployment
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,24 +9,18 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-29 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description:
|
15
|
-
email:
|
16
|
-
- danq@atechmedia.com
|
14
|
+
description:
|
15
|
+
email: danq@keeptrack.co
|
17
16
|
executables: []
|
18
17
|
extensions: []
|
19
18
|
extra_rdoc_files: []
|
20
19
|
files:
|
21
|
-
- .
|
22
|
-
-
|
23
|
-
- LICENSE.txt
|
24
|
-
- README.md
|
25
|
-
- Rakefile
|
26
|
-
- deployment.gemspec
|
20
|
+
- lib/deployment/deploy.rb
|
21
|
+
- lib/deployment/unicorn.rb
|
27
22
|
- lib/deployment.rb
|
28
|
-
|
29
|
-
homepage: ''
|
23
|
+
homepage: http://keeptrack.co
|
30
24
|
licenses: []
|
31
25
|
post_install_message:
|
32
26
|
rdoc_options: []
|
@@ -49,5 +43,5 @@ rubyforge_project:
|
|
49
43
|
rubygems_version: 1.8.23
|
50
44
|
signing_key:
|
51
45
|
specification_version: 3
|
52
|
-
summary:
|
46
|
+
summary: Gem to make deployments with Capistrano easier.
|
53
47
|
test_files: []
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/LICENSE.txt
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
Copyright (c) 2013 Dan Quinney
|
2
|
-
|
3
|
-
MIT License
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
-
a copy of this software and associated documentation files (the
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
11
|
-
the following conditions:
|
12
|
-
|
13
|
-
The above copyright notice and this permission notice shall be
|
14
|
-
included in all copies or substantial portions of the Software.
|
15
|
-
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
# Deployment
|
2
|
-
|
3
|
-
TODO: Write a gem description
|
4
|
-
|
5
|
-
## Installation
|
6
|
-
|
7
|
-
Add this line to your application's Gemfile:
|
8
|
-
|
9
|
-
gem 'deployment'
|
10
|
-
|
11
|
-
And then execute:
|
12
|
-
|
13
|
-
$ bundle
|
14
|
-
|
15
|
-
Or install it yourself as:
|
16
|
-
|
17
|
-
$ gem install deployment
|
18
|
-
|
19
|
-
## Usage
|
20
|
-
|
21
|
-
TODO: Write usage instructions here
|
22
|
-
|
23
|
-
## Contributing
|
24
|
-
|
25
|
-
1. Fork it
|
26
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
-
5. Create new Pull Request
|
data/Rakefile
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require "bundler/gem_tasks"
|
data/deployment.gemspec
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'deployment/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |gem|
|
7
|
-
gem.name = "deployment"
|
8
|
-
gem.version = Deployment::VERSION
|
9
|
-
gem.authors = ["Dan Quinney"]
|
10
|
-
gem.email = ["danq@atechmedia.com"]
|
11
|
-
gem.description = "Gem to make deployments with Capistrano easier."
|
12
|
-
gem.summary = "Placeholder for now."
|
13
|
-
gem.homepage = ""
|
14
|
-
|
15
|
-
gem.files = `git ls-files`.split($/)
|
16
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
-
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
-
gem.require_paths = ["lib"]
|
19
|
-
end
|
data/lib/deployment/version.rb
DELETED