hell 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -9,6 +9,7 @@ gem 'capistrano'
9
9
  gem 'multi_json'
10
10
 
11
11
  gem 'pusher'
12
+ gem 'pusher-client'
12
13
  gem 'sinatra'
13
14
  gem 'sinatra-contrib'
14
15
  gem 'sinatra-assetpack', :require => 'sinatra/assetpack'
@@ -69,20 +69,6 @@ The following environment variables are available for your use:
69
69
  - `HELL_BASE_DIR`: Base directory to use in web ui. Useful for subdirectories. Defaults to `/`.
70
70
  - `HELL_SENTINEL_STRINGS`: Sentinel string used to denote the end of a task run. Defaults to `Hellish Task Completed`.
71
71
 
72
- ## TODO
73
-
74
- * ~~Finish the execute task so that it sends output to the browser~~
75
- * ~~Figure out where/how to store deploy logs on disk~~
76
- * ~~Blacklist tasks from being displayed~~
77
- * ~~Add support for environment variables~~
78
- * ~~Add support for deployment environments~~
79
- * ~~Add support for ad-hoc deploy callbacks~~
80
- * Save favorite commands as buttons
81
- * Save defaults in a cookie
82
- * Use a slide-up element for task output
83
- * Add optional task locking so that deploys cannot interfere with one-another
84
- * Add ability to use pusher instead of sinatra streaming
85
-
86
72
  ## License
87
73
 
88
74
  Copyright (c) 2012 Jose Diaz-Gonzalez
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
data/bin/hell CHANGED
@@ -6,7 +6,7 @@ require 'hell/lib/cli'
6
6
  ENV["RACK_ENV"] ||= "development"
7
7
 
8
8
  unicorn_path = File.expand_path('../../unicorn', __FILE__)
9
- options, op = Hell::CLI.unicorn_options(ARGV, unicorn_path)
9
+ options, op = Hell::CLI.unicorn_option_parser(ARGV, unicorn_path)
10
10
 
11
11
  unless File.directory? options[:log_path]
12
12
  abort('Missing hell log path %s' % options[:log_path])
@@ -6,15 +6,22 @@ require 'hell/lib/helpers'
6
6
  TASK_ID = ENV.fetch('HELL_TASK_ID', nil)
7
7
  HELL_LOG_PATH = ENV.fetch('HELL_LOG_PATH', File.join(Dir.pwd, 'log'))
8
8
  HELL_SENTINEL_STRINGS = ENV.fetch('HELL_SENTINEL_STRINGS', 'Hellish Task Completed').split(',')
9
+ HELL_PUSHER_APP_ID = ENV.fetch('HELL_PUSHER_APP_ID', nil)
10
+ HELL_PUSHER_KEY = ENV.fetch('HELL_PUSHER_KEY', nil)
11
+ HELL_PUSHER_SECRET = ENV.fetch('HELL_PUSHER_SECRET', nil)
12
+
9
13
  abort('Missing hell task id') unless TASK_ID
14
+ abort('Missing pusher app id') unless HELL_PUSHER_APP_ID
15
+ abort('Missing pusher app key') unless HELL_PUSHER_KEY
16
+ abort('Missing pusher app secret') unless HELL_PUSHER_SECRET
17
+
18
+ Pusher.app_id = HELL_PUSHER_APP_ID
19
+ Pusher.key = HELL_PUSHER_KEY
20
+ Pusher.secret = HELL_PUSHER_SECRET
10
21
 
11
22
  unless Hell::Helpers.valid_log(TASK_ID)
12
23
  Hell::Helpers::pusher_error(TASK_ID, "log file '#{TASK_ID}' not found")
13
24
  abort("log file '#{TASK_ID}' not found")
14
25
  end
15
26
 
16
- Pusher.app_id = ENV.fetch('HELL_PUSHER_APP_ID', nil)
17
- Pusher.key = ENV.fetch('HELL_PUSHER_KEY', nil)
18
- Pusher.secret = ENV.fetch('HELL_PUSHER_SECRET', nil)
19
-
20
27
  Hell::Helpers::pusher_success(TASK_ID, "tail -n 1000 -f %s" % File.join(HELL_LOG_PATH, TASK_ID + ".log"))
@@ -0,0 +1,65 @@
1
+ #!/this/will/be/overwritten/or/wrapped/anyways/do/not/worry/ruby
2
+ # -*- encoding: binary -*-
3
+ require 'multi_json'
4
+ require 'optparse'
5
+ require 'rest_client'
6
+ require 'pusher-client'
7
+
8
+ require 'hell/lib/cli'
9
+
10
+ options, op = Hell::CLI.runner_option_parser(ARGV)
11
+
12
+ abort("Base hell url required, specify it using the -b flag") unless options[:base_url]
13
+ abort("Task name required, specify it using the -t flag") unless options[:task]
14
+
15
+ USE_PUSHER = !!(options[:pusher_app_id] && options[:pusher_key] && options[:pusher_secret])
16
+
17
+ # Create the command
18
+ command = []
19
+ command << options[:environment] unless options[:environment].nil?
20
+ command << options[:task] unless options[:task].nil?
21
+ command = command.join('+')
22
+
23
+ # Construct a url
24
+ url = options[:base_url] + '/tasks/' + command + '/background'
25
+
26
+ begin
27
+ response = RestClient.put(url, {:verbose => options[:verbose] ? "on" : "off"})
28
+ rescue Exception => e
29
+ abort("Error retrieving response: %s" % e)
30
+ end
31
+
32
+ abort("Invalid response from server") unless response.code == 200
33
+
34
+ body = MultiJson.load(response.body)
35
+ task_id = body["task_id"]
36
+
37
+ puts options
38
+
39
+ if USE_PUSHER
40
+ PusherClient.logger = Logger.new('/dev/null')
41
+ socket = PusherClient::Socket.new(options[:pusher_key], {
42
+ :secret => options[:pusher_secret]
43
+ })
44
+
45
+ socket.subscribe(task_id)
46
+
47
+ socket[task_id].bind('start') do |data|
48
+ PusherClient.logger.debug "Received the first response for " + command
49
+ end
50
+
51
+ socket[task_id].bind('message') do |data|
52
+ data = MultiJson.load(data)
53
+ puts data['message'].gsub(/~+$/, '')
54
+ end
55
+
56
+ socket[task_id].bind('end') do |data|
57
+ PusherClient.logger.debug "Received the last response " + command
58
+ socket.unsubscribe(task_id)
59
+ socket.disconnect
60
+ end
61
+
62
+ socket.connect
63
+ else
64
+ abort("EventSource not implemented yet")
65
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "hell"
8
- s.version = "0.1.1"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jose Diaz-Gonzalez"]
12
- s.date = "2013-02-21"
12
+ s.date = "2013-03-11"
13
13
  s.description = "Hell is an open source web interface that exposes a set of capistrano recipes as a json api, for usage within large teams"
14
14
  s.email = "jose@seatgeek.com"
15
15
  s.executables = ["hell", "hell-pusher"]
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
26
26
  "VERSION",
27
27
  "bin/hell",
28
28
  "bin/hell-pusher",
29
+ "bin/hell-runner",
29
30
  "config.ru",
30
31
  "hell.gemspec",
31
32
  "lib/hell.rb",
@@ -73,6 +74,7 @@ Gem::Specification.new do |s|
73
74
  s.add_runtime_dependency(%q<capistrano>, [">= 0"])
74
75
  s.add_runtime_dependency(%q<multi_json>, [">= 0"])
75
76
  s.add_runtime_dependency(%q<pusher>, [">= 0"])
77
+ s.add_runtime_dependency(%q<pusher-client>, [">= 0"])
76
78
  s.add_runtime_dependency(%q<sinatra>, [">= 0"])
77
79
  s.add_runtime_dependency(%q<sinatra-contrib>, [">= 0"])
78
80
  s.add_runtime_dependency(%q<sinatra-assetpack>, [">= 0"])
@@ -84,6 +86,7 @@ Gem::Specification.new do |s|
84
86
  s.add_dependency(%q<capistrano>, [">= 0"])
85
87
  s.add_dependency(%q<multi_json>, [">= 0"])
86
88
  s.add_dependency(%q<pusher>, [">= 0"])
89
+ s.add_dependency(%q<pusher-client>, [">= 0"])
87
90
  s.add_dependency(%q<sinatra>, [">= 0"])
88
91
  s.add_dependency(%q<sinatra-contrib>, [">= 0"])
89
92
  s.add_dependency(%q<sinatra-assetpack>, [">= 0"])
@@ -96,6 +99,7 @@ Gem::Specification.new do |s|
96
99
  s.add_dependency(%q<capistrano>, [">= 0"])
97
100
  s.add_dependency(%q<multi_json>, [">= 0"])
98
101
  s.add_dependency(%q<pusher>, [">= 0"])
102
+ s.add_dependency(%q<pusher-client>, [">= 0"])
99
103
  s.add_dependency(%q<sinatra>, [">= 0"])
100
104
  s.add_dependency(%q<sinatra-contrib>, [">= 0"])
101
105
  s.add_dependency(%q<sinatra-assetpack>, [">= 0"])
@@ -115,8 +115,8 @@ module Hell
115
115
  tail_in_background!(task_id) if USE_PUSHER
116
116
 
117
117
  response = {}
118
- response[:status] = tasks.empty? ? 404 : 200,
119
- response[:message] = tasks.empty? ? "Task not found" : "Running task in background",
118
+ response[:status] = tasks.empty? ? 404 : 200
119
+ response[:message] = tasks.empty? ? "Task not found" : "Running task in background"
120
120
  response[:task_id] = task_id unless tasks.empty?
121
121
  json response
122
122
  end
@@ -174,6 +174,5 @@ module Hell
174
174
  close_stream(out)
175
175
  end
176
176
  end
177
-
178
177
  end
179
178
  end
@@ -25,153 +25,246 @@ module Hell
25
25
  options
26
26
  end
27
27
 
28
- def self.unicorn_options(args, unicorn_path=nil)
29
- options, op = Hell::CLI.option_parser(args, unicorn_path)
28
+ def self.generic_options(options, opts)
29
+ cmd = File.basename($0)
30
+ opts.banner = "Usage: #{cmd} " \
31
+ "[ruby options] [#{cmd} options] [rackup config file]"
32
+ opts.separator "Ruby options:"
33
+
34
+ lineno = 1
35
+ opts.on("-e", "--eval LINE", "evaluate a LINE of code") do |line|
36
+ eval line, TOPLEVEL_BINDING, "-e", lineno
37
+ lineno += 1
38
+ end
30
39
 
31
- [
32
- :app_root,
33
- :base_path,
34
- :require_env,
35
- :sentinel,
36
- :pusher_app_id,
37
- :pusher_key,
38
- :pusher_secret,
39
- ].each {|key| options.delete(key)}
40
+ opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") do
41
+ $DEBUG = true
42
+ end
40
43
 
41
- [options, op]
44
+ opts.on("-w", "--warn", "turn warnings on for your script") do
45
+ $-w = true
46
+ end
47
+
48
+ opts.on("-I", "--include PATH",
49
+ "specify $LOAD_PATH (may be used more than once)") do |path|
50
+ $LOAD_PATH.unshift(*path.split(/:/))
51
+ end
52
+
53
+ opts.on("-r", "--require LIBRARY",
54
+ "require the library, before executing your script") do |library|
55
+ require library
56
+ end
57
+
58
+ [options, opts]
42
59
  end
43
60
 
44
- def self.option_parser(args, unicorn_path=nil)
45
- options = Hell::CLI.default_options(unicorn_path)
61
+ def self.runner_options(options, opts)
62
+ opts.separator "Runner options"
46
63
 
47
- op = OptionParser.new("", 24, ' ') do |opts|
48
- cmd = File.basename($0)
49
- opts.banner = "Usage: #{cmd} " \
50
- "[ruby options] [#{cmd} options] [rackup config file]"
51
- opts.separator "Ruby options:"
52
-
53
- lineno = 1
54
- opts.on("-e", "--eval LINE", "evaluate a LINE of code") do |line|
55
- eval line, TOPLEVEL_BINDING, "-e", lineno
56
- lineno += 1
57
- end
64
+ opts.on("--base-url BASE_URL", "base hell url") do |base_url|
65
+ options[:base_url] = base_url.gsub(/[\/]+$/, '') if base_url
66
+ end
58
67
 
59
- opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") do
60
- $DEBUG = true
61
- end
68
+ opts.on("--environment ENVIRONMENT", "environment to run task in") do |environment|
69
+ options[:environment] = environment if environment
70
+ end
62
71
 
63
- opts.on("-w", "--warn", "turn warnings on for your script") do
64
- $-w = true
65
- end
72
+ opts.on("--task TASK", "full task name to run") do |task|
73
+ options[:task] = task if task
74
+ end
66
75
 
67
- opts.on("-I", "--include PATH",
68
- "specify $LOAD_PATH (may be used more than once)") do |path|
69
- $LOAD_PATH.unshift(*path.split(/:/))
70
- end
76
+ opts.on("--verbose", "run task in verbose mode") do |environment|
77
+ options[:verbose] = true if verbose
78
+ end
71
79
 
72
- opts.on("-r", "--require LIBRARY",
73
- "require the library, before executing your script") do |library|
74
- require library
75
- end
80
+ [options, opts]
81
+ end
76
82
 
77
- opts.separator "Unicorn options:"
83
+ def self.server_options(options, opts)
84
+ # some of these switches exist for rackup command-line compatibility,
85
+ opts.separator "Server options"
78
86
 
79
- # some of these switches exist for rackup command-line compatibility,
87
+ opts.on("-o", "--host HOST",
88
+ "listen on HOST (default: 0.0.0.0)") do |h|
89
+ rackup_opts[:host] = h || '0.0.0.0'
90
+ rackup_opts[:set_listener] = true
91
+ end
80
92
 
81
- opts.on("-o", "--host HOST",
82
- "listen on HOST (default: 0.0.0.0)") do |h|
83
- rackup_opts[:host] = h || '0.0.0.0'
84
- rackup_opts[:set_listener] = true
85
- end
93
+ opts.on("-p", "--port PORT",
94
+ "use PORT (default: 4567)") do |p|
95
+ rackup_opts[:port] = p || 4567
96
+ rackup_opts[:port] = rackup_opts[:port].to_i
97
+ rackup_opts[:set_listener] = true
98
+ end
86
99
 
87
- opts.on("-p", "--port PORT",
88
- "use PORT (default: 4567)") do |p|
89
- rackup_opts[:port] = p || 4567
90
- rackup_opts[:port] = rackup_opts[:port].to_i
91
- rackup_opts[:set_listener] = true
92
- end
100
+ opts.on("-E", "--env RACK_ENV",
101
+ "use RACK_ENV for defaults (default: development)") do |e|
102
+ ENV["RACK_ENV"] = e
103
+ end
93
104
 
94
- opts.on("-E", "--env RACK_ENV",
95
- "use RACK_ENV for defaults (default: development)") do |e|
96
- ENV["RACK_ENV"] = e
97
- end
105
+ opts.on("-D", "--daemonize", "run daemonized in the background") do |d|
106
+ rackup_opts[:daemonize] = !!d
107
+ end
98
108
 
99
- opts.on("-D", "--daemonize", "run daemonized in the background") do |d|
100
- rackup_opts[:daemonize] = !!d
101
- end
109
+ opts.on("-P", "--pid FILE", "DEPRECATED") do |f|
110
+ warn %q{Use of --pid/-P is strongly discouraged}
111
+ warn %q{Use the 'pid' directive in the Unicorn config file instead}
112
+ options[:pid] = f
113
+ end
102
114
 
103
- opts.on("-P", "--pid FILE", "DEPRECATED") do |f|
104
- warn %q{Use of --pid/-P is strongly discouraged}
105
- warn %q{Use the 'pid' directive in the Unicorn config file instead}
106
- options[:pid] = f
107
- end
115
+ opts.on("-s", "--server SERVER",
116
+ "this flag only exists for compatibility") do |s|
117
+ warn "-s/--server only exists for compatibility with rackup"
118
+ end
108
119
 
109
- opts.on("-s", "--server SERVER",
110
- "this flag only exists for compatibility") do |s|
111
- warn "-s/--server only exists for compatibility with rackup"
112
- end
120
+ [options, opts]
121
+ end
113
122
 
114
- # Unicorn-specific stuff
115
- opts.on("-l", "--listen {HOST:PORT|PATH}",
116
- "listen on HOST:PORT or PATH",
117
- "this may be specified multiple times",
118
- "(default: 0.0.0.0:4567)") do |address|
119
- options[:listeners] << address || '0.0.0.0:4567'
120
- end
123
+ def self.unicorn_options(options, opts)
124
+ # Unicorn-specific stuff
125
+ opts.separator "Unicorn options:"
121
126
 
122
- opts.on("-c", "--config-file FILE", "Unicorn-specific config file") do |f|
123
- options[:config_file] = unicorn_path
124
- end
127
+ opts.on("-l", "--listen {HOST:PORT|PATH}",
128
+ "listen on HOST:PORT or PATH",
129
+ "this may be specified multiple times",
130
+ "(default: 0.0.0.0:4567)") do |address|
131
+ options[:listeners] << address || '0.0.0.0:4567'
132
+ end
125
133
 
126
- # I'm avoiding Unicorn-specific config options on the command-line.
127
- # IMNSHO, config options on the command-line are redundant given
128
- # config files and make things unnecessarily complicated with multiple
129
- # places to look for a config option.
134
+ opts.on("-c", "--config-file FILE", "Unicorn-specific config file") do |f|
135
+ options[:config_file] = unicorn_path
136
+ end
137
+
138
+ [options, opts]
139
+ end
130
140
 
131
- opts.separator "Common options"
132
- opts.separator "Note: will not work under unicorn, use environment variables instead"
141
+ def self.common_options(options, opts)
142
+ opts.separator "Common options"
133
143
 
134
- opts.on_tail("-h", "--help", "Show this message") do
135
- puts opts.to_s.gsub(/^.*DEPRECATED.*$/s, '')
136
- exit
137
- end
144
+ opts.on_tail("-h", "--help", "Show this message") do
145
+ puts opts.to_s.gsub(/^.*DEPRECATED.*$/s, '')
146
+ exit
147
+ end
138
148
 
139
- opts.on_tail("-v", "--version", "Show version") do
140
- puts "#{cmd} v#{Unicorn::Const::UNICORN_VERSION}"
141
- exit
142
- end
149
+ opts.on_tail("-v", "--version", "Show version") do
150
+ puts "#{cmd} v#{Unicorn::Const::UNICORN_VERSION}"
151
+ exit
152
+ end
143
153
 
144
- opts.on('-a', '--app-root APP_ROOT', 'directory from which capistrano should run') do |app_root|
145
- options[:app_root] = app_root if app_root
154
+ opts.on('-a', '--app-root APP_ROOT', 'directory from which capistrano should run') do |app_root|
155
+ if app_root
156
+ options[:app_root] = app_root
157
+ ENV['HELL_APP_ROOT'] = app_root
146
158
  end
159
+ end
147
160
 
148
- opts.on('-b', '--base-path BASE_PATH', 'base directory path to use in the web ui') do |base_path|
149
- options[:base_path] = base_path if base_path
161
+ opts.on('-b', '--base-path BASE_PATH', 'base directory path to use in the web ui') do |base_path|
162
+ if base_path
163
+ options[:base_path] = base_path
164
+ ENV['HELL_BASE_PATH'] = base_path
150
165
  end
166
+ end
151
167
 
152
- opts.on('-L', '--log-path LOG_PATH', 'directory path to hell logs') do |log_path|
153
- options[:log_path] = log_path if log_path
168
+ opts.on('-L', '--log-path LOG_PATH', 'directory path to hell logs') do |log_path|
169
+ if log_path
170
+ options[:log_path] = log_path
171
+ ENV['HELL_LOG_PATH'] = log_path
154
172
  end
173
+ end
155
174
 
156
- opts.on('-R', '--require-env REQUIRE_ENV', 'whether or not to require specifying an environment') do |require_env|
157
- options[:require_env] = !!require_env if require_env
175
+ opts.on('-R', '--require-env REQUIRE_ENV', 'whether or not to require specifying an environment') do |require_env|
176
+ if require_env
177
+ options[:require_env] = !!require_env
178
+ ENV['HELL_REQUIRE_ENV'] = !!require_env
158
179
  end
180
+ end
159
181
 
160
- opts.on('-S', '--sentinel SENTINAL_PHRASE', 'sentinel phrase used to denote the end of a task run') do |sentinel|
161
- options[:sentinel] = sentinel.split(',') if sentinel
182
+ opts.on('-S', '--sentinel SENTINAL_PHRASE', 'sentinel phrase used to denote the end of a task run') do |sentinel|
183
+ if sentinel
184
+ options[:sentinel] = sentinel.split(',')
185
+ ENV['HELL_SENTINEL_STRINGS'] = sentinel.split(',')
162
186
  end
187
+ end
163
188
 
164
- opts.on('--pusher-app-id PUSHER_APP_ID', 'pusher app id') do |pusher_app_id|
165
- options[:pusher_app_id] = pusher_app_id if pusher_app_id
189
+ opts.on('--pusher-app-id PUSHER_APP_ID', 'pusher app id') do |pusher_app_id|
190
+ if pusher_app_id
191
+ options[:pusher_app_id] = pusher_app_id
192
+ ENV['HELL_PUSHER_APP_ID'] = pusher_app_id
166
193
  end
194
+ end
167
195
 
168
- opts.on('--pusher-key PUSHER_KEY', 'pusher key') do |pusher_key|
169
- options[:pusher_key] = pusher_key if pusher_key
196
+ opts.on('--pusher-key PUSHER_KEY', 'pusher key') do |pusher_key|
197
+ if pusher_key
198
+ options[:pusher_key] = pusher_key
199
+ ENV['HELL_PUSHER_KEY'] = pusher_key
170
200
  end
201
+ end
171
202
 
172
- opts.on('--pusher-secret PUSHER_SECRET', 'pusher secret') do |pusher_secret|
173
- options[:pusher_secret] = pusher_secret if pusher_secret
203
+ opts.on('--pusher-secret PUSHER_SECRET', 'pusher secret') do |pusher_secret|
204
+ if pusher_secret
205
+ options[:pusher_secret] = pusher_secret
206
+ ENV['HELL_PUSHER_SECRET'] = pusher_secret
174
207
  end
208
+ end
209
+
210
+ [options, opts]
211
+ end
212
+
213
+ def self.runner_option_parser(args)
214
+ options = options = {
215
+ :environment => nil,
216
+ :task => nil,
217
+ :verbose => false,
218
+ :pusher_app_id => ENV.fetch('HELL_PUSHER_APP_ID', nil),
219
+ :pusher_key => ENV.fetch('HELL_PUSHER_KEY', nil),
220
+ :pusher_secret => ENV.fetch('HELL_PUSHER_SECRET', nil),
221
+ }
222
+
223
+ op = OptionParser.new("", 24, ' ') do |opts|
224
+ options, opts = Hell::CLI.generic_options(options, opts)
225
+
226
+ options, opts = Hell::CLI.runner_options(options, opts)
227
+
228
+ options, opts = Hell::CLI.common_options(options, opts)
229
+
230
+ opts.parse! args
231
+ end
232
+
233
+ [options, op]
234
+ end
235
+
236
+ def self.unicorn_option_parser(args, unicorn_path=nil)
237
+ options, op = Hell::CLI.option_parser(args, unicorn_path)
238
+
239
+ [
240
+ :app_root,
241
+ :base_path,
242
+ :require_env,
243
+ :sentinel,
244
+ :pusher_app_id,
245
+ :pusher_key,
246
+ :pusher_secret,
247
+ ].each {|key| options.delete(key)}
248
+
249
+ [options, op]
250
+ end
251
+
252
+ def self.option_parser(args, unicorn_path=nil)
253
+ options = Hell::CLI.default_options(unicorn_path)
254
+
255
+ op = OptionParser.new("", 24, ' ') do |opts|
256
+ options, opts = Hell::CLI.generic_options(options, opts)
257
+
258
+ options, opts = Hell::CLI.server_options(options, opts)
259
+
260
+ options, opts = Hell::CLI.unicorn_options(options, opts)
261
+
262
+ # I'm avoiding Unicorn-specific config options on the command-line.
263
+ # IMNSHO, config options on the command-line are redundant given
264
+ # config files and make things unnecessarily complicated with multiple
265
+ # places to look for a config option.
266
+
267
+ options, opts = Hell::CLI.common_options(options, opts)
175
268
 
176
269
  opts.parse! args
177
270
  end
@@ -81,10 +81,11 @@ module Hell
81
81
 
82
82
  def run_in_background!(background_cmd)
83
83
  log_file = random_id
84
+ task_end = HELL_SENTINEL_STRINGS.first
84
85
  cmd = [
85
86
  "cd #{HELL_APP_ROOT} && echo '#{background_cmd}' >> #{HELL_LOG_PATH}/#{log_file}.log 2>&1",
86
87
  "cd #{HELL_APP_ROOT} && #{background_cmd} >> #{HELL_LOG_PATH}/#{log_file}.log 2>&1",
87
- "cd #{HELL_APP_ROOT} && echo 'Hellish Task Completed' >> #{HELL_LOG_PATH}/#{log_file}.log 2>&1",
88
+ "cd #{HELL_APP_ROOT} && echo '#{task_end}' >> #{HELL_LOG_PATH}/#{log_file}.log 2>&1",
88
89
  ].join(" ; ")
89
90
  system("sh -c \"#{cmd}\" &")
90
91
 
@@ -100,7 +101,7 @@ module Hell
100
101
  end
101
102
 
102
103
  def tail_in_background!(task_id)
103
- cmd = "cd #{HELL_LOG_PATH} && HELL_TASK_ID='#{task_id}' HELL_SENTINEL_STRINGS='#{HELL_SENTINEL_STRINGS.join(',')}' HELL_LOG_PATH='#{HELL_LOG_PATH}' bundle exec hell-pusher"
104
+ cmd = "cd #{HELL_LOG_PATH} && HELL_TASK_ID='#{task_id}' HELL_SENTINEL_STRINGS='#{HELL_SENTINEL_STRINGS.join(',')}' bundle exec hell-pusher"
104
105
  system("sh -c \"#{cmd}\" &")
105
106
  end
106
107
 
@@ -2151,7 +2151,7 @@ table th[class*="span"],
2151
2151
  *margin-right: .3em;
2152
2152
  line-height: 14px;
2153
2153
  vertical-align: text-top;
2154
- background-image: url("../img/glyphicons-halflings.png");
2154
+ background-image: url("./../img/glyphicons-halflings.png");
2155
2155
  background-position: 14px 14px;
2156
2156
  background-repeat: no-repeat;
2157
2157
  }
@@ -2171,7 +2171,7 @@ table th[class*="span"],
2171
2171
  .dropdown-menu > .active > a > [class*=" icon-"],
2172
2172
  .dropdown-submenu:hover > a > [class^="icon-"],
2173
2173
  .dropdown-submenu:hover > a > [class*=" icon-"] {
2174
- background-image: url("../img/glyphicons-halflings-white.png");
2174
+ background-image: url("./../img/glyphicons-halflings-white.png");
2175
2175
  }
2176
2176
 
2177
2177
  .icon-glass {
@@ -167,7 +167,7 @@ $(function() {
167
167
  _executeEventsource: function(task_id) {
168
168
  var that = this;
169
169
 
170
- // Create new websocket
170
+ // Create new EventSource
171
171
  var src = new EventSource(HellApp.www_base_dir + 'logs/' + task_id + '/tail');
172
172
 
173
173
  // Received the first response
@@ -176,7 +176,7 @@ $(function() {
176
176
  that.setStatus("started");
177
177
  });
178
178
 
179
- // Close the websocket when there are no more events
179
+ // Close the EventSource when there are no more events
180
180
  src.addEventListener('end', function () {
181
181
  HellApp.set_flash("Received the last response " + name, "info");
182
182
  that.setStatus("finished");
@@ -194,7 +194,7 @@ $(function() {
194
194
  view: function() {
195
195
  HellApp.set_flash("Viewing a past task", "info");
196
196
 
197
- // Close all websockets
197
+ // Close all EventSource
198
198
  HellApp.close_sockets(src);
199
199
  HellApp.toggle_overlay();
200
200
  window.location.hash = "#run";
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-21 00:00:00.000000000 Z
12
+ date: 2013-03-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: capistrano
@@ -59,6 +59,22 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: pusher-client
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
62
78
  - !ruby/object:Gem::Dependency
63
79
  name: sinatra
64
80
  requirement: !ruby/object:Gem::Requirement
@@ -190,6 +206,7 @@ files:
190
206
  - VERSION
191
207
  - bin/hell
192
208
  - bin/hell-pusher
209
+ - bin/hell-runner
193
210
  - config.ru
194
211
  - hell.gemspec
195
212
  - lib/hell.rb
@@ -238,7 +255,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
238
255
  version: '0'
239
256
  segments:
240
257
  - 0
241
- hash: -2842994347166960270
258
+ hash: -2087860351003938988
242
259
  required_rubygems_version: !ruby/object:Gem::Requirement
243
260
  none: false
244
261
  requirements: