deployml 0.3.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.
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'