Compare commits

...
89 Commits
Author SHA1 Message Date
David Dollar a87a882e60 0.47.0 2012-06-07 22:49:51 -04:00
David Dollar 6ba9252d0f Merge pull request #165 from elf-pavlik/master
list of ports to other languages added to README
2012-06-07 19:45:11 -07:00
David Dollar efd9e2119b Merge pull request #173 from Viximo/feature/escape-env
Quote and escape environment variables in upstart templates
2012-06-07 19:43:20 -07:00
David Dollar bf9bdbf118 Merge pull request #194 from maxpow4h/master
Added launchd to exporters
2012-06-07 19:41:23 -07:00
David Dollar 929a138e54 Merge pull request #195 from aneeth/patch-1
Updated data/export/bluepill/master.pill.erb
2012-06-07 19:41:09 -07:00
David Dollar d6514b4f33 Merge pull request #201 from sos4nt/patch-1
Terminate gracefully upon SIGHUP
2012-06-07 19:40:38 -07:00
David Dollar 8696a36833 Merge pull request #208 from dbrock/master
Fix multi-word argument handling in `foreman run`.
2012-06-06 07:48:44 -07:00
Daniel Brockman 3ea5de42aa Fix multi-word argument handling in foreman run. 2012-06-06 15:36:59 +02:00
David Dollar 4a13122082 Merge pull request #199 from atog/master
set port from .env if specified
2012-05-16 15:06:56 -07:00
Koen Van der Auwera 9b2987c3f0 make 'PORT=5000 foreman start' work 2012-05-16 23:59:09 +02:00
Stefan Schüßler 6274f99225 Terminate gracefully upon SIGHUP
Tmux sends SIGHUP when a session is killed which can result in orphaned processes. Adding a SIGHUP handler terminates the processes as expected.
2012-05-14 13:04:46 +03:00
Koen Van der Auwera 0b0324fed9 set port from .env if specified 2012-05-11 14:17:03 +02:00
Aneeth 32db70b778 Updated data/export/bluepill/master.pill.erb to read in the environment variables from the foreman .env file and reflect it in the pill file 2012-05-04 15:53:16 +08:00
Maxwell Swadling 3db1ad6fbc Added launchd exporter 2012-05-04 15:21:16 +10:00
David Dollar 003b466a17 Merge pull request #193 from pat2man/patch-1
Add stop_grace_time to bluepill config
2012-05-03 12:16:23 -07:00
Patrick Tescher 2a896a0fb5 Add stop_grace_time to bluepill config. Fixes this error message:
Config Error: Stop_grace_time should be greater than the sum of stop_signals delays!

Changed bluepill spec example files to include stop_grace_time
2012-05-03 12:11:24 -07:00
David Dollar 6a8c81a38b Revert "Merge pull request #192 from pat2man/patch-1"
This reverts commit a83dab363e, reversing
changes made to e0fe5baf1b.
2012-05-03 14:53:31 -04:00
David Dollar a83dab363e Merge pull request #192 from pat2man/patch-1
Add stop_grace_time to bluepill config
2012-05-03 11:52:02 -07:00
Patrick Tescher 53e0f4ecf9 Add stop_grace_time to bluepill config. Fixes this error message:
Config Error: Stop_grace_time should be greater than the sum of stop_signals delays!
2012-05-03 11:50:29 -07:00
David Dollar e0fe5baf1b update docs 2012-05-02 13:21:02 -04:00
David Dollar 1aa1f15b8f update changelog 2012-05-02 13:20:54 -04:00
David Dollar fa46a605bb 0.46.0 2012-05-02 13:19:11 -04:00
David Dollar 3077857ab7 Merge pull request #191 from ged/profile_load_write_append
Add Procfile load/write/append API
2012-05-02 10:03:31 -07:00
David Dollar 08aa8f9d5d Merge pull request #190 from ged/remove_obsolete_spec
Remove spec obsoleted by 91a8704
2012-05-02 10:01:30 -07:00
Michael Granger 771489dec9 Remove spec obsoleted by 91a8704 2012-05-02 09:37:32 -07:00
Michael Granger 053ae8f0be Add Profile load/write/append API 2012-05-02 09:30:57 -07:00
David Dollar af58af1c60 Merge pull request #187 from bkaney/master
Guard against missing Procfile in engine.rb
2012-04-29 21:00:58 -07:00
David Dollar 9075d93370 update docs 2012-04-26 17:50:03 -04:00
David Dollar 0c2e9df722 changelog 2012-04-26 17:50:00 -04:00
David Dollar 047f1ff5c4 0.45.0 2012-04-26 17:49:35 -04:00
David Dollar 26b54a62c5 Merge pull request #188 from technomancy/upstart-log-dir
Create and chown log dir in upstart export.
2012-04-24 17:50:42 -07:00
Phil Hagelberg 7b85ad7c1a Create and chown log dir in upstart export. 2012-04-24 17:24:53 -07:00
Brian Kaney 91a87049db Guard against missing Procfile in engine.rb
Should be able to 'foreman run <task>' without a Procfile.  This seems true to the orig. intent as the cli does not directly check with 'run' (as it  does for 'start').
2012-04-24 15:51:14 -04:00
David Dollar f46408e8be remove parka from dist files 2012-04-23 16:00:27 -04:00
David Dollar 93f04e42ac update docs 2012-04-23 15:57:06 -04:00
David Dollar 97c4582acc changelog 2012-04-23 15:57:00 -04:00
David Dollar 5689d75a87 0.44.0 2012-04-23 15:55:56 -04:00
David Dollar 1325b6750e make var output order repeatable 2012-04-23 15:53:59 -04:00
David Dollar 638005403f clean up file/directory interaction, add some tests 2012-04-23 15:50:23 -04:00
David Dollar 55f274532f Merge pull request #183 from technomancy/app_root
Look for .env and app_root in the same dir as the Procfile.
2012-04-23 12:20:10 -07:00
Phil Hagelberg 66f76c2036 Look for .env and app_root in the same dir as the Procfile. 2012-04-20 20:59:37 -07:00
David Dollar 865cabb525 update docs 2012-04-20 19:33:14 -04:00
David Dollar 7c3c4bc58f add more options to the start docs 2012-04-20 19:33:11 -04:00
David Dollar 2dbe8c733b update docs 2012-04-20 17:42:47 -04:00
David Dollar 84352b82cc changelog 2012-04-20 17:42:33 -04:00
David Dollar 383c1f87af 0.43.0 2012-04-20 17:41:08 -04:00
David Dollar ce3003b026 factor out wrap_environment 2012-04-20 17:40:53 -04:00
David Dollar e06f4b2f9e Merge pull request #182 from leahpar/master
Supervisord Export fix for environments containing commas
2012-04-20 14:36:26 -07:00
Raphael Randschau b721fd894e per default wrap every environment value in quotes 2012-04-20 21:15:43 +02:00
Raphael Randschau b8ea6fd4b3 fix typo in spec description 2012-04-20 09:14:12 +02:00
Raphael Randschau dbda63263b fix supervisord export for environments containing commas 2012-04-20 09:11:25 +02:00
David Dollar 93cdc31be0 update docs 2012-04-18 13:04:45 -04:00
David Dollar 4dfbe46690 update changelog 2012-04-18 13:03:58 -04:00
David Dollar 0033f9caeb 0.42.0 2012-04-18 13:02:51 -04:00
David Dollar 74839800a9 Merge pull request #181 from technomancy/master
Public read_environment
2012-04-18 10:01:38 -07:00
Phil Hagelberg b75337e21e Move read_environment to a public class method. 2012-04-18 09:56:17 -07:00
David Dollar d94f941189 update gemfile.lock 2012-04-18 12:49:33 -04:00
David Dollar 0b34f067cb Revert "Merge pull request #176 from rtyler/feature/156-foreman-stop-command"
Rewriting using a better Process API

This reverts commit dbe51832b0, reversing
changes made to 69216b4c5e.
2012-04-18 12:48:51 -04:00
David Dollar dbe51832b0 Merge pull request #176 from rtyler/feature/156-foreman-stop-command
Adding #stop method to Foreman::Engine
2012-04-11 10:29:54 -07:00
R. Tyler Croy 3a2a53be95 Remove ALL_PROCESSES and default the name arguments to #start/#stop to nil 2012-04-11 10:25:58 -07:00
R. Tyler Croy b2bf95479e Refactor #stop to reference ALL_PROCESSES for a bit clearer readability 2012-04-10 20:35:59 -07:00
R. Tyler Croy 48f764e347 Refactor #spawn_processes into #start(name)
When passed nil (aka ALL_PROCESSES) #start will start all processes in the
Procfile as per existing behavior
2012-04-10 20:35:59 -07:00
R. Tyler Croy de62d0655e Re-name the main Foreman::Engine method to #run to avoid a name collision with #start(name) 2012-04-10 20:35:59 -07:00
R. Tyler Croy 38aecff886 When executing #stop(nil), all processes should be sent the signal 2012-04-10 20:35:58 -07:00
R. Tyler Croy e4a3215257 Re-implement #terminate_gracefully with #stop(name) 2012-04-10 20:19:23 -07:00
R. Tyler Croy c705b5fbef Add #stop method on Foreman::Engine for stopping certain named processes
This will make embedding foreman "nicer" since the embedder can then stop
a specific process (e.g. turning off a service for an integration fail-over test)
2012-04-10 20:10:51 -07:00
Matt Griffin 2fcb64959b Quote and escape environment variables in upstart templates 2012-04-03 16:36:18 -04:00
David Dollar 69216b4c5e Merge pull request #171 from technomancy/0.41.0-deparkaed
Drop parka dependency to make things easier on the build slaves.
2012-03-26 15:05:35 -07:00
Phil Hagelberg 5d2930745a Drop parka dependency to make things easier on the build slaves. 2012-03-26 15:01:04 -07:00
elf Pavlik a5465bf55e added list of ports to other languages to README 2012-03-18 09:35:51 +01:00
David Dollar 8fc3d1ef24 Merge pull request #161 from leahpar/master
Supervisord Support (Update & Bugfix)
2012-03-16 18:47:15 -07:00
David Dollar d33e4fb0ed update changelog 2012-03-16 16:36:16 -04:00
David Dollar 39b48b566f 0.41.0 2012-03-16 16:34:32 -04:00
David Dollar 2f982ff9c7 replace term-ansicolor with built-in colorization 2012-03-16 16:34:14 -04:00
Raphael Randschau 1217ef1b56 fix typo 2012-03-05 15:51:10 +01:00
Raphael Randschau c9943d70ec add group support for supervisord 2012-03-05 15:48:40 +01:00
Raphael Randschau 08dca57eb4 fix enviroment export 2012-02-25 17:24:27 +01:00
David Dollar bb3377407a Merge pull request #160 from leahpar/master
supervisord support
2012-02-24 11:49:55 -08:00
Raphael Randschau 084b9493d1 revert bundle update 2012-02-24 20:31:07 +01:00
Raphael Randschau 279a251c78 fix whitespaces 2012-02-24 20:29:16 +01:00
Raphael Randschau a49ef286e8 all specs are passing 2012-02-24 20:18:38 +01:00
Raphael Randschau 0b3da59947 passing first export 2012-02-24 19:52:18 +01:00
David Dollar 1f725dd68a let github show authors 2012-02-24 11:34:34 -05:00
David Dollar 2272f76479 authors 2012-02-24 11:33:33 -05:00
David Dollar cf4762071c changelog 2012-02-24 11:33:18 -05:00
Raphael Randschau 1127551369 rename supervisord base template to app
add supervisord stub
2012-02-23 17:24:08 +01:00
Raphael Randschau 8cb58b8517 require supervisord export 2012-02-23 17:11:19 +01:00
Raphael Randschau d03e931b67 add supervisord export engine 2012-02-23 17:10:57 +01:00
Raphael Randschau 9ba2b32b36 add supervisord base template 2012-02-23 17:02:59 +01:00
45 changed files with 692 additions and 93 deletions
+39
View File
@@ -1,3 +1,42 @@
## 0.46.0 (2012-05-02)
* Add Profile load/write/append API [Michael Granger]
* Guard against missing Procfile in engine.rb [Brian Kaney]
## 0.45.0 (2012-04-26)
* create and chown log dir in upstart export. [Phil Hagelberg]
* remove parka from dist files [David Dollar]
## 0.44.0 (2012-04-23)
* make var output order repeatable in supervisord export [David Dollar]
* make --procfile and --app-root influence each other in a more intuitive way [David Dollar]
* Look for .env and app_root in the same dir as the Procfile. [Phil Hagelberg]
## 0.43.0 (2012-04-20)
* wrap supervisord env vars in quotes [Raphael Randschau]
## 0.42.0 (2012-04-18)
* Move read_environment to a public class method. [Phil Hagelberg]
* Drop parka dependency [Phil Hagelberg]
* add group support for supervisord [Raphael Randschau]
* fix enviroment export [Raphael Randschau]
## 0.41.0 (2012-03-16)
* replace term-ansicolor with built-in colorization [David Dollar]
* supervisord export template [Raphael Randschau]
## 0.40.0 (2012-02-24)
* support various quoting styles in .env [David Dollar]
* remove load_env! as it's made unnecessary by foreman run [David Dollar]
* Provide a useful error if `foreman check` fails to find a Procfile [R. Tyler Croy]
* update docs [David Dollar]
## 0.39.0 (2012-02-07) ## 0.39.0 (2012-02-07)
* rename bin/runner to bin/foreman-runner [David Dollar] * rename bin/runner to bin/foreman-runner [David Dollar]
-1
View File
@@ -12,7 +12,6 @@ end
group :development do group :development do
gem 'aws-s3' gem 'aws-s3'
gem 'parka'
gem 'rake' gem 'rake'
gem 'ronn' gem 'ronn'
gem 'fakefs', '~> 0.3.2' gem 'fakefs', '~> 0.3.2'
+1 -11
View File
@@ -1,8 +1,7 @@
PATH PATH
remote: . remote: .
specs: specs:
foreman (0.40.0) foreman (0.47.0)
term-ansicolor (~> 1.0.7)
thor (>= 0.13.6) thor (>= 0.13.6)
GEM GEM
@@ -13,7 +12,6 @@ GEM
mime-types mime-types
xml-simple xml-simple
builder (3.0.0) builder (3.0.0)
crack (0.1.8)
diff-lcs (1.1.3) diff-lcs (1.1.3)
fakefs (0.3.2) fakefs (0.3.2)
hpricot (0.8.6) hpricot (0.8.6)
@@ -21,15 +19,9 @@ GEM
mime-types (1.16) mime-types (1.16)
multi_json (1.0.4) multi_json (1.0.4)
mustache (0.11.2) mustache (0.11.2)
parka (0.6.2)
crack
rest-client
thor
posix-spawn (0.3.6) posix-spawn (0.3.6)
rake (0.9.2.2) rake (0.9.2.2)
rdiscount (1.6.5) rdiscount (1.6.5)
rest-client (1.6.1)
mime-types (>= 1.16)
ronn (0.7.3) ronn (0.7.3)
hpricot (>= 0.8.2) hpricot (>= 0.8.2)
mustache (>= 0.7.0) mustache (>= 0.7.0)
@@ -47,7 +39,6 @@ GEM
multi_json (~> 1.0.3) multi_json (~> 1.0.3)
simplecov-html (~> 0.5.3) simplecov-html (~> 0.5.3)
simplecov-html (0.5.3) simplecov-html (0.5.3)
term-ansicolor (1.0.7)
thor (0.14.6) thor (0.14.6)
win32console (1.3.0-x86-mingw32) win32console (1.3.0-x86-mingw32)
xml-simple (1.0.15) xml-simple (1.0.15)
@@ -61,7 +52,6 @@ DEPENDENCIES
aws-s3 aws-s3
fakefs (~> 0.3.2) fakefs (~> 0.3.2)
foreman! foreman!
parka
posix-spawn (~> 0.3.6) posix-spawn (~> 0.3.6)
rake rake
ronn ronn
+7 -1
View File
@@ -27,13 +27,19 @@ Manage Procfile-based applications
* [wiki](http://github.com/ddollar/foreman/wiki) * [wiki](http://github.com/ddollar/foreman/wiki)
* [changelog](https://github.com/ddollar/foreman/blob/master/Changelog.md) * [changelog](https://github.com/ddollar/foreman/blob/master/Changelog.md)
## Ports
* [shoreman](https://github.com/hecticjeff/shoreman) - shell
* [honcho](https://github.com/nickstenning/honcho) - python
* [norman](https://github.com/josh/norman) - node.js
## Authors ## Authors
#### Created and maintained by #### Created and maintained by
David Dollar David Dollar
#### Patches contributed by #### Patches contributed by
Adam Wiggins, Chris Continanza, Chris Lowder, Craig R Webster, Dan Farina, Dan Peterson, David Dollar, Fletcher Nichol, Florian Apolloner, Gabriel Burt, Gamaliel Toro, Greg Reinacker, Hugues Le Gendre, Hunter Nield, Iain Hecker, Jay Zeschin, John Firebaugh, Keith Rarick, Khaja Minhajuddin, Lincoln Stoll, Marcos Muino Garcia, Mark McGranaghan, Matt Griffin, Matt Haynes, Matthijs Langenberg, Michael Dwan, Michael van Rooijen, Mike Javorski, Nathan Broadbent, Nathan L Smith, Nick Zadrozny, Phil Hagelberg, Ricardo Chimal, Jr, Thom May, Tom Ward, brainopia, clifff, jc00ke [Contributor List](https://github.com/ddollar/foreman/contributors)
## License ## License
+3 -7
View File
@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# #
#/ Usage: foreman-runner [-d <dir>] <command> #/ Usage: foreman-runner [-d <dir>] <command> [<args>...]
#/ #/
#/ Run a command with exec, optionally changing directory first #/ Run a command with exec, optionally changing directory first
@@ -27,10 +27,6 @@ done
shift $((OPTIND-1)) shift $((OPTIND-1))
command=$1 [ -z "$1" ] && usage
if [ -z "$1" ]; then exec "$@"
usage
fi
exec $1
+2 -1
View File
@@ -11,8 +11,9 @@ Bluepill.application("<%= app %>", :foreground => false, :log_file => "/var/log/
process.working_dir = "<%= engine.directory %>" process.working_dir = "<%= engine.directory %>"
process.daemonize = true process.daemonize = true
process.environment = {"PORT" => "<%= port %>"} process.environment = {"PORT" => "<%= port %>"<% engine.environment.each_pair do |var,env| %> , "<%= var.upcase %>" => "<%= env %>" <% end %>}
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill] process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
process.stop_grace_time = 45.seconds
process.stdout = process.stderr = "<%= log_root %>/<%= app %>-<%= process.name %>-<%=num%>.log" process.stdout = process.stderr = "<%= log_root %>/<%= app %>-<%= process.name %>-<%=num%>.log"
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string><%= "#{app}-#{process.name}-#{num}" %></string>
<key>ProgramArguments</key>
<array>
<string><%= process.command %></string>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string><%= log_root %>/<%= app %>-<%= process.name %>-<%=num%>.log</string>
<key>UserName</key>
<string><%= user %></string>
<key>WorkingDirectory</key>
<string><%= engine.directory %></string>
</dict>
</plist>
+27
View File
@@ -0,0 +1,27 @@
<%
app_names = []
engine.procfile.entries.each do |process|
next if (conc = self.concurrency[process.name]) < 1
1.upto(self.concurrency[process.name]) do |num|
port = engine.port_for(process, num, self.port)
name = if (conc > 1); "#{process.name}-#{num}" else process.name; end
environment = (engine.environment.keys.sort.map{ |var| %{#{var.upcase}="#{engine.environment[var]}"} } + [%{PORT="#{port}"}])
app_name = "#{app}-#{name}"
app_names << app_name
%>
[program:<%= app_name %>]
command=<%= process.command %>
autostart=true
autorestart=true
stopsignal=QUIT
stdout_logfile=<%= log_root %>/<%=process.name%>-<%=num%>-out.log
stderr_logfile=<%= log_root %>/<%=process.name%>-<%=num%>-err.log
user=<%= user %>
directory=<%= engine.directory %>
environment=<%= environment.join(',') %><%
end
end
%>
[group:<%= app %>]
programs=<%= app_names.join(',') %>
+1 -1
View File
@@ -2,4 +2,4 @@ start on starting <%= app %>-<%= process.name %>
stop on stopping <%= app %>-<%= process.name %> stop on stopping <%= app %>-<%= process.name %>
respawn respawn
exec su - <%= user %> -c 'cd <%= engine.directory %>; export PORT=<%= port %>;<% engine.environment.each_pair do |var,env| %> export <%= var.upcase %>=<%= env %>; <% end %> <%= process.command %> >> <%= log_root %>/<%=process.name%>-<%=num%>.log 2>&1' exec su - <%= user %> -c 'cd <%= engine.directory %>; export PORT=<%= port %>;<% engine.environment.each_pair do |var,env| %> export <%= var.upcase %>=<%= shell_quote(env) %>; <% end %> <%= process.command %> >> <%= log_root %>/<%=process.name%>-<%=num%>.log 2>&1'
+1 -1
View File
@@ -10,5 +10,5 @@ task "gem:clean" do
end end
task "gem:release" => "gem:build" do |t| task "gem:release" => "gem:build" do |t|
sh "parka push -f #{pkg("foreman-#{version}.gem")}" sh "gem push #{pkg("foreman-#{version}.gem")} || echo 'error'"
end end
+1 -1
View File
@@ -12,5 +12,5 @@ task "jruby:clean" do
end end
task "jruby:release" => "jruby:build" do |t| task "jruby:release" => "jruby:build" do |t|
sh "parka push -f #{pkg("foreman-#{version}-jruby.gem")}" sh "gem push #{pkg("foreman-#{version}-jruby.gem")} || echo 'error'"
end end
+1 -1
View File
@@ -12,5 +12,5 @@ task "mingw32:clean" do
end end
task "mingw32:release" => "mingw32:build" do |t| task "mingw32:release" => "mingw32:build" do |t|
sh "parka push -f #{pkg("foreman-#{version}-mingw32.gem")}" sh "gem push #{pkg("foreman-#{version}-mingw32.gem")} || echo 'error'"
end end
+1 -2
View File
@@ -16,8 +16,7 @@ Gem::Specification.new do |gem|
gem.files = Dir["**/*"].select { |d| d =~ %r{^(README|bin/|data/|ext/|lib/|spec/|test/)} } gem.files = Dir["**/*"].select { |d| d =~ %r{^(README|bin/|data/|ext/|lib/|spec/|test/)} }
gem.files << "man/foreman.1" gem.files << "man/foreman.1"
gem.add_dependency 'term-ansicolor', '~> 1.0.7' gem.add_dependency 'thor', '>= 0.13.6'
gem.add_dependency 'thor', '>= 0.13.6'
if ENV["PLATFORM"] == "java" if ENV["PLATFORM"] == "java"
gem.add_dependency "posix-spawn", "~> 0.3.6" gem.add_dependency "posix-spawn", "~> 0.3.6"
+8 -3
View File
@@ -2,6 +2,7 @@ require "foreman"
require "foreman/helpers" require "foreman/helpers"
require "foreman/engine" require "foreman/engine"
require "foreman/export" require "foreman/export"
require "shellwords"
require "thor" require "thor"
require "yaml" require "yaml"
@@ -59,12 +60,12 @@ class Foreman::CLI < Thor
puts "valid procfile detected (#{engine.procfile.process_names.join(', ')})" puts "valid procfile detected (#{engine.procfile.process_names.join(', ')})"
end end
desc "run COMMAND", "Run a command using your application's environment" desc "run COMMAND [ARGS...]", "Run a command using your application's environment"
def run(*args) def run(*args)
engine.apply_environment! engine.apply_environment!
begin begin
exec args.join(" ") exec args.shelljoin
rescue Errno::EACCES rescue Errno::EACCES
error "not executable: #{args.first}" error "not executable: #{args.first}"
rescue Errno::ENOENT rescue Errno::ENOENT
@@ -83,7 +84,11 @@ private ######################################################################
end end
def procfile def procfile
options[:procfile] || "Procfile" case
when options[:procfile] then options[:procfile]
when options[:app_root] then File.expand_path(File.join(options[:app_root], "Procfile"))
else "Procfile"
end
end end
def error(message) def error(message)
+40
View File
@@ -0,0 +1,40 @@
require "foreman"
module Foreman::Color
ANSI = {
:reset => 0,
:black => 30,
:red => 31,
:green => 32,
:yellow => 33,
:blue => 34,
:magenta => 35,
:cyan => 36,
:white => 37,
:bright_black => 30,
:bright_red => 31,
:bright_green => 32,
:bright_yellow => 33,
:bright_blue => 34,
:bright_magenta => 35,
:bright_cyan => 36,
:bright_white => 37,
}
def self.enable(io)
io.extend(self)
end
def color?
return false unless self.respond_to?(:isatty)
self.isatty && ENV["TERM"]
end
def color(name)
return "" unless color?
return "" unless ansi = ANSI[name.to_sym]
"\e[#{ansi}m"
end
end
+36 -36
View File
@@ -1,10 +1,10 @@
require "foreman" require "foreman"
require "foreman/color"
require "foreman/process" require "foreman/process"
require "foreman/procfile" require "foreman/procfile"
require "foreman/utils" require "foreman/utils"
require "tempfile" require "tempfile"
require "timeout" require "timeout"
require "term/ansicolor"
require "fileutils" require "fileutils"
require "thread" require "thread"
@@ -15,18 +15,19 @@ class Foreman::Engine
attr_reader :directory attr_reader :directory
attr_reader :options attr_reader :options
extend Term::ANSIColor COLORS = %w( cyan yellow green magenta red blue intense_cyan intense_yellow
intense_green intense_magenta intense_red, intense_blue )
COLORS = [ cyan, yellow, green, magenta, red, blue, Foreman::Color.enable($stdout)
intense_cyan, intense_yellow, intense_green, intense_magenta,
intense_red, intense_blue ]
def initialize(procfile, options={}) def initialize(procfile, options={})
@procfile = Foreman::Procfile.new(procfile) @procfile = Foreman::Procfile.new(procfile) if File.exists?(procfile)
@directory = options[:app_root] || File.expand_path(File.dirname(procfile)) @directory = options[:app_root] || File.expand_path(File.dirname(procfile))
@options = options.dup @options = options.dup
@environment = read_environment_files(options[:env])
@output_mutex = Mutex.new @output_mutex = Mutex.new
@options[:env] ||= default_env
@environment = read_environment_files(@options[:env])
end end
def start def start
@@ -35,6 +36,7 @@ class Foreman::Engine
trap("TERM") { puts "SIGTERM received"; terminate_gracefully } trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
trap("INT") { puts "SIGINT received"; terminate_gracefully } trap("INT") { puts "SIGINT received"; terminate_gracefully }
trap("HUP") { puts "SIGHUP received"; terminate_gracefully }
assign_colors assign_colors
spawn_processes spawn_processes
@@ -52,6 +54,22 @@ class Foreman::Engine
environment.each { |k,v| ENV[k] = v } environment.each { |k,v| ENV[k] = v }
end end
def self.read_environment(filename)
return {} unless File.exists?(filename)
File.read(filename).split("\n").inject({}) do |hash, line|
if line =~ /\A([A-Za-z_0-9]+)=(.*)\z/
key, val = [$1, $2]
case val
when /\A'(.*)'\z/ then hash[key] = $1
when /\A"(.*)"\z/ then hash[key] = $1.gsub(/\\(.)/, '\1')
else hash[key] = val
end
end
hash
end
end
private ###################################################################### private ######################################################################
def spawn_processes def spawn_processes
@@ -67,7 +85,7 @@ private ######################################################################
end end
def base_port def base_port
options[:port] || 5000 options[:port] || environment["PORT"] || ENV["PORT"] || 5000
end end
def kill_all(signal="SIGTERM") def kill_all(signal="SIGTERM")
@@ -128,11 +146,11 @@ private ######################################################################
rescue Errno::ECHILD rescue Errno::ECHILD
end end
def info(message, name="system", color=Term::ANSIColor.white) def info(message, name="system", color=:white)
output = "" output = ""
output += color output += $stdout.color(color)
output += "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | " output += "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
output += Term::ANSIColor.reset output += $stdout.color(:reset)
output += message.chomp output += message.chomp
puts output puts output
end end
@@ -182,8 +200,8 @@ private ######################################################################
end end
def assign_colors def assign_colors
procfile.entries.each do |entry| procfile.entries.each_with_index do |entry, idx|
colors[entry.name] = next_color colors[entry.name] = COLORS[idx % COLORS.length]
end end
end end
@@ -191,38 +209,20 @@ private ######################################################################
readers.invert[reader] readers.invert[reader]
end end
def next_color
@current_color ||= -1
@current_color += 1
@current_color = 0 if COLORS.length < @current_color
COLORS[@current_color]
end
def read_environment_files(filenames) def read_environment_files(filenames)
environment = {} environment = {}
(filenames || "").split(",").map(&:strip).each do |filename| (filenames || "").split(",").map(&:strip).each do |filename|
error "No such file: #{filename}" unless File.exists?(filename) error "No such file: #{filename}" unless File.exists?(filename)
environment.merge!(read_environment(filename)) environment.merge!(Foreman::Engine.read_environment(filename))
end end
environment.merge!(read_environment(".env")) unless filenames
environment environment
end end
def read_environment(filename) def default_env
return {} unless File.exists?(filename) env = File.join(directory, ".env")
File.exists?(env) ? env : ""
File.read(filename).split("\n").inject({}) do |hash, line|
if line =~ /\A([A-Za-z_0-9]+)=(.*)\z/
key, val = [$1, $2]
case val
when /\A'(.*)'\z/ then hash[key] = $1
when /\A"(.*)"\z/ then hash[key] = $1.gsub(/\\(.)/, '\1')
else hash[key] = val
end
end
hash
end
end end
end end
+3
View File
@@ -30,3 +30,6 @@ require "foreman/export/inittab"
require "foreman/export/upstart" require "foreman/export/upstart"
require "foreman/export/bluepill" require "foreman/export/bluepill"
require "foreman/export/runit" require "foreman/export/runit"
require "foreman/export/supervisord"
require "foreman/export/launchd"
+15
View File
@@ -48,4 +48,19 @@ private ######################################################################
end end
end end
# Quote a string to be used on the command line. Backslashes are escapde to \\ and quotes
# escaped to \"
#
# str - string to be quoted
#
# Examples
#
# shell_quote("FB|123\"\\1")
# # => "\"FB|123\"\\"\\\\1\""
#
# Returns the the escaped string surrounded by quotes
def shell_quote(str)
"\"#{str.gsub(/\\/){ '\\\\' }.gsub(/["]/){ "\\\"" }}\""
end
end end
+27
View File
@@ -0,0 +1,27 @@
require "erb"
require "foreman/export"
class Foreman::Export::Launchd < Foreman::Export::Base
def export
error("Must specify a location") unless location
app = self.app || File.basename(engine.directory)
user = self.user || app
log_root = self.log || "/var/log/#{app}"
template_root = self.template
FileUtils.mkdir_p(location)
engine.procfile.entries.each do |process|
1.upto(self.concurrency[process.name]) do |num|
master_template = export_template("launchd", "launchd.plist.erb", template_root)
master_config = ERB.new(master_template).result(binding)
write_file "#{location}/#{app}-#{process.name}-#{num}.plist", master_config
end
end
end
end
+26
View File
@@ -0,0 +1,26 @@
require "erb"
require "foreman/export"
class Foreman::Export::Supervisord < Foreman::Export::Base
def export
error("Must specify a location") unless location
FileUtils.mkdir_p location
app = self.app || File.basename(engine.directory)
user = self.user || app
log_root = self.log || "/var/log/#{app}"
template_root = self.template
Dir["#{location}/#{app}*.conf"].each do |file|
say "cleaning up: #{file}"
FileUtils.rm(file)
end
app_template = export_template("supervisord", "app.conf.erb", template_root)
app_config = ERB.new(app_template, 0, '<').result(binding)
write_file "#{location}/#{app}.conf", app_config
end
end
+3 -1
View File
@@ -36,6 +36,8 @@ class Foreman::Export::Upstart < Foreman::Export::Base
write_file "#{location}/#{app}-#{process.name}-#{num}.conf", process_config write_file "#{location}/#{app}-#{process.name}-#{num}.conf", process_config
end end
end end
end
FileUtils.mkdir_p(log_root) rescue error "could not create #{log_root}"
FileUtils.chown(user, nil, log_root) rescue error "could not chown #{log_root} to #{user}"
end
end end
+1 -1
View File
@@ -62,7 +62,7 @@ private
$stdout.reopen writer $stdout.reopen writer
$stderr.reopen writer $stderr.reopen writer
reader.close reader.close
exec Foreman.runner, "-d", basedir, command exec Foreman.runner, "-d", basedir, *command.shellsplit
end end
end end
[ reader, pid ] [ reader, pid ]
+24 -4
View File
@@ -13,8 +13,9 @@ class Foreman::Procfile
attr_reader :entries attr_reader :entries
def initialize(filename) def initialize(filename=nil)
@entries = parse_procfile(filename) @entries = []
load(filename) if filename
end end
def [](name) def [](name)
@@ -25,12 +26,31 @@ class Foreman::Procfile
entries.map(&:name) entries.map(&:name)
end end
private def load(filename)
entries.clear
parse_procfile(filename)
end
def write(filename)
File.open(filename, 'w') do |io|
entries.each do |ent|
io.puts(ent)
end
end
end
def <<(entry)
entries << Foreman::ProcfileEntry.new(*entry)
self
end
protected
def parse_procfile(filename) def parse_procfile(filename)
File.read(filename).split("\n").map do |line| File.read(filename).split("\n").map do |line|
if line =~ /^([A-Za-z0-9_]+):\s*(.+)$/ if line =~ /^([A-Za-z0-9_]+):\s*(.+)$/
Foreman::ProcfileEntry.new($1, $2) self << [ $1, $2 ]
end end
end.compact end.compact
end end
+4
View File
@@ -19,4 +19,8 @@ class Foreman::ProcfileEntry
end end
end end
def to_s
"#{name}: #{command}"
end
end end
+1 -1
View File
@@ -1,5 +1,5 @@
module Foreman module Foreman
VERSION = "0.40.0" VERSION = "0.47.0"
end end
+9 -1
View File
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "FOREMAN" "1" "February 2012" "Foreman 0.39.0" "Foreman Manual" .TH "FOREMAN" "1" "April 2012" "Foreman 0.46.0" "Foreman Manual"
. .
.SH "NAME" .SH "NAME"
\fBforeman\fR \- manage Procfile\-based applications \fBforeman\fR \- manage Procfile\-based applications
@@ -35,6 +35,14 @@ The following options control how the application is run:
Specify the number of each process type to run\. The value passed in should be in the format \fBprocess=num,process=num\fR Specify the number of each process type to run\. The value passed in should be in the format \fBprocess=num,process=num\fR
. .
.TP .TP
\fB\-e\fR, \fB\-\-env\fR
Specify one or more \.env files to load
.
.TP
\fB\-f\fR, \fB\-\-procfile\fR
Specify an alternate Procfile to load, implies \fB\-d\fR at the Procfile root\.
.
.TP
\fB\-p\fR, \fB\-\-port\fR \fB\-p\fR, \fB\-\-port\fR
Specify which port to use as the base for this application\. Should be a multiple of 1000\. Specify which port to use as the base for this application\. Should be a multiple of 1000\.
. .
+6
View File
@@ -30,6 +30,12 @@ The following options control how the application is run:
Specify the number of each process type to run. The value passed in Specify the number of each process type to run. The value passed in
should be in the format `process=num,process=num` should be in the format `process=num,process=num`
* `-e`, `--env`:
Specify one or more .env files to load
* `-f`, `--procfile`:
Specify an alternate Procfile to load, implies `-d` at the Procfile root.
* `-p`, `--port`: * `-p`, `--port`:
Specify which port to use as the base for this application. Should be Specify which port to use as the base for this application. Should be
a multiple of 1000. a multiple of 1000.
+12 -3
View File
@@ -34,6 +34,15 @@ describe "Foreman::CLI", :fakefs do
subject.start("alpha") subject.start("alpha")
end end
end end
describe "with an alternate root" do
it "reads the Procfile from that root" do
write_procfile "/some/app/Procfile"
mock(Foreman::Procfile).new("/some/app/Procfile")
mock.instance_of(Foreman::Engine).start
foreman %{ start -d /some/app }
end
end
end end
describe "export" do describe "export" do
@@ -135,7 +144,7 @@ describe "Foreman::CLI", :fakefs do
before { write_procfile } before { write_procfile }
describe "and a command" do describe "and a command" do
let(:command) { ["ls", "-l"] } let(:command) { ["ls", "-l", "foo bar"] }
before(:each) do before(:each) do
stub(subject).exec stub(subject).exec
@@ -151,8 +160,8 @@ describe "Foreman::CLI", :fakefs do
ENV["FOO"].should be_nil ENV["FOO"].should be_nil
end end
it "should runute the command as a string" do it "should exec the argument list as a shell command" do
mock(subject).exec(command.join(" ")) mock(subject).exec(command.shelljoin)
subject.run *command subject.run *command
end end
end end
+31
View File
@@ -0,0 +1,31 @@
require "spec_helper"
require "foreman/color"
describe Foreman::Color do
let(:io) { Object.new }
it "should extend an object with colorization" do
Foreman::Color.enable(io)
io.should respond_to(:color)
end
it "should not colorize if the object does not respond to isatty" do
mock(io).respond_to?(:isatty) { false }
Foreman::Color.enable(io)
io.color(:white).should == ""
end
it "should not colorize if the object is not a tty" do
mock(io).isatty { false }
Foreman::Color.enable(io)
io.color(:white).should == ""
end
it "should colorize if the object is a tty" do
mock(io).isatty { true }
Foreman::Color.enable(io)
io.color(:white).should == "\e[37m"
end
end
+24 -6
View File
@@ -12,12 +12,6 @@ describe "Foreman::Engine", :fakefs do
end end
describe "initialize" do describe "initialize" do
describe "without an existing Procfile" do
it "raises an error" do
lambda { subject }.should raise_error
end
end
describe "with a Procfile" do describe "with a Procfile" do
before { write_procfile } before { write_procfile }
@@ -49,6 +43,14 @@ describe "Foreman::Engine", :fakefs do
end end
end end
describe "directories" do
it "has the directory default relative to the Procfile" do
write_procfile "/some/app/Procfile"
engine = Foreman::Engine.new("/some/app/Procfile")
engine.directory.should == "/some/app"
end
end
describe "environment" do describe "environment" do
before(:each) do before(:each) do
write_procfile write_procfile
@@ -97,6 +99,22 @@ describe "Foreman::Engine", :fakefs do
engine.environment.should == {"FOO"=>"qoo"} engine.environment.should == {"FOO"=>"qoo"}
engine.start engine.start
end end
it "should set port from .env if specified" do
File.open(".env", "w") { |f| f.puts("PORT=8017") }
engine = Foreman::Engine.new("Procfile")
engine.send(:base_port).should == "8017"
engine.start
end
it "should be loaded relative to the Procfile" do
FileUtils.mkdir_p "/some/app"
File.open("/some/app/.env", "w") { |f| f.puts("FOO=qoo") }
write_procfile "/some/app/Procfile"
engine = Foreman::Engine.new("/some/app/Procfile")
engine.environment.should == {"FOO"=>"qoo"}
engine.start
end
end end
describe "utf8" do describe "utf8" do
+24
View File
@@ -0,0 +1,24 @@
require "spec_helper"
require "foreman/engine"
require "foreman/export/launchd"
require "tmpdir"
describe Foreman::Export::Launchd, :fakefs do
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile") }
let(:engine) { Foreman::Engine.new(procfile) }
let(:options) { Hash.new }
let(:launchd) { Foreman::Export::Launchd.new("/tmp/init", engine, options) }
before(:each) { load_export_templates_into_fakefs("launchd") }
before(:each) { stub(launchd).say }
it "exports to the filesystem" do
launchd.export
normalize_space(File.read("/tmp/init/app-alpha-1.plist")).should == normalize_space(example_export_file("launchd/launchd-a.default"))
normalize_space(File.read("/tmp/init/app-bravo-1.plist")).should == normalize_space(example_export_file("launchd/launchd-b.default"))
end
end
+85
View File
@@ -0,0 +1,85 @@
require "spec_helper"
require "foreman/engine"
require "foreman/export/supervisord"
require "tmpdir"
describe Foreman::Export::Supervisord, :fakefs do
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile") }
let(:engine) { Foreman::Engine.new(procfile) }
let(:options) { Hash.new }
let(:supervisord) { Foreman::Export::Supervisord.new("/tmp/init", engine, options) }
before(:each) { load_export_templates_into_fakefs("supervisord") }
before(:each) { stub(supervisord).say }
it "exports to the filesystem" do
supervisord.export
File.read("/tmp/init/app.conf").should == example_export_file("supervisord/app.conf")
end
it "cleans up if exporting into an existing dir" do
mock(FileUtils).rm("/tmp/init/app.conf")
supervisord.export
supervisord.export
end
context "with concurrency" do
let(:options) { Hash[:concurrency => "alpha=2"] }
it "exports to the filesystem with concurrency" do
supervisord.export
File.read("/tmp/init/app.conf").should == example_export_file("supervisord/app-alpha-2.conf")
end
end
context "with alternate templates" do
let(:template_root) { "/tmp/alternate" }
let(:supervisord) { Foreman::Export::Supervisord.new("/tmp/init", engine, :template => template_root) }
before do
FileUtils.mkdir_p template_root
File.open("#{template_root}/app.conf.erb", "w") { |f| f.puts "alternate_template" }
end
it "can export with alternate template files" do
supervisord.export
File.read("/tmp/init/app.conf").should == "alternate_template\n"
end
end
context "with alternate templates from home dir" do
let(:default_template_root) {File.expand_path("#{ENV['HOME']}/.foreman/templates")}
before do
ENV['_FOREMAN_SPEC_HOME'] = ENV['HOME']
ENV['HOME'] = "/home/appuser"
FileUtils.mkdir_p default_template_root
File.open("#{default_template_root}/app.conf.erb", "w") { |f| f.puts "default_alternate_template" }
end
after do
ENV['HOME'] = ENV.delete('_FOREMAN_SPEC_HOME')
end
it "can export with alternate template files" do
supervisord.export
File.read("/tmp/init/app.conf").should == "default_alternate_template\n"
end
end
context "environment export" do
it "correctly translates environment when exporting" do
File.open("/tmp/supervisord_env", "w") { |f| f.puts("QUEUE=fastqueue,slowqueue\nVERBOSE=1") }
engine = Foreman::Engine.new(procfile,:env => "/tmp/supervisord_env")
supervisor = Foreman::Export::Supervisord.new("/tmp/init", engine, options)
stub(supervisor).say
supervisor.export
File.read("/tmp/init/app.conf").should == example_export_file("supervisord/app-env-with-comma.conf")
end
end
end
+6
View File
@@ -33,6 +33,12 @@ describe Foreman::Export::Upstart, :fakefs do
upstart.export upstart.export
end end
it "quotes and escapes environment variables" do
engine.environment['KEY'] = 'd"\|d'
upstart.export
File.read("/tmp/init/app-alpha-1.conf").should include('KEY="d\"\\\\|d"')
end
context "with concurrency" do context "with concurrency" do
let(:options) { Hash[:concurrency => "alpha=2"] } let(:options) { Hash[:concurrency => "alpha=2"] }
+16 -2
View File
@@ -121,11 +121,25 @@ describe Foreman::Process do
output.should include('777') output.should include('777')
end end
it 'should handle arguments' do it 'should handle multi-word arguments (old test)' do
pending # TODO: This test used to be marked pending; it now passes,
# but is very slow. The next test is a fast replacement.
run %{ sh -c "trap '' TERM; sleep 10" } run %{ sh -c "trap '' TERM; sleep 10" }
subject.should be_alive subject.should be_alive
end end
it 'should handle multi-word arguments' do
# We have to be a little clever here since Foreman will always
# print a status message that includes the command.
run %{ sh -c 'echo abcdef | tr a-c x | tr d-f y' }
output.should include('xxxyyy')
end
it 'should not clobber "$x"-subexpressions' do
pending 'this conflicts with the variable interpolation hack'
run %{ sh -c 'echo \$abcdef | tr \$ %' }
output.should include('%abcdef')
end
end end
end end
end end
+13
View File
@@ -0,0 +1,13 @@
require 'spec_helper'
require 'foreman/procfile_entry'
require 'pathname'
require 'tmpdir'
describe Foreman::ProcfileEntry do
subject { described_class.new('alpha', './alpha') }
it "stringifies as a Procfile line" do
subject.to_s.should == 'alpha: ./alpha'
end
end
+31
View File
@@ -0,0 +1,31 @@
require 'spec_helper'
require 'foreman/procfile'
require 'pathname'
require 'tmpdir'
describe Foreman::Procfile do
subject { described_class.new }
let(:testdir) { Pathname(Dir.tmpdir) }
let(:procfile) { testdir + 'Procfile' }
it "can have a process appended to it" do
subject << ['alpha', './alpha']
subject['alpha'].should be_a(Foreman::ProcfileEntry)
end
it "can write itself out to a file" do
subject << ['alpha', './alpha']
subject.write(procfile)
procfile.read.should == "alpha: ./alpha\n"
end
it "can re-read entries from a file" do
procfile.open('w') { |io| io.puts "gamma: ./radiation", "theta: ./rate" }
subject << ['alpha', './alpha']
subject.load(procfile)
subject.process_names.should have(2).members
subject.process_names.should include('gamma', 'theta')
end
end
@@ -13,6 +13,7 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
process.daemonize = true process.daemonize = true
process.environment = {"PORT" => "5000"} process.environment = {"PORT" => "5000"}
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill] process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
process.stop_grace_time = 45.seconds
process.stdout = process.stderr = "/var/log/app/app-alpha-1.log" process.stdout = process.stderr = "/var/log/app/app-alpha-1.log"
@@ -31,6 +32,7 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
process.daemonize = true process.daemonize = true
process.environment = {"PORT" => "5001"} process.environment = {"PORT" => "5001"}
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill] process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
process.stop_grace_time = 45.seconds
process.stdout = process.stderr = "/var/log/app/app-alpha-2.log" process.stdout = process.stderr = "/var/log/app/app-alpha-2.log"
+2
View File
@@ -13,6 +13,7 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
process.daemonize = true process.daemonize = true
process.environment = {"PORT" => "5000"} process.environment = {"PORT" => "5000"}
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill] process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
process.stop_grace_time = 45.seconds
process.stdout = process.stderr = "/var/log/app/app-alpha-1.log" process.stdout = process.stderr = "/var/log/app/app-alpha-1.log"
@@ -30,6 +31,7 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
process.daemonize = true process.daemonize = true
process.environment = {"PORT" => "5100"} process.environment = {"PORT" => "5100"}
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill] process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
process.stop_grace_time = 45.seconds
process.stdout = process.stderr = "/var/log/app/app-bravo-1.log" process.stdout = process.stderr = "/var/log/app/app-bravo-1.log"
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>app-alpha-1</string>
<key>ProgramArguments</key>
<array>
<string>./alpha</string>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/var/log/app/app-alpha-1.log</string>
<key>UserName</key>
<string>app</string>
<key>WorkingDirectory</key>
<string>/tmp/app</string>
</dict>
</plist>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>app-bravo-1</string>
<key>ProgramArguments</key>
<array>
<string>./bravo</string>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/var/log/app/app-bravo-1.log</string>
<key>UserName</key>
<string>app</string>
<key>WorkingDirectory</key>
<string>/tmp/app</string>
</dict>
</plist>
@@ -0,0 +1,24 @@
[program:app-alpha-1]
command=./alpha
autostart=true
autorestart=true
stopsignal=QUIT
stdout_logfile=/var/log/app/alpha-1-out.log
stderr_logfile=/var/log/app/alpha-1-err.log
user=app
directory=/tmp/app
environment=PORT="5000"
[program:app-alpha-2]
command=./alpha
autostart=true
autorestart=true
stopsignal=QUIT
stdout_logfile=/var/log/app/alpha-2-out.log
stderr_logfile=/var/log/app/alpha-2-err.log
user=app
directory=/tmp/app
environment=PORT="5001"
[group:app]
programs=app-alpha-1,app-alpha-2
@@ -0,0 +1,24 @@
[program:app-alpha]
command=./alpha
autostart=true
autorestart=true
stopsignal=QUIT
stdout_logfile=/var/log/app/alpha-1-out.log
stderr_logfile=/var/log/app/alpha-1-err.log
user=app
directory=/tmp/app
environment=QUEUE="fastqueue,slowqueue",VERBOSE="1",PORT="5000"
[program:app-bravo]
command=./bravo
autostart=true
autorestart=true
stopsignal=QUIT
stdout_logfile=/var/log/app/bravo-1-out.log
stderr_logfile=/var/log/app/bravo-1-err.log
user=app
directory=/tmp/app
environment=QUEUE="fastqueue,slowqueue",VERBOSE="1",PORT="5100"
[group:app]
programs=app-alpha,app-bravo
@@ -0,0 +1,21 @@
[program:app-alpha]
command=./alpha
autostart=true
autorestart=true
stopsignal=QUIT
stdout_logfile=/var/log/app/alpha-1-out.log
stderr_logfile=/var/log/app/alpha-1-err.log
user=app
directory=/tmp/app
environment=FOO="bar",PORT="5000"
[program:app-bravo]
command=./bravo
autostart=true
autorestart=true
stopsignal=QUIT
stdout_logfile=/var/log/app/bravo-1-out.log
stderr_logfile=/var/log/app/bravo-1-err.log
user=app
directory=/tmp/app
environment=FOO="bar",PORT="5100"
@@ -0,0 +1,24 @@
[program:app-alpha]
command=./alpha
autostart=true
autorestart=true
stopsignal=QUIT
stdout_logfile=/var/log/app/alpha-1-out.log
stderr_logfile=/var/log/app/alpha-1-err.log
user=app
directory=/tmp/app
environment=PORT="5000"
[program:app-bravo]
command=./bravo
autostart=true
autorestart=true
stopsignal=QUIT
stdout_logfile=/var/log/app/bravo-1-out.log
stderr_logfile=/var/log/app/bravo-1-err.log
user=app
directory=/tmp/app
environment=PORT="5100"
[group:app]
programs=app-alpha,app-bravo
-8
View File
@@ -27,14 +27,6 @@ task :pages => "man:commit" do
} }
end end
desc "Generate an authors list"
task :authors do
authors = %x{ git log --pretty=format:"%an" | sort -u }.split("\n")
readme = File.read("README.md")
readme.gsub!(/#### Patches contributed by\n([^\n]*)\n/m, "#### Patches contributed by\n#{authors.join(", ")}\n")
File.open("README.md", "w") { |f| f.print readme }
end
def latest_release def latest_release
latest = File.read("Changelog.md").split("\n").first.split(" ")[1] latest = File.read("Changelog.md").split("\n").first.split(" ")[1]
end end