deployml 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.document +3 -0
  2. data/.rspec +1 -0
  3. data/.yardopts +1 -0
  4. data/ChangeLog.md +22 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +107 -0
  7. data/Rakefile +35 -0
  8. data/bin/deployml +5 -0
  9. data/deployml.gemspec +10 -0
  10. data/gemspec.yml +21 -0
  11. data/lib/deployml/cli.rb +192 -0
  12. data/lib/deployml/configuration.rb +149 -0
  13. data/lib/deployml/environment.rb +273 -0
  14. data/lib/deployml/exceptions/config_not_found.rb +4 -0
  15. data/lib/deployml/exceptions/invalid_config.rb +4 -0
  16. data/lib/deployml/exceptions/missing_option.rb +6 -0
  17. data/lib/deployml/exceptions/unknown_environment.rb +4 -0
  18. data/lib/deployml/exceptions/unknown_framework.rb +6 -0
  19. data/lib/deployml/exceptions/unknown_server.rb +6 -0
  20. data/lib/deployml/frameworks/rails2.rb +9 -0
  21. data/lib/deployml/frameworks/rails3.rb +20 -0
  22. data/lib/deployml/frameworks.rb +2 -0
  23. data/lib/deployml/local_shell.rb +54 -0
  24. data/lib/deployml/options/mongrel.rb +46 -0
  25. data/lib/deployml/options/thin.rb +72 -0
  26. data/lib/deployml/options.rb +1 -0
  27. data/lib/deployml/project.rb +304 -0
  28. data/lib/deployml/remote_shell.rb +130 -0
  29. data/lib/deployml/servers/apache.rb +19 -0
  30. data/lib/deployml/servers/mongrel.rb +41 -0
  31. data/lib/deployml/servers/thin.rb +41 -0
  32. data/lib/deployml/servers.rb +3 -0
  33. data/lib/deployml/shell.rb +46 -0
  34. data/lib/deployml/version.rb +4 -0
  35. data/lib/deployml.rb +2 -0
  36. data/spec/configuration_spec.rb +73 -0
  37. data/spec/deployml_spec.rb +11 -0
  38. data/spec/environment_spec.rb +34 -0
  39. data/spec/helpers/projects/bad_config/config/deploy.yml +1 -0
  40. data/spec/helpers/projects/basic/config/deploy.yml +3 -0
  41. data/spec/helpers/projects/invalid_server/config/deploy.yml +4 -0
  42. data/spec/helpers/projects/missing_config/.gitkeep +0 -0
  43. data/spec/helpers/projects/missing_dest/config/deploy.yml +2 -0
  44. data/spec/helpers/projects/missing_source/config/deploy.yml +2 -0
  45. data/spec/helpers/projects/rails/config/deploy/production.yml +10 -0
  46. data/spec/helpers/projects/rails/config/deploy/staging.yml +10 -0
  47. data/spec/helpers/projects/rails/config/deploy.yml +3 -0
  48. data/spec/helpers/projects.rb +11 -0
  49. data/spec/project_spec.rb +66 -0
  50. data/spec/spec_helper.rb +8 -0
  51. metadata +207 -0
@@ -0,0 +1,273 @@
1
+ require 'deployml/exceptions/missing_option'
2
+ require 'deployml/exceptions/unknown_server'
3
+ require 'deployml/exceptions/unknown_framework'
4
+ require 'deployml/configuration'
5
+ require 'deployml/local_shell'
6
+ require 'deployml/remote_shell'
7
+ require 'deployml/servers'
8
+ require 'deployml/frameworks'
9
+
10
+ module DeploYML
11
+ class Environment < Configuration
12
+
13
+ # Mapping of possible 'server' names to their mixins.
14
+ SERVERS = {
15
+ :apache => Servers::Apache,
16
+ :mongrel => Servers::Mongrel,
17
+ :thin => Servers::Thin
18
+ }
19
+
20
+ # Mapping of possible 'framework' names to their mixins.
21
+ FRAMEWORKS = {
22
+ :rails2 => Frameworks::Rails2,
23
+ :rails3 => Frameworks::Rails3
24
+ }
25
+
26
+ #
27
+ # Creates a new deployment environment.
28
+ #
29
+ # @param [Symbol, String] name
30
+ # The name of the deployment environment.
31
+ #
32
+ # @param [Hash{String => Object}] config
33
+ # Environment specific configuration.
34
+ #
35
+ # @raise [MissingOption]
36
+ # Either the `source` or `dest` options were not specified in the
37
+ # confirmation.
38
+ #
39
+ # @since 0.3.0
40
+ #
41
+ def initialize(name,config={})
42
+ super(config)
43
+
44
+ unless @source
45
+ raise(MissingOption,":source option is missing for the #{@name} environment")
46
+ end
47
+
48
+ unless @dest
49
+ raise(MissingOption,":dest option is missing for the #{@name} environment")
50
+ end
51
+
52
+ @environment ||= name.to_sym
53
+
54
+ load_framework!
55
+ load_server!
56
+ end
57
+
58
+ #
59
+ # Creates a local shell.
60
+ #
61
+ # @yield [shell]
62
+ # If a block is given, it will be passed the new local shell.
63
+ #
64
+ # @yieldparam [LocalShell] shell
65
+ # The remote shell session.
66
+ #
67
+ # @return [LocalShell]
68
+ # The local shell.
69
+ #
70
+ # @since 0.3.0
71
+ #
72
+ def local_shell(&block)
73
+ LocalShell.new(&block)
74
+ end
75
+
76
+ #
77
+ # Creates a remote shell with the destination server.
78
+ #
79
+ # @yield [shell]
80
+ # If a block is given, it will be passed the new remote shell.
81
+ #
82
+ # @yieldparam [RemoteShell] shell
83
+ # The remote shell.
84
+ #
85
+ # @return [RemoteShell]
86
+ # The remote shell.
87
+ #
88
+ # @since 0.3.0
89
+ #
90
+ def remote_shell(&block)
91
+ RemoteShell.new(@dest,&block)
92
+ end
93
+
94
+ #
95
+ # Runs a command on the destination server, in the destination
96
+ # directory.
97
+ #
98
+ # @return [true]
99
+ #
100
+ # @since 0.3.0
101
+ #
102
+ def exec(command)
103
+ remote_shell do |shell|
104
+ shell.cd(@dest.path)
105
+ shell.run(command)
106
+ end
107
+
108
+ return true
109
+ end
110
+
111
+ #
112
+ # Executes a Rake task on the destination server, in the destination
113
+ # directory.
114
+ #
115
+ # @return [true]
116
+ #
117
+ # @since 0.3.0
118
+ #
119
+ def rake(task,*args)
120
+ remote_shell do |shell|
121
+ shell.cd(@dest.path)
122
+ shell.rake(task,*args)
123
+ end
124
+
125
+ return true
126
+ end
127
+
128
+ #
129
+ # Starts an SSH session with the destination server.
130
+ #
131
+ # @param [Array] args
132
+ # Additional arguments to pass to SSH.
133
+ #
134
+ # @return [true]
135
+ #
136
+ # @since 0.3.0
137
+ #
138
+ def ssh(*args)
139
+ RemoteShell.new(@dest).ssh(*args)
140
+ return true
141
+ end
142
+
143
+ #
144
+ # Sets up the deployment repository for the project.
145
+ #
146
+ # @param [RemoteShell] shell
147
+ # The remote shell to execute commands through.
148
+ #
149
+ # @since 0.3.0
150
+ #
151
+ def setup(shell)
152
+ shell.run 'git', 'clone', '--depth', 1, @source, @dest.path
153
+ end
154
+
155
+ #
156
+ # Updates the deployed repository for the project.
157
+ #
158
+ # @param [RemoteShell] shell
159
+ # The remote shell to execute commands through.
160
+ #
161
+ # @since 0.3.0
162
+ #
163
+ def update(shell)
164
+ shell.run 'git', 'reset', '--hard', 'HEAD'
165
+ shell.run 'git', 'pull'
166
+ end
167
+
168
+ #
169
+ # Place-holder method.
170
+ #
171
+ # @param [RemoteShell] shell
172
+ # The remote shell to execute commands through.
173
+ #
174
+ # @since 0.3.0
175
+ #
176
+ def install(shell)
177
+ end
178
+
179
+ #
180
+ # Place-holder method.
181
+ #
182
+ # @param [RemoteShell] shell
183
+ # The remote shell to execute commands through.
184
+ #
185
+ # @since 0.3.0
186
+ #
187
+ def migrate(shell)
188
+ end
189
+
190
+ #
191
+ # Place-holder method.
192
+ #
193
+ # @param [RemoteShell] shell
194
+ # The remote shell to execute commands through.
195
+ #
196
+ # @since 0.3.0
197
+ #
198
+ def server_config(shell)
199
+ end
200
+
201
+ #
202
+ # Place-holder method.
203
+ #
204
+ # @param [RemoteShell] shell
205
+ # The remote shell to execute commands through.
206
+ #
207
+ # @since 0.3.0
208
+ #
209
+ def server_start(shell)
210
+ end
211
+
212
+ #
213
+ # Place-holder method.
214
+ #
215
+ # @param [RemoteShell] shell
216
+ # The remote shell to execute commands through.
217
+ #
218
+ # @since 0.3.0
219
+ #
220
+ def server_stop(shell)
221
+ end
222
+
223
+ #
224
+ # Place-holder method.
225
+ #
226
+ # @param [RemoteShell] shell
227
+ # The remote shell to execute commands through.
228
+ #
229
+ # @since 0.3.0
230
+ #
231
+ def server_restart(shell)
232
+ end
233
+
234
+ protected
235
+
236
+ #
237
+ # Loads the framework configuration.
238
+ #
239
+ # @since 0.3.0
240
+ #
241
+ def load_framework!
242
+ if @orm
243
+ unless FRAMEWORKS.has_key?(@framework)
244
+ raise(UnknownFramework,"Unknown framework #{@framework}")
245
+ end
246
+
247
+ extend FRAMEWORKS[@framework]
248
+
249
+ initialize_framework() if self.respond_to?(:initialize_framework)
250
+ end
251
+ end
252
+
253
+ #
254
+ # Loads the server configuration.
255
+ #
256
+ # @raise [UnknownServer]
257
+ #
258
+ # @since 0.3.0
259
+ #
260
+ def load_server!
261
+ if @server_name
262
+ unless SERVERS.has_key?(@server_name)
263
+ raise(UnknownServer,"Unknown server name #{@server_name}")
264
+ end
265
+
266
+ extend SERVERS[@server_name]
267
+
268
+ initialize_server() if self.respond_to?(:initialize_server)
269
+ end
270
+ end
271
+
272
+ end
273
+ end
@@ -0,0 +1,4 @@
1
+ module DeploYML
2
+ class ConfigNotFound < RuntimeError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module DeploYML
2
+ class InvalidConfig < RuntimeError
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ require 'deployml/exceptions/invalid_config'
2
+
3
+ module DeploYML
4
+ class MissingOption < InvalidConfig
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ module DeploYML
2
+ class UnknownEnvironment < RuntimeError
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ require 'deployml/exceptions/invalid_config'
2
+
3
+ module DeploYML
4
+ class UnknownFramework < InvalidConfig
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'deployml/exceptions/invalid_config'
2
+
3
+ module DeploYML
4
+ class UnknownServer < InvalidConfig
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ module DeploYML
2
+ module Frameworks
3
+ module Rails2
4
+ def migrate(shell)
5
+ shell.run 'rake', 'db:migrate', "RAILS_ENV=#{@environment}"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,20 @@
1
+ module DeploYML
2
+ module Frameworks
3
+ module Rails3
4
+ def install(shell)
5
+ shell.run 'bundle', 'install', '--deployment'
6
+ end
7
+
8
+ def migrate(shell)
9
+ task = case @orm
10
+ when :datamapper
11
+ 'db:autoupgrade'
12
+ else
13
+ 'db:migrate'
14
+ end
15
+
16
+ shell.run 'rake', task, "RAILS_ENV=#{@environment}"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,2 @@
1
+ require 'deployml/frameworks/rails2'
2
+ require 'deployml/frameworks/rails3'
@@ -0,0 +1,54 @@
1
+ require 'deployml/shell'
2
+
3
+ module DeploYML
4
+ class LocalShell
5
+
6
+ include Shell
7
+
8
+ #
9
+ # Runs a program locally.
10
+ #
11
+ # @param [String] program
12
+ # The name or path of the program to run.
13
+ #
14
+ # @param [Array<String>] args
15
+ # Additional arguments for the program.
16
+ #
17
+ def run(program,*args)
18
+ system(program,*args)
19
+ end
20
+
21
+ #
22
+ # Prints out a message.
23
+ #
24
+ # @param [String] message
25
+ # The message to print.
26
+ #
27
+ def echo(message)
28
+ puts message
29
+ end
30
+
31
+ #
32
+ # Changes the current working directory.
33
+ #
34
+ # @param [String] path
35
+ # The path of the new current working directory to use.
36
+ #
37
+ # @yield []
38
+ # If a block is given, then the directory will be changed back after
39
+ # the block has returned.
40
+ #
41
+ def cd(path,&block)
42
+ if block
43
+ cwd = Dir.pwd
44
+
45
+ Dir.chdir(path)
46
+ block.call()
47
+ Dir.chdir(cwd)
48
+ else
49
+ Dir.chdir(path)
50
+ end
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,46 @@
1
+ require 'rprogram/task'
2
+
3
+ module DeploYML
4
+ module Options
5
+ class Mongrel < RProgram::Task
6
+
7
+ DEFAULTS = {
8
+ :environment => :production,
9
+ :address => '127.0.0.1',
10
+ :num_servers => 2
11
+ }
12
+
13
+ long_option :flag => '--environment'
14
+ long_option :flag => '--port'
15
+ long_option :flag => '--address'
16
+ long_option :flag => '--log'
17
+ long_option :flag => '--pid'
18
+ long_option :flag => '--chdir'
19
+ long_option :flag => '--timeout'
20
+ long_option :flag => '--throttle'
21
+ long_option :flag => '--mime'
22
+ long_option :flag => '--root'
23
+ long_option :flag => '--num-procs'
24
+ long_option :flag => '--debug'
25
+ long_option :flag => '--script'
26
+ long_option :flag => '--num-servers'
27
+ long_option :flag => '--config'
28
+ long_option :flag => '--user'
29
+ long_option :flag => '--group'
30
+ long_option :flag => '--prefix'
31
+ long_option :flag => '--help'
32
+ long_option :flag => '--version'
33
+
34
+ #
35
+ # Initialize the Mongrel options.
36
+ #
37
+ # @param [Hash] options
38
+ # The given options.
39
+ #
40
+ def initialize(options={})
41
+ super(DEFAULTS.merge(options))
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,72 @@
1
+ require 'rprogram/task'
2
+
3
+ module DeploYML
4
+ module Options
5
+ class Thin < RProgram::Task
6
+
7
+ # Default options for Thin
8
+ DEFAULTS = {
9
+ :environment => :production,
10
+ :address => '127.0.0.1',
11
+ :servers => 2
12
+ }
13
+
14
+ # Server options:
15
+ long_option :flag => '--address'
16
+ long_option :flag => '--port'
17
+ long_option :flag => '--socket'
18
+ long_option :flag => '--swiftiply'
19
+ long_option :flag => '--adapter'
20
+ long_option :flag => '--rackup'
21
+ long_option :flag => '--chdir'
22
+ long_option :flag => '--stats'
23
+
24
+ # Adapter options:
25
+ long_option :flag => '--environment'
26
+ long_option :flag => '--prefix'
27
+
28
+ # Daemon options:
29
+ long_option :flag => '--daemonize'
30
+ long_option :flag => '--log'
31
+ long_option :flag => '--pid'
32
+ long_option :flag => '--user'
33
+ long_option :flag => '--group'
34
+ long_option :flag => '--tag'
35
+
36
+ # Cluster options:
37
+ long_option :flag => '--servers'
38
+ long_option :flag => '--only'
39
+ long_option :flag => '--config'
40
+ long_option :flag => '--all'
41
+ long_option :flag => '--onebyone', :name => :one_by_one
42
+ long_option :flag => '--wait'
43
+
44
+ # Tuning options:
45
+ long_option :flag => '--backend'
46
+ long_option :flag => '--timeout'
47
+ long_option :flag => '--force'
48
+ long_option :flag => '--max-conns', :name => :max_connections
49
+ long_option :flag => '--max-persistent-conns', :name => :max_persistant_connections
50
+ long_option :flag => '--threaded'
51
+ long_option :flag => '--no-epoll'
52
+
53
+ # Common options:
54
+ long_option :flag => '--require'
55
+ long_option :flag => '--debug'
56
+ long_option :flag => '--trace'
57
+ long_option :flag => '--help'
58
+ long_option :flag => '--version'
59
+
60
+ #
61
+ # Initialize the Thin options.
62
+ #
63
+ # @param [Hash] options
64
+ # The given options.
65
+ #
66
+ def initialize(options={})
67
+ super(DEFAULTS.merge(options))
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1 @@
1
+ require 'deployml/options/thin'