godfat-app-deploy 0.5.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.
data/CHANGES ADDED
@@ -0,0 +1,3 @@
1
+
2
+ 2008-12-10
3
+ bundle as gem
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
@@ -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
@@ -0,0 +1,4 @@
1
+ = app-deploy todo list
2
+
3
+ * escape \" and \' in options?
4
+ * extract rack-cluster
@@ -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
@@ -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
@@ -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,13 @@
1
+
2
+ namespace :app do
3
+ namespace :mongrel do
4
+
5
+ [:start, :stop, :restart].each{ |name|
6
+ desc "#{name} the mongrel cluster"
7
+ task name do
8
+ sh "mongrel_rails cluster::#{name}"
9
+ end
10
+ }
11
+
12
+ end # of mongrel
13
+ 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,9 @@
1
+
2
+ namespace :app do
3
+ namespace :server do
4
+
5
+ desc 'please define your server:restart task'
6
+ task :restart
7
+
8
+ end # of server
9
+ end # of app
@@ -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
@@ -0,0 +1,4 @@
1
+
2
+ module AppDeploy
3
+ VERSION = '0.5.0'
4
+ end
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
+