godfat-app-deploy 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +3 -0
- data/README +38 -0
- data/Rakefile +58 -0
- data/TODO +4 -0
- data/app-deploy.gemspec +35 -0
- data/example.rake +79 -0
- data/lib/app-deploy.rb +186 -0
- data/lib/app-deploy/deploy.rake +18 -0
- data/lib/app-deploy/gem.rake +25 -0
- data/lib/app-deploy/git.rake +76 -0
- data/lib/app-deploy/install.rake +17 -0
- data/lib/app-deploy/merb.rake +20 -0
- data/lib/app-deploy/mongrel.rake +13 -0
- data/lib/app-deploy/nginx.rake +25 -0
- data/lib/app-deploy/rack.rake +34 -0
- data/lib/app-deploy/rack_cluster.rb +73 -0
- data/lib/app-deploy/rack_daemon.rb +62 -0
- data/lib/app-deploy/server.rake +9 -0
- data/lib/app-deploy/thin.rake +13 -0
- data/lib/app-deploy/version.rb +4 -0
- metadata +100 -0
data/CHANGES
ADDED
data/README
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
tasks:
|
2
|
+
|
3
|
+
$ rake -T app
|
4
|
+
(in /home/photos)
|
5
|
+
rake app:deploy # deploy to master state
|
6
|
+
rake app:deploy:after # after deploy hook for you to override
|
7
|
+
rake app:deploy:before # before deploy hook for you to override
|
8
|
+
rake app:gem:install # install gems
|
9
|
+
rake app:gem:reinstall # reinstall gems
|
10
|
+
rake app:gem:uninstall # uninstall gems
|
11
|
+
rake app:git[cmd] # generic git cmd walk through all dependency
|
12
|
+
rake app:git:clone # clone repoitory from github
|
13
|
+
rake app:git:gc # git gc
|
14
|
+
rake app:git:pull # pull anything from origin
|
15
|
+
rake app:git:reset # make anything reflect master state
|
16
|
+
rake app:install # install this application
|
17
|
+
rake app:install:after # after install hook for you to override
|
18
|
+
rake app:install:before # before install hook for you to override
|
19
|
+
rake app:merb:restart # restart the merb server
|
20
|
+
rake app:merb:start[config] # start the merb server, default config: config/merb.yml
|
21
|
+
rake app:merb:stop # stop the merb server
|
22
|
+
rake app:mongrel:restart # restart the mongrel cluster
|
23
|
+
rake app:mongrel:start # start the mongrel cluster
|
24
|
+
rake app:mongrel:stop # stop the mongrel cluster
|
25
|
+
rake app:nginx:restart # reload config
|
26
|
+
rake app:nginx:start[config,nginx] # start nginx, default config is config/nginx.conf, nginx is /usr/sbin/nginx
|
27
|
+
rake app:nginx:stop[timeout] # stop nginx
|
28
|
+
rake app:rack:restart[config] # restart the rack cluster
|
29
|
+
rake app:rack:start[config] # start the rack cluster
|
30
|
+
rake app:rack:stop[config] # stop the rack cluster
|
31
|
+
rake app:server:restart # please define your server:restart task
|
32
|
+
rake app:thin:restart[config] # restart the thin cluster
|
33
|
+
rake app:thin:start[config] # start the thin cluster
|
34
|
+
rake app:thin:stop[config] # stop the thin cluster
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
example: see example.rake
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bones'
|
5
|
+
Bones.setup
|
6
|
+
rescue LoadError
|
7
|
+
load 'tasks/setup.rb' # this line should already be there
|
8
|
+
end
|
9
|
+
|
10
|
+
PROJ.name = 'app-deploy'
|
11
|
+
# supress warnings, there's too many warnings in dm-core
|
12
|
+
# PROJ.ruby_opts.delete '-w'
|
13
|
+
|
14
|
+
# PROJ.gem.dependencies << ['dm-core', '>=0.9.3']
|
15
|
+
# PROJ.gem.development_dependencies << ['minitest', '>=1.3.0']
|
16
|
+
# PROJ.gem.executables = ["bin/#{PROJ.name}"]
|
17
|
+
|
18
|
+
task :default do
|
19
|
+
Rake.application.options.show_task_pattern = /./
|
20
|
+
Rake.application.display_tasks_and_comments
|
21
|
+
end
|
22
|
+
|
23
|
+
namespace :gem do
|
24
|
+
desc "create #{PROJ.name}.gemspec"
|
25
|
+
task 'gemspec' do
|
26
|
+
puts "rake gem:debug > #{PROJ.name}.gemspec"
|
27
|
+
File.open("#{PROJ.name}.gemspec", 'w'){|spec| spec << `rake gem:debug`.sub(/.*/, '')}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
PROJ.authors = 'Lin Jen-Shin (a.k.a. godfat 真常)'
|
32
|
+
PROJ.email = 'godfat (XD) godfat.org'
|
33
|
+
PROJ.url = "http://github.com/godfat/#{PROJ.name}"
|
34
|
+
PROJ.description = PROJ.summary = paragraphs_of('README', 'description').join("\n\n")
|
35
|
+
PROJ.changes = paragraphs_of('CHANGES', 0..1).join("\n\n")
|
36
|
+
PROJ.rubyforge.name = 'ludy'
|
37
|
+
PROJ.version = File.read("lib/#{PROJ.name}/version.rb").gsub(/.*VERSION = '(.*)'.*/m, '\1')
|
38
|
+
|
39
|
+
PROJ.manifest_file = 'Manifest'
|
40
|
+
PROJ.exclude += ['^Manifest$', '^tmp', 'tmp$', '^pkg',
|
41
|
+
'^\.gitignore$', '^ann-', '\.sqlite3$', '\.db$']
|
42
|
+
|
43
|
+
PROJ.rdoc.remote_dir = PROJ.name
|
44
|
+
|
45
|
+
PROJ.readme_file = 'README'
|
46
|
+
PROJ.rdoc.main = 'README'
|
47
|
+
PROJ.rdoc.exclude += ['Rakefile', '^tasks', '^test']
|
48
|
+
PROJ.rdoc.include << '\w+'
|
49
|
+
PROJ.rdoc.opts << '--diagram' if !WIN32 and `which dot` =~ %r/\/dot/
|
50
|
+
PROJ.rdoc.opts += ['--charset=utf-8', '--inline-source',
|
51
|
+
'--line-numbers', '--promiscuous']
|
52
|
+
|
53
|
+
PROJ.spec.opts << '--color'
|
54
|
+
|
55
|
+
PROJ.ann.file = "ann-#{PROJ.name}-#{PROJ.version}"
|
56
|
+
PROJ.ann.paragraphs.concat %w[LINKS SYNOPSIS REQUIREMENTS INSTALL LICENSE]
|
57
|
+
|
58
|
+
CLEAN.include Dir['**/*.rbc']
|
data/TODO
ADDED
data/app-deploy.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
# -*- encoding: utf-8 -*-
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = %q{app-deploy}
|
6
|
+
s.version = "0.5.0"
|
7
|
+
|
8
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
|
+
s.authors = ["Lin Jen-Shin (a.k.a. godfat \347\234\237\345\270\270)"]
|
10
|
+
s.date = %q{2009-01-13}
|
11
|
+
s.description = %q{}
|
12
|
+
s.email = %q{godfat (XD) godfat.org}
|
13
|
+
s.extra_rdoc_files = ["CHANGES", "README", "TODO", "app-deploy.gemspec", "example.rake", "lib/app-deploy/deploy.rake", "lib/app-deploy/gem.rake", "lib/app-deploy/git.rake", "lib/app-deploy/install.rake", "lib/app-deploy/merb.rake", "lib/app-deploy/mongrel.rake", "lib/app-deploy/nginx.rake", "lib/app-deploy/rack.rake", "lib/app-deploy/server.rake", "lib/app-deploy/thin.rake"]
|
14
|
+
s.files = ["CHANGES", "README", "Rakefile", "TODO", "app-deploy.gemspec", "example.rake", "lib/app-deploy.rb", "lib/app-deploy/deploy.rake", "lib/app-deploy/gem.rake", "lib/app-deploy/git.rake", "lib/app-deploy/install.rake", "lib/app-deploy/merb.rake", "lib/app-deploy/mongrel.rake", "lib/app-deploy/nginx.rake", "lib/app-deploy/rack.rake", "lib/app-deploy/rack_cluster.rb", "lib/app-deploy/rack_daemon.rb", "lib/app-deploy/server.rake", "lib/app-deploy/thin.rake", "lib/app-deploy/version.rb"]
|
15
|
+
s.has_rdoc = true
|
16
|
+
s.homepage = %q{http://github.com/godfat/app-deploy}
|
17
|
+
s.rdoc_options = ["--diagram", "--charset=utf-8", "--inline-source", "--line-numbers", "--promiscuous", "--main", "README"]
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
s.rubyforge_project = %q{ludy}
|
20
|
+
s.rubygems_version = %q{1.3.1}
|
21
|
+
s.summary = %q{}
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 2
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
s.add_development_dependency(%q<bones>, [">= 2.2.0"])
|
29
|
+
else
|
30
|
+
s.add_dependency(%q<bones>, [">= 2.2.0"])
|
31
|
+
end
|
32
|
+
else
|
33
|
+
s.add_dependency(%q<bones>, [">= 2.2.0"])
|
34
|
+
end
|
35
|
+
end
|
data/example.rake
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'app-deploy'
|
6
|
+
|
7
|
+
rescue LoadError
|
8
|
+
|
9
|
+
puts "app-deploy not found, automaticly downloading and installing..."
|
10
|
+
|
11
|
+
`git clone git://github.com/godfat/app-deploy.git tmp/app-deploy`
|
12
|
+
Dir.chdir 'tmp/app-deploy'
|
13
|
+
|
14
|
+
sh 'rake clobber'
|
15
|
+
sh 'rake gem:package'
|
16
|
+
sh 'gem install --local pkg/app-deploy-*.gem --no-ri --no-rdoc'
|
17
|
+
|
18
|
+
puts "Please re-invoke: rake #{ARGV.join(' ')}"
|
19
|
+
exit(1)
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
task :default do
|
24
|
+
Rake.application.options.show_task_pattern = /./
|
25
|
+
Rake.application.display_tasks_and_comments
|
26
|
+
end
|
27
|
+
|
28
|
+
# install gem from rubyforge
|
29
|
+
AppDeploy.dependency_gem :gem => 'bones'
|
30
|
+
|
31
|
+
# install gem from github
|
32
|
+
AppDeploy.dependency_gem :gem => 'pagfiy', :source => 'http://gems.github.com'
|
33
|
+
|
34
|
+
# clone and build and install gem from github with bones
|
35
|
+
AppDeploy.dependency_gem :github_user => 'godfat',
|
36
|
+
:github_project => 'friendly_format',
|
37
|
+
:task_gem => 'bones',
|
38
|
+
:git_path => 'tmp/friendly_format'
|
39
|
+
|
40
|
+
# same as above but with hoe
|
41
|
+
AppDeploy.dependency_gem :github_user => 'godfat',
|
42
|
+
:github_project => 'mogilefs-client',
|
43
|
+
:task_gem => 'hoe',
|
44
|
+
:git_path => 'tmp/mogilefs-client'
|
45
|
+
|
46
|
+
# same as above but with custom install script
|
47
|
+
AppDeploy.dependency_gem :github_user => 'godfat',
|
48
|
+
:github_project => 'app-deploy',
|
49
|
+
:git_path => 'tmp/app-deploy' do
|
50
|
+
sh 'rake clobber'
|
51
|
+
sh 'rake gem:package'
|
52
|
+
sh 'gem install --local pkg/app-deploy-*.gem --no-ri --no-rdoc'
|
53
|
+
end
|
54
|
+
|
55
|
+
# no gem to install, just clone it
|
56
|
+
AppDeploy.dependency :github_user => 'godfat',
|
57
|
+
:github_project => 'in_place_editing',
|
58
|
+
:git_path => 'tmp/vendor/plugins/in_place_editing'
|
59
|
+
|
60
|
+
namespace :app do
|
61
|
+
namespace :install do
|
62
|
+
# before install hook
|
63
|
+
task :before do
|
64
|
+
# explicit install gem, ignore gem that was already installed
|
65
|
+
AppDeploy.install_gem(:gem => 'hoe')
|
66
|
+
end
|
67
|
+
|
68
|
+
# after install hook
|
69
|
+
task :after do
|
70
|
+
# explicit uninstall gem, ignore gem that was not installed
|
71
|
+
AppDeploy.uninstall_gem(:gem => 'zzz')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
namespace :server do
|
76
|
+
# use thin as server
|
77
|
+
task :restart => 'thin:restart'
|
78
|
+
end
|
79
|
+
end
|
data/lib/app-deploy.rb
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
|
2
|
+
%w[deploy gem git install merb mongrel nginx server thin rack].each{ |task|
|
3
|
+
load "app-deploy/#{task}.rake"
|
4
|
+
}
|
5
|
+
|
6
|
+
module AppDeploy
|
7
|
+
module_function
|
8
|
+
def github; @github ||= []; end
|
9
|
+
def dependency opts = {}
|
10
|
+
opts = opts.dup
|
11
|
+
opts[:git_path] ||= opts[:github_project]
|
12
|
+
github << opts.freeze
|
13
|
+
end
|
14
|
+
|
15
|
+
def gem; @gem ||= []; end
|
16
|
+
def dependency_gem opts = {}, &block
|
17
|
+
opts = opts.dup
|
18
|
+
|
19
|
+
if opts[:github_project]
|
20
|
+
opts[:git_path] ||= opts[:github_project]
|
21
|
+
opts[:task_gem] = block if block_given?
|
22
|
+
github << opts.freeze
|
23
|
+
end
|
24
|
+
|
25
|
+
gem << opts.freeze
|
26
|
+
end
|
27
|
+
|
28
|
+
def each *with
|
29
|
+
with = [:github, :gem] if with.empty?
|
30
|
+
cwd = Dir.pwd
|
31
|
+
|
32
|
+
# github's gem would be in @github and @gem,
|
33
|
+
# so call uniq to ensure it wouldn't get called twice.
|
34
|
+
with.map{ |kind| AppDeploy.send(kind) }.flatten.uniq.each{ |opts|
|
35
|
+
puts
|
36
|
+
|
37
|
+
begin
|
38
|
+
if opts[:github_project]
|
39
|
+
if File.directory?(opts[:git_path])
|
40
|
+
Dir.chdir(opts[:git_path])
|
41
|
+
else
|
42
|
+
puts "Skip #{opts[:github_project]}, because it was not found"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
yield(opts)
|
47
|
+
|
48
|
+
rescue RuntimeError => e
|
49
|
+
puts e
|
50
|
+
|
51
|
+
ensure
|
52
|
+
Dir.chdir(cwd)
|
53
|
+
|
54
|
+
end
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def extract_config config
|
59
|
+
require 'yaml'
|
60
|
+
YAML.load(File.read(config)).inject([]){ |result, opt_value|
|
61
|
+
opt, value = opt_value
|
62
|
+
if block_given?
|
63
|
+
result << yield(opt, value)
|
64
|
+
else
|
65
|
+
result << "--#{opt} #{value}"
|
66
|
+
end
|
67
|
+
result
|
68
|
+
}.compact.join(' ')
|
69
|
+
end
|
70
|
+
|
71
|
+
# about git
|
72
|
+
def clone opts
|
73
|
+
user, proj, path = opts[:github_user], opts[:github_project], opts[:git_path]
|
74
|
+
|
75
|
+
if File.exist?(path)
|
76
|
+
puts "Skip #{proj} because #{path} exists"
|
77
|
+
else
|
78
|
+
sh "git clone git://github.com/#{user}/#{proj}.git #{path}"
|
79
|
+
sh "git --git-dir #{path}/.git gc"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# about gem
|
84
|
+
def installed_gem? gem_name
|
85
|
+
`gem list '^#{gem_name}$'` =~ /^#{gem_name}/
|
86
|
+
end
|
87
|
+
|
88
|
+
def install_gem opts
|
89
|
+
gem_name = opts[:gem] || opts[:github_project]
|
90
|
+
|
91
|
+
if AppDeploy.installed_gem?(gem_name)
|
92
|
+
puts "Skip #{gem_name} because it was installed. Uninstall first if you want to reinstall"
|
93
|
+
|
94
|
+
else
|
95
|
+
if opts[:gem]
|
96
|
+
AppDeploy.install_gem_remote(opts[:gem], opts[:source])
|
97
|
+
else
|
98
|
+
AppDeploy.install_gem_local(opts[:github_project], opts[:task_gem])
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def uninstall_gem opts
|
105
|
+
gem_name = opts[:gem] || opts[:github_project]
|
106
|
+
if AppDeploy.installed_gem?(gem_name)
|
107
|
+
sh "gem uninstall #{gem_name}"
|
108
|
+
else
|
109
|
+
puts "Skip #{gem_name} because it was not installed"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def install_gem_remote gem_name, source = nil
|
114
|
+
sh "gem install #{gem_name} --no-ri --no-rdoc#{source ? ' --source' + source : ''}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def install_gem_local proj, task
|
118
|
+
case task
|
119
|
+
when 'bones'
|
120
|
+
sh 'rake clobber'
|
121
|
+
sh 'rake gem:package'
|
122
|
+
sh "gem install --local pkg/#{proj}-*.gem --no-ri --no-rdoc"
|
123
|
+
|
124
|
+
when 'hoe'
|
125
|
+
sh 'rake gem'
|
126
|
+
sh "gem install --local pkg/#{proj}-*.gem --no-ri --no-rdoc"
|
127
|
+
|
128
|
+
when Proc
|
129
|
+
task.call
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# about sending signal
|
134
|
+
def read_pid pid_path
|
135
|
+
if File.exist?(pid_path)
|
136
|
+
File.read(pid_path).strip.to_i
|
137
|
+
|
138
|
+
else
|
139
|
+
puts "WARN: No pid file found in #{pid_path}"
|
140
|
+
nil
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def hup pid_path, name = nil
|
146
|
+
if pid = AppDeploy.read_pid(pid_path)
|
147
|
+
puts "Sending HUP to #{name}(#{pid})..."
|
148
|
+
Process.kill('HUP', pid)
|
149
|
+
end
|
150
|
+
rescue Errno::ESRCH
|
151
|
+
puts "WARN: No such pid: #{pid}, removing #{pid_path}..."
|
152
|
+
File.delete(pid_path)
|
153
|
+
end
|
154
|
+
|
155
|
+
def term pid_path, name = nil, limit = 5
|
156
|
+
if pid = AppDeploy.read_pid(pid_path)
|
157
|
+
puts "Sending TERM to #{name}(#{pid})..."
|
158
|
+
|
159
|
+
else
|
160
|
+
return
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
require 'timeout'
|
165
|
+
begin
|
166
|
+
timeout(limit){
|
167
|
+
while true
|
168
|
+
Process.kill('TERM', pid)
|
169
|
+
sleep(0.1)
|
170
|
+
end
|
171
|
+
}
|
172
|
+
rescue Errno::ESRCH
|
173
|
+
if File.exist?(pid_path)
|
174
|
+
puts "WARN: No such pid: #{pid}, removing #{pid_path}..."
|
175
|
+
File.delete(pid_path)
|
176
|
+
else
|
177
|
+
puts "Killed #{name}(#{pid})"
|
178
|
+
end
|
179
|
+
|
180
|
+
rescue Timeout::Error
|
181
|
+
puts "Timeout(#{limit}) killing #{name}(#{pid})"
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
|
4
|
+
desc 'deploy to master state'
|
5
|
+
task :deploy => 'deploy:default'
|
6
|
+
|
7
|
+
namespace :deploy do
|
8
|
+
desc 'before deploy hook for you to override'
|
9
|
+
task :before
|
10
|
+
|
11
|
+
desc 'after deploy hook for you to override'
|
12
|
+
task :after
|
13
|
+
|
14
|
+
task :default => [:before, 'git:reset',
|
15
|
+
'server:restart', :after]
|
16
|
+
|
17
|
+
end # of deploy
|
18
|
+
end # of app
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
namespace :gem do
|
4
|
+
|
5
|
+
desc 'install gems'
|
6
|
+
task :install do
|
7
|
+
AppDeploy.each(:gem){ |dep|
|
8
|
+
puts "Installing #{dep[:gem] || dep[:github_project]}..."
|
9
|
+
AppDeploy.install_gem(dep)
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'uninstall gems'
|
14
|
+
task :uninstall do
|
15
|
+
AppDeploy.each(:gem){ |dep|
|
16
|
+
puts "Uninstalling #{dep[:gem] || dep[:github_project]}..."
|
17
|
+
AppDeploy.uninstall_gem(dep)
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'reinstall gems'
|
22
|
+
task :reinstall => [:uninstall, :install]
|
23
|
+
|
24
|
+
end # of gem
|
25
|
+
end # of app
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
|
4
|
+
desc 'generic git cmd walk through all dependency'
|
5
|
+
task :git, :cmd do |t, args|
|
6
|
+
cmd = args[:cmd] || 'status'
|
7
|
+
|
8
|
+
puts "Invoking git #{cmd}..."
|
9
|
+
begin
|
10
|
+
sh "git #{cmd}"
|
11
|
+
rescue RuntimeError => e
|
12
|
+
puts e
|
13
|
+
end
|
14
|
+
|
15
|
+
AppDeploy.each(:github){ |opts|
|
16
|
+
puts "Invoking git #{cmd} on #{opts[:github_project]}..."
|
17
|
+
begin
|
18
|
+
sh "git #{cmd}"
|
19
|
+
rescue RuntimeError => e
|
20
|
+
puts e
|
21
|
+
end
|
22
|
+
}
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
namespace :git do
|
27
|
+
|
28
|
+
desc 'make anything reflect master state'
|
29
|
+
task :reset do
|
30
|
+
puts 'Resetting...'
|
31
|
+
sh 'git stash' # oops, save your work first.
|
32
|
+
sh 'git reset --hard'
|
33
|
+
|
34
|
+
AppDeploy.each(:github){ |opts|
|
35
|
+
puts "Resetting #{opts[:github_project]}..."
|
36
|
+
sh 'git stash' # oops, save your work first.
|
37
|
+
sh 'git reset --hard'
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'clone repoitory from github'
|
42
|
+
task :clone do
|
43
|
+
AppDeploy.github.each{ |dep|
|
44
|
+
puts "Cloning #{dep[:github_project]}..."
|
45
|
+
AppDeploy.clone(dep)
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
desc 'pull anything from origin'
|
50
|
+
task :pull do
|
51
|
+
puts 'Pulling...'
|
52
|
+
begin
|
53
|
+
sh 'git pull' if `git remote` =~ /^origin$/
|
54
|
+
rescue RuntimeError => e
|
55
|
+
puts e
|
56
|
+
end
|
57
|
+
|
58
|
+
AppDeploy.each(:github){ |opts|
|
59
|
+
puts "Pulling #{opts[:github_project]}..."
|
60
|
+
sh 'git pull'
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
desc 'git gc'
|
65
|
+
task :gc do
|
66
|
+
puts 'Garbage collecting...'
|
67
|
+
sh 'git gc'
|
68
|
+
|
69
|
+
AppDeploy.each(:github){ |opts|
|
70
|
+
puts "Garbage collecting #{opts[:github_project]}..."
|
71
|
+
sh 'git gc'
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
end # of git
|
76
|
+
end # of app
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
|
4
|
+
desc 'install this application'
|
5
|
+
task :install => 'install:default'
|
6
|
+
|
7
|
+
namespace :install do
|
8
|
+
desc 'before install hook for you to override'
|
9
|
+
task :before
|
10
|
+
|
11
|
+
desc 'after install hook for you to override'
|
12
|
+
task :after
|
13
|
+
|
14
|
+
task :default => [:before, 'git:clone', 'gem:install', :after]
|
15
|
+
|
16
|
+
end # of install
|
17
|
+
end # of app
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
namespace :merb do
|
4
|
+
|
5
|
+
desc 'start the merb server, default config: config/merb.yml'
|
6
|
+
task :start, :config do |t, args|
|
7
|
+
sh "merb #{AppDeploy.extract_config(args[:config] || 'config/merb.yml')}"
|
8
|
+
end
|
9
|
+
|
10
|
+
desc 'stop the merb server'
|
11
|
+
task :stop do
|
12
|
+
sh 'merb -K all'
|
13
|
+
sleep(0.5)
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'restart the merb server'
|
17
|
+
task :restart => [:stop, :start]
|
18
|
+
|
19
|
+
end # of merb
|
20
|
+
end # of app
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
namespace :nginx do
|
4
|
+
|
5
|
+
desc 'start nginx, default config is config/nginx.conf, nginx is /usr/sbin/nginx'
|
6
|
+
task :start, :config, :nginx do |t, args|
|
7
|
+
if !File.exist?('tmp/pids/nginx.pid')
|
8
|
+
sh "#{args[:nginx] || '/usr/sbin/nginx'} -c #{args[:config] || 'config/nginx.conf'}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'reload config'
|
13
|
+
task :restart do
|
14
|
+
# sh 'kill -HUP `cat tmp/pids/nginx.pid`'
|
15
|
+
AppDeploy.hup('tmp/pids/nginx.pid', 'nginx')
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'stop nginx'
|
19
|
+
task :stop, :timeout do |t, args|
|
20
|
+
# sh "kill -TERM `cat tmp/pids/nginx.pid`"
|
21
|
+
AppDeploy.term('tmp/pids/nginx.pid', 'nginx', args[:timeout] || 5)
|
22
|
+
end
|
23
|
+
|
24
|
+
end # of nginx
|
25
|
+
end # of app
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
require 'app-deploy/rack_cluster'
|
3
|
+
|
4
|
+
namespace :app do
|
5
|
+
namespace :rack do
|
6
|
+
|
7
|
+
desc "start the rack cluster"
|
8
|
+
task :start, :config do |t, args|
|
9
|
+
config = args[:config] || 'config/rack_cluster.yml'
|
10
|
+
RackCluster.each(config){ |config, ruby_opts, rack_opts|
|
11
|
+
RackCluster.start(config, ruby_opts, rack_opts)
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "stop the rack cluster"
|
16
|
+
task :stop, :config do |t, args|
|
17
|
+
config = args[:config] || 'config/rack_cluster.yml'
|
18
|
+
RackCluster.each(config){ |config, ruby_opts, rack_opts|
|
19
|
+
AppDeploy.term(config[:pid], config[:server])
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "restart the rack cluster"
|
24
|
+
task :restart, :config do |t, args|
|
25
|
+
config = args[:config] || 'config/rack_cluster.yml'
|
26
|
+
RackCluster.each(config){ |config, ruby_opts, rack_opts|
|
27
|
+
AppDeploy.term(config[:pid], config[:server])
|
28
|
+
RackCluster.start(config, ruby_opts, rack_opts)
|
29
|
+
puts
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
end # of rack
|
34
|
+
end # of app
|
@@ -0,0 +1,73 @@
|
|
1
|
+
|
2
|
+
module RackCluster
|
3
|
+
module_function
|
4
|
+
def each path
|
5
|
+
config_orig = {}
|
6
|
+
rack_opts = AppDeploy.extract_config(path){ |opt, value|
|
7
|
+
case opt
|
8
|
+
when 'environment'; "--env #{value}"
|
9
|
+
|
10
|
+
when *%w[server host]
|
11
|
+
config_orig[opt.to_sym] = value
|
12
|
+
"--#{opt} #{value}"
|
13
|
+
|
14
|
+
when *%w[user group chdir servers require rackup daemonize port pid log]
|
15
|
+
config_orig[opt.to_sym] = value
|
16
|
+
nil # rack doesn't have this option
|
17
|
+
|
18
|
+
else
|
19
|
+
"--#{opt} #{value}"
|
20
|
+
|
21
|
+
end
|
22
|
+
}
|
23
|
+
|
24
|
+
config_orig[:servers].times{ |n|
|
25
|
+
config = config_orig.dup
|
26
|
+
ruby_opts = ''
|
27
|
+
rack_opts = ''
|
28
|
+
|
29
|
+
config[:port] += n if config[:port]
|
30
|
+
config[:pid] = RackCluster.pid_path(config[:pid], config[:port])
|
31
|
+
|
32
|
+
if config[:daemonize]
|
33
|
+
config[:log] = RackCluster.log_path(config[:log], config[:port])
|
34
|
+
|
35
|
+
args = [:pid, :log, :user, :group, :chdir].map{ |kind|
|
36
|
+
config.send(:[], kind)
|
37
|
+
}.join("', '")
|
38
|
+
|
39
|
+
init_script = "RackDaemon.daemonize('#{args}')"
|
40
|
+
rack_daemon = File.dirname(__FILE__) + '/rack_daemon.rb'
|
41
|
+
ruby_opts += " -r #{rack_daemon} -e \"#{init_script}\""
|
42
|
+
end
|
43
|
+
|
44
|
+
rack_opts += " --port #{config[:port]}" if config[:port]
|
45
|
+
rack_opts += " --pid #{config[:pid]}" if config[:pid]
|
46
|
+
|
47
|
+
yield(config, ruby_opts, rack_opts)
|
48
|
+
}
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
def start config, ruby_opts, rack_opts
|
53
|
+
puts "Starting #{config[:server]} on #{config[:host]}:#{config[:port]}..."
|
54
|
+
sh "rackup#{ruby_opts}#{rack_opts} #{config[:rackup]}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def pid_path path, port
|
58
|
+
RackCluster.include_server_number(path, port)
|
59
|
+
end
|
60
|
+
|
61
|
+
def log_path path, port
|
62
|
+
File.expand_path(RackCluster.include_server_number(path, port))
|
63
|
+
end
|
64
|
+
|
65
|
+
# extracted from thin
|
66
|
+
# Add the server port or number in the filename
|
67
|
+
# so each instance get its own file
|
68
|
+
def include_server_number path, number
|
69
|
+
ext = File.extname(path)
|
70
|
+
path.gsub(/#{ext}$/, ".#{number}#{ext}")
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'daemons'
|
4
|
+
|
5
|
+
require 'etc'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
module RackDaemon
|
9
|
+
module_function
|
10
|
+
def daemonize pid_path, log_path, user, group, chdir
|
11
|
+
Dir.chdir(chdir) if chdir
|
12
|
+
|
13
|
+
user ||= Etc.getpwuid(Process.uid).name
|
14
|
+
group ||= Etc.getpwuid(Process.gid).name
|
15
|
+
|
16
|
+
RackDaemon.change_privilege(user, group)
|
17
|
+
|
18
|
+
cwd = Dir.pwd
|
19
|
+
Daemonize.daemonize(log_path, 'rack-cluster')
|
20
|
+
Dir.chdir(cwd)
|
21
|
+
|
22
|
+
RackDaemon.write_pid(pid_path)
|
23
|
+
|
24
|
+
at_exit{
|
25
|
+
puts "Stopping #{pid_path}..."
|
26
|
+
RackDaemon.remove_pid(pid_path)
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
# extracted from thin
|
31
|
+
# Change privileges of the process
|
32
|
+
# to the specified user and group.
|
33
|
+
def change_privilege user, group
|
34
|
+
|
35
|
+
uid, gid = Process.euid, Process.egid
|
36
|
+
target_uid = Etc.getpwnam(user).uid
|
37
|
+
target_gid = Etc.getgrnam(group).gid
|
38
|
+
|
39
|
+
if uid != target_uid || gid != target_gid
|
40
|
+
puts "Changing process privilege to #{user}:#{group}"
|
41
|
+
|
42
|
+
# Change process ownership
|
43
|
+
Process.initgroups(user, target_gid)
|
44
|
+
Process::GID.change_privilege(target_gid)
|
45
|
+
Process::UID.change_privilege(target_uid)
|
46
|
+
end
|
47
|
+
|
48
|
+
rescue Errno::EPERM => e
|
49
|
+
puts "Couldn't change user and group to #{user}:#{group}: #{e}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def write_pid path
|
53
|
+
FileUtils.mkdir_p(File.dirname(path))
|
54
|
+
File.open(path, 'w'){ |f| f.write(Process.pid) }
|
55
|
+
File.chmod(0644, path)
|
56
|
+
end
|
57
|
+
|
58
|
+
def remove_pid path
|
59
|
+
File.delete(path) if File.exist?(path)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
namespace :app do
|
3
|
+
namespace :thin do
|
4
|
+
|
5
|
+
[:start, :stop, :restart].each{ |name|
|
6
|
+
desc "#{name} the thin cluster"
|
7
|
+
task name, :config do |t, args|
|
8
|
+
sh "thin -C #{args[:config] || 'config/thin.yml'} #{name}"
|
9
|
+
end
|
10
|
+
}
|
11
|
+
|
12
|
+
end # of thin
|
13
|
+
end # of app
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: godfat-app-deploy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "Lin Jen-Shin (a.k.a. godfat \xE7\x9C\x9F\xE5\xB8\xB8)"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-01-13 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: bones
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.2.0
|
23
|
+
version:
|
24
|
+
description: ""
|
25
|
+
email: godfat (XD) godfat.org
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files:
|
31
|
+
- CHANGES
|
32
|
+
- README
|
33
|
+
- TODO
|
34
|
+
- app-deploy.gemspec
|
35
|
+
- example.rake
|
36
|
+
- lib/app-deploy/deploy.rake
|
37
|
+
- lib/app-deploy/gem.rake
|
38
|
+
- lib/app-deploy/git.rake
|
39
|
+
- lib/app-deploy/install.rake
|
40
|
+
- lib/app-deploy/merb.rake
|
41
|
+
- lib/app-deploy/mongrel.rake
|
42
|
+
- lib/app-deploy/nginx.rake
|
43
|
+
- lib/app-deploy/rack.rake
|
44
|
+
- lib/app-deploy/server.rake
|
45
|
+
- lib/app-deploy/thin.rake
|
46
|
+
files:
|
47
|
+
- CHANGES
|
48
|
+
- README
|
49
|
+
- Rakefile
|
50
|
+
- TODO
|
51
|
+
- app-deploy.gemspec
|
52
|
+
- example.rake
|
53
|
+
- lib/app-deploy.rb
|
54
|
+
- lib/app-deploy/deploy.rake
|
55
|
+
- lib/app-deploy/gem.rake
|
56
|
+
- lib/app-deploy/git.rake
|
57
|
+
- lib/app-deploy/install.rake
|
58
|
+
- lib/app-deploy/merb.rake
|
59
|
+
- lib/app-deploy/mongrel.rake
|
60
|
+
- lib/app-deploy/nginx.rake
|
61
|
+
- lib/app-deploy/rack.rake
|
62
|
+
- lib/app-deploy/rack_cluster.rb
|
63
|
+
- lib/app-deploy/rack_daemon.rb
|
64
|
+
- lib/app-deploy/server.rake
|
65
|
+
- lib/app-deploy/thin.rake
|
66
|
+
- lib/app-deploy/version.rb
|
67
|
+
has_rdoc: true
|
68
|
+
homepage: http://github.com/godfat/app-deploy
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options:
|
71
|
+
- --diagram
|
72
|
+
- --charset=utf-8
|
73
|
+
- --inline-source
|
74
|
+
- --line-numbers
|
75
|
+
- --promiscuous
|
76
|
+
- --main
|
77
|
+
- README
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: "0"
|
85
|
+
version:
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: "0"
|
91
|
+
version:
|
92
|
+
requirements: []
|
93
|
+
|
94
|
+
rubyforge_project: ludy
|
95
|
+
rubygems_version: 1.2.0
|
96
|
+
signing_key:
|
97
|
+
specification_version: 2
|
98
|
+
summary: ""
|
99
|
+
test_files: []
|
100
|
+
|