sunraise 0.1.1
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/README.md +0 -0
- data/bin/sunraise +26 -0
- data/lib/config.rb +97 -0
- data/lib/deployer.rb +197 -0
- data/sunraise.example +12 -0
- data/sunraise.gemspec +26 -0
- metadata +80 -0
data/README.md
ADDED
File without changes
|
data/bin/sunraise
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rainbow'
|
5
|
+
|
6
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'config')
|
7
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'deployer')
|
8
|
+
|
9
|
+
include SunRaise::PubConf
|
10
|
+
|
11
|
+
|
12
|
+
if File.expand_path(__FILE__) == File.expand_path(File.join(Dir.pwd, 'sunraise'))
|
13
|
+
puts "Run it from you app folder, containing sunraise file with deploy instructions"
|
14
|
+
exit
|
15
|
+
end
|
16
|
+
|
17
|
+
unless File.file?(File.join Dir.pwd, 'sunraise')
|
18
|
+
puts "No sunraise file found at #{Dir.pwd}"
|
19
|
+
exit
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
at_exit { SunRaise::Deployer.new.go! }
|
24
|
+
|
25
|
+
|
26
|
+
load File.join Dir.pwd, 'sunraise'
|
data/lib/config.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
module SunRaise
|
5
|
+
# configurator class
|
6
|
+
class Config
|
7
|
+
|
8
|
+
include Singleton
|
9
|
+
attr_accessor :conf, :callbacks
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_accessor :config_methods
|
13
|
+
end
|
14
|
+
|
15
|
+
@config_methods = [
|
16
|
+
:remote_host,
|
17
|
+
:remote_user,
|
18
|
+
:deploy_to,
|
19
|
+
:then_link_to,
|
20
|
+
:git_url,
|
21
|
+
:shared_dirs,
|
22
|
+
:linked_dirs,
|
23
|
+
:local_project_path,
|
24
|
+
:verbose,
|
25
|
+
:force,
|
26
|
+
:release,
|
27
|
+
:remake,
|
28
|
+
:test_rails_app,
|
29
|
+
:auto_migrate,
|
30
|
+
:help,
|
31
|
+
:destroy
|
32
|
+
]
|
33
|
+
|
34
|
+
@config_methods.each do |method_name|
|
35
|
+
define_method method_name do |value|
|
36
|
+
value.strip! if value.class == String
|
37
|
+
@conf[method_name] = value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
@callbacks = {:after => ''}
|
43
|
+
@conf = {
|
44
|
+
:verbose => false,
|
45
|
+
:local_project_path => '.',
|
46
|
+
:release => true,
|
47
|
+
:test_rails_app => true,
|
48
|
+
:auto_migrate => true,
|
49
|
+
:help => false
|
50
|
+
}
|
51
|
+
|
52
|
+
cl_options
|
53
|
+
end
|
54
|
+
|
55
|
+
def cl_options
|
56
|
+
OptionParser.new do |opts|
|
57
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |verbose|
|
58
|
+
@conf[:verbose] = verbose
|
59
|
+
end
|
60
|
+
|
61
|
+
opts.on("-f", "--[no-]force", "Deploy even there are no new commits") do |force|
|
62
|
+
@conf[:force] = force
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on("-n", "--no-reelase", "Do not replace 'current' dir and start test server") do |no_release|
|
66
|
+
@conf[:release] = !no_release
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.on("--remake", "Delete current deploy and make initial deploy") do |remake|
|
70
|
+
@conf[:remake] = remake
|
71
|
+
end
|
72
|
+
|
73
|
+
opts.on("-d", "--destroy", "Delete current deploy and make initial deploy") do |destroy|
|
74
|
+
@conf[:destroy] = destroy
|
75
|
+
end
|
76
|
+
|
77
|
+
opts.on("-h", "--help", "Show this help") do |help|
|
78
|
+
@conf[:help] = true
|
79
|
+
puts opts
|
80
|
+
end
|
81
|
+
end.parse!
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
module PubConf
|
87
|
+
SunRaise::Config.config_methods.each do |method_name|
|
88
|
+
define_method method_name do |value|
|
89
|
+
SunRaise::Config.instance.send method_name, value
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def after_deploy &block
|
94
|
+
SunRaise::Config.instance.callbacks[:after] = block
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/deployer.rb
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
begin
|
2
|
+
require 'rubygems'
|
3
|
+
gem 'net-ssh', ">= 2.0.10"
|
4
|
+
rescue LoadError, NameError
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'net/ssh'
|
8
|
+
|
9
|
+
module SunRaise
|
10
|
+
# working horse
|
11
|
+
class Deployer
|
12
|
+
|
13
|
+
def go!
|
14
|
+
return if conf[:help]
|
15
|
+
return destroy_existen! if conf[:destroy]
|
16
|
+
if !conf[:remake] && initiated?
|
17
|
+
update
|
18
|
+
else
|
19
|
+
init_deploy
|
20
|
+
end
|
21
|
+
|
22
|
+
callbacks :after
|
23
|
+
|
24
|
+
puts "SSH OUT: \n" + @ssh_out.join("\n") if conf[:verbose]
|
25
|
+
end
|
26
|
+
|
27
|
+
def init_deploy
|
28
|
+
destroy_existen! if conf[:remake]
|
29
|
+
log_ok "initial deploy.."
|
30
|
+
ssh_exec [
|
31
|
+
"mkdir -p #{deploy_path}",
|
32
|
+
"cd #{deploy_path}",
|
33
|
+
"mkdir -p log shared tmp",
|
34
|
+
"git clone #{conf[:git_url]} current"
|
35
|
+
]
|
36
|
+
log_ok "Created dir and cloned repo"
|
37
|
+
|
38
|
+
test_rails_app! 'current' if conf[:test_rails_app]
|
39
|
+
auto_migrate! 'current' if conf[:auto_migrate]
|
40
|
+
|
41
|
+
log_ok "Made new dirs and cloned repo"
|
42
|
+
make_links 'current'
|
43
|
+
end
|
44
|
+
|
45
|
+
def update
|
46
|
+
|
47
|
+
last_commit = ssh_exec ["cd #{current_path}", "git log -1 --pretty=format:\"%H\""]
|
48
|
+
last_repo_commit = (`cd #{conf[:local_project_path]} && git ls-remote #{conf[:git_url]}`).split("\t").first
|
49
|
+
|
50
|
+
if !conf[:force] && last_commit.strip == last_repo_commit.strip
|
51
|
+
log_ok "Nothing to update"
|
52
|
+
return
|
53
|
+
end
|
54
|
+
|
55
|
+
new_commits = (`cd #{conf[:local_project_path]} && git log #{last_commit}..HEAD --pretty=format:"%s"`).split("\n")
|
56
|
+
|
57
|
+
log_ok "New commits: \n #{new_commits.join "\n "}"
|
58
|
+
@new_dir = "pre_release"
|
59
|
+
|
60
|
+
ssh_exec [
|
61
|
+
"cd #{deploy_path}",
|
62
|
+
"rm #{@new_dir} .git_temp previous2 current2 -rf", # if previous deploy was crashed
|
63
|
+
"mv current/.git .git_temp", # moving repo dir
|
64
|
+
"cp current #{@new_dir}", # clone sitedir without .git
|
65
|
+
"mv .git_temp #{@new_dir}/.git", # move git in pre_release folder
|
66
|
+
"cd #{@new_dir}",
|
67
|
+
"git pull origin master"
|
68
|
+
]
|
69
|
+
log_ok "Forked, git updated"
|
70
|
+
|
71
|
+
make_links @new_dir
|
72
|
+
|
73
|
+
test_rails_app! @new_dir if conf[:test_rails_app]
|
74
|
+
auto_migrate! @new_dir if conf[:auto_migrate]
|
75
|
+
|
76
|
+
release! if conf[:release]
|
77
|
+
end
|
78
|
+
|
79
|
+
def release!
|
80
|
+
ssh_exec [
|
81
|
+
"cd #{deploy_path}", # folder magic :) old current => previous, pre_release => current
|
82
|
+
"mv current current2",
|
83
|
+
"mv #{@new_dir} current",
|
84
|
+
"if [ -d previous ]; then mv previous previous2 -f; fi",
|
85
|
+
"mv current2 previous"
|
86
|
+
]
|
87
|
+
log_ok "Released!"
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
def ssh_exec command
|
92
|
+
command = command.join " && " if command.is_a? Array
|
93
|
+
puts ">>>>".color(:cyan) + " #{command}" if conf[:verbose]
|
94
|
+
@ssh_ist ||= Net::SSH.start conf[:remote_host], conf[:remote_user]
|
95
|
+
@ssh_out ||= []
|
96
|
+
@ssh_out << @ssh_ist.exec!(command)
|
97
|
+
@ssh_out.last
|
98
|
+
end
|
99
|
+
|
100
|
+
def make_links dist_dir
|
101
|
+
links = []
|
102
|
+
conf[:shared_dirs].each do |dir|
|
103
|
+
links << "rm #{dir} -rf"
|
104
|
+
links << "mkdir ../shared/#{dir} -p"
|
105
|
+
links << "ln -s ../shared/#{dir} #{dir}"
|
106
|
+
end
|
107
|
+
|
108
|
+
conf[:linked_dirs].each do |dir|
|
109
|
+
links << "rm #{dir} -rf"
|
110
|
+
links << "mkdir ../#{dir} -p"
|
111
|
+
links << "ln -s ../#{dir} #{dir}"
|
112
|
+
end
|
113
|
+
|
114
|
+
ssh_exec ["cd #{File.join deploy_path, dist_dir}"] + links
|
115
|
+
@ssh_out.each {|m| puts m}
|
116
|
+
log_ok "Made links"
|
117
|
+
end
|
118
|
+
|
119
|
+
def initiated?
|
120
|
+
ssh_exec "cd #{current_path}"
|
121
|
+
last_msg = @ssh_out.pop
|
122
|
+
!(last_msg && last_msg =~ /No such file or directory/)
|
123
|
+
end
|
124
|
+
|
125
|
+
def destroy_existen!
|
126
|
+
log_ok "Removing existen deploy dir"
|
127
|
+
ssh_exec "rm #{deploy_path} -rf"
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_rails_app! dir
|
131
|
+
@app_about ||= rails_app_about dir
|
132
|
+
if !@app_about.index('Application root')
|
133
|
+
if !@app_about.index('Database schema version')
|
134
|
+
log_error "Rails app test fail"
|
135
|
+
else
|
136
|
+
log_error "Rails app test: Database didn't configurated"
|
137
|
+
end
|
138
|
+
puts @app_about
|
139
|
+
log_error "Deploy aborted, use " + "ssh #{conf[:remote_user]}@#{conf[:remote_host]}".italic + " to fix it"
|
140
|
+
exit
|
141
|
+
else
|
142
|
+
log_ok "Rails app successfully tested"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def auto_migrate! dir
|
147
|
+
@app_about ||= rails_app_about dir
|
148
|
+
matches = @app_about.match(/Database schema version\s+ ([0-9]+)/)
|
149
|
+
remote_magration_version = matches && matches.size > 0 && matches[1] || 0
|
150
|
+
local_about = `#{File.join conf[:local_project_path], 'script', 'about'}`
|
151
|
+
local_migration_version = local_about.match(/Database schema version\s+ ([0-9]+)/)[1]
|
152
|
+
if remote_magration_version == local_migration_version
|
153
|
+
msg_ok "No new migrations"
|
154
|
+
else
|
155
|
+
log_ok "Rinning rake db:migrate"
|
156
|
+
puts ssh_exec ["cd #{File.join deploy_path, dir}", "rake db:migrate RAILS_ENV=production"] # run migrations
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def rails_app_about dir
|
161
|
+
ssh_exec "RAILS_ENV=production " + File.join(deploy_path, dir, 'script', 'about') # run script/about
|
162
|
+
end
|
163
|
+
|
164
|
+
def conf
|
165
|
+
SunRaise::Config.instance.conf
|
166
|
+
end
|
167
|
+
|
168
|
+
def callbacks name
|
169
|
+
c = SunRaise::Config.instance.callbacks
|
170
|
+
|
171
|
+
if c[name].class == Proc
|
172
|
+
instance_eval &c[name]
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def current_path
|
177
|
+
File.join conf[:deploy_to], 'current'
|
178
|
+
end
|
179
|
+
|
180
|
+
def deploy_path
|
181
|
+
conf[:deploy_to]
|
182
|
+
end
|
183
|
+
|
184
|
+
def app_path
|
185
|
+
File.join deploy_path, (conf[:release] ? 'current' : 'pre_release' )
|
186
|
+
end
|
187
|
+
|
188
|
+
def log_ok msg
|
189
|
+
puts ":: ".color(:green) + "#{msg}".bright
|
190
|
+
end
|
191
|
+
|
192
|
+
def log_error msg
|
193
|
+
puts "!! ".bright.color(:red) + "#{msg}".bright
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
end
|
data/sunraise.example
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
remote_host 'twews.com'
|
2
|
+
remote_user 'root'
|
3
|
+
|
4
|
+
git_url 'git://github.com/Paxa/sunraise_test_app.git'
|
5
|
+
|
6
|
+
deploy_to '/tmp/deploy/suntest'
|
7
|
+
then_link_to '/tmp/www/suntest'
|
8
|
+
|
9
|
+
shared_dirs ['lib']
|
10
|
+
linked_dirs ['logs', 'tmp']
|
11
|
+
|
12
|
+
local_project_path "/home/paxa/Dropbox/sunraise/test/suntest"
|
data/sunraise.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "sunraise"
|
3
|
+
s.version = "0.1.1"
|
4
|
+
s.summary = "Super-fast and simple rails deployment."
|
5
|
+
s.description = "Super-fast and simple rails deployment"
|
6
|
+
s.author = "Pavel Evstigneev"
|
7
|
+
s.email = "pavel.evst@gmail.com"
|
8
|
+
s.homepage = "http://github.com/Paxa/sunraise"
|
9
|
+
s.has_rdoc = false
|
10
|
+
s.executables = ["sunraise"]
|
11
|
+
s.rubyforge_project = "sunraise"
|
12
|
+
s.files = [ "bin/sunraise", "lib/config.rb", "lib/deployer.rb", "README.md", "sunraise.gemspec", 'sunraise.example']
|
13
|
+
|
14
|
+
if s.respond_to? :specification_version then
|
15
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
16
|
+
s.specification_version = 3
|
17
|
+
|
18
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
19
|
+
s.add_development_dependency(%q<rainbow>, [">= 1.0.4"])
|
20
|
+
else
|
21
|
+
s.add_dependency(%q<rainbow>, [">= 1.0.4"])
|
22
|
+
end
|
23
|
+
else
|
24
|
+
s.add_dependency(%q<rainbow>, [">= 1.0.4"])
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sunraise
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 1
|
9
|
+
version: 0.1.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Pavel Evstigneev
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-03-09 00:00:00 +03:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rainbow
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 0
|
30
|
+
- 4
|
31
|
+
version: 1.0.4
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
description: Super-fast and simple rails deployment
|
35
|
+
email: pavel.evst@gmail.com
|
36
|
+
executables:
|
37
|
+
- sunraise
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files: []
|
41
|
+
|
42
|
+
files:
|
43
|
+
- bin/sunraise
|
44
|
+
- lib/config.rb
|
45
|
+
- lib/deployer.rb
|
46
|
+
- README.md
|
47
|
+
- sunraise.gemspec
|
48
|
+
- sunraise.example
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: http://github.com/Paxa/sunraise
|
51
|
+
licenses: []
|
52
|
+
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
requirements: []
|
73
|
+
|
74
|
+
rubyforge_project: sunraise
|
75
|
+
rubygems_version: 1.3.6
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: Super-fast and simple rails deployment.
|
79
|
+
test_files: []
|
80
|
+
|