sunraise 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+