Compare commits

...
72 Commits
Author SHA1 Message Date
David Dollar 8b49256175 0.60.2 2012-10-08 10:47:00 -04:00
David Dollar 37d777f224 update docs 2012-10-08 10:46:34 -04:00
David Dollar 73fc059634 Merge pull request #273 from silviorelli/master
Fix for fix on issue #260
2012-10-08 07:46:16 -07:00
Silvio Relli f7b7029cc0 Fix for nil value on io select loop, fixes #260 2012-10-08 16:40:37 +02:00
David Dollar 3a101ec7dd update changelog 2012-10-08 10:31:10 -04:00
David Dollar 6c931ea15e 0.60.1 2012-10-08 10:30:25 -04:00
David Dollar d173570d98 ree is timing out 2012-10-08 10:29:37 -04:00
David Dollar 0cd41fee7f Merge pull request #272 from silviorelli/master
High cpu load patch by @mauricio - fixes #260
2012-10-08 07:29:31 -07:00
Silvio Relli 9da4e38209 Cleaner fix for high cpu load issue, fixes #260 2012-10-08 16:05:20 +02:00
Silvio Relli 5d9dfd294e Patch for high cpu load issue 2012-10-08 11:52:39 +02:00
David Dollar 8998e9a47c update docs 2012-09-25 12:39:17 -05:00
David Dollar 8238a86942 update changelog 2012-09-25 12:38:45 -05:00
David Dollar 1153fb0f0c 0.60.0 2012-09-25 12:38:01 -05:00
David Dollar f69c755d9a Merge pull request #262 from dpiddy/foreman-run-from-procfile
foreman run can run things from the Procfile like heroku run.
2012-09-25 10:37:25 -07:00
David Dollar 64f0749d16 0.59.0 2012-09-15 11:49:46 +09:00
David Dollar 6b77ca1e46 Merge pull request #246 from jeremyevans/patch-1
Don't have foreman-runner depend on bash
2012-09-14 19:48:03 -07:00
Jeremy Evans 6a44dd3fd3 Use /bin/sh instead of bash for foreman-runner
/bin/sh should be installed by default on all unix machines, bash
is not necessarily installed on all machines.
2012-09-14 17:35:54 -07:00
Dan Peterson e99f3173ef foreman run can run things from the Procfile like heroku run. 2012-09-14 10:43:03 -03:00
David Dollar 6c04dab649 0.58.0 2012-09-14 18:10:05 +09:00
David Dollar 96e26e7412 dont set HOME 2012-09-14 17:44:32 +09:00
David Dollar a2c03cc402 Merge pull request #217 from danielfarrell/capistrano
Add capistrano export support
2012-09-14 01:42:34 -07:00
David Dollar 803115c0c4 Merge pull request #226 from alachaum/master
CLI: fix directory option
2012-09-14 01:41:36 -07:00
David Dollar a4343187ad Merge pull request #239 from indrekj/master
Use path and env variables in the inittab export
2012-09-14 01:41:18 -07:00
David Dollar 98af1f0943 Merge pull request #261 from martinisoft/launchd_environment
Launchd environment
2012-09-14 01:34:35 -07:00
David Dollar af2d4762a8 Merge pull request #250 from szimek/249_multiline_strings
Handle multiline strings in .env file
2012-09-14 01:34:10 -07:00
Aaron Kalin 1d06124457 Add StandardOutPath to launchd export 2012-09-11 15:04:15 -05:00
Aaron Kalin 698e6ae092 Add command argument string splitting
launchd uses exec() under the hood when you specify ProgramArguments
or Program so you must break apart program arguments into separate
strings in an array or the command will fail
2012-09-10 19:10:47 -05:00
Aaron Kalin c617ddb3b2 Cleanup launchd exporter
Also suppresses the deprecation warning for the launchd exporter when
using port instead of engine.port_for
2012-09-10 18:21:51 -05:00
Aaron Kalin f6d4badcd2 Enable trim_mode via '-' in ERB templates
This adds whitespace supression optionally, similar to the default
behavior in Rails ActionView ERB templates.

Just add - to a %> like so: -%> and it will remove trailing whitespace
and newlines. This can also be done to the beginning tag for removing
newlines from the beginning of the tag line.
2012-09-10 18:18:56 -05:00
Aaron Kalin f29bf49a35 Add support for setting environment variables 2012-09-05 18:27:10 -05:00
David Dollar e06d36b27c dont test 1.8.7 or rbx 2012-08-24 12:49:35 -04:00
David Dollar 85e62dfbeb Merge pull request #254 from omarkhan/master
foreman run should exit with the same code as its command
2012-08-24 09:14:45 -07:00
Omar Khan 574e852710 foreman run should exit with the same code as its command 2012-08-24 16:50:05 +01:00
David Dollar 68f098c1d2 update docs 2012-08-21 10:59:21 -04:00
David Dollar e8bdafdfc1 changelog 2012-08-21 10:58:58 -04:00
David Dollar 4abd3ebedb 0.57.0 2012-08-21 10:58:11 -04:00
David Dollar f765436dde fix errant space 2012-08-21 10:58:00 -04:00
David Dollar b5c513b4b5 Merge pull request #247 from asanghi/master
start on boot worked with network-interface but not network
2012-08-21 07:56:30 -07:00
Aditya Sanghi ee761ff098 Another fix for PR #229 2012-08-21 20:16:28 +05:30
David Dollar 27c22deb6c update changelog 2012-08-19 12:05:37 -04:00
David Dollar 681a9f7e61 0.56.0 2012-08-19 12:05:07 -04:00
David Dollar 8335a2b1ba read .profile, not .profile.d 2012-08-16 12:57:22 -04:00
David Dollar 407425ca78 update changelog 2012-08-14 17:08:14 -04:00
David Dollar 6ca505b4cd 0.55.0 2012-08-14 17:07:52 -04:00
David Dollar 612eae5e21 use a forked process to exec a run with environment 2012-08-14 17:07:39 -04:00
David Dollar 497b5ea1eb update changelog 2012-08-14 17:03:28 -04:00
David Dollar cd384e0d59 0.54.0 2012-08-14 17:00:19 -04:00
David Dollar 8921cac35b use Foreman::Process to extract command running 2012-08-14 17:00:01 -04:00
Szymon Nowak 7d6de5b2a7 Handle multiline strings in .env file 2012-08-14 11:09:21 +02:00
Aditya Sanghi cc4306492e run on reboot works with network-interface not network 2012-08-12 14:17:39 +05:30
David Dollar 6042783e82 Merge pull request #245 from brntbeer/env_bash_fix
changed to check env for bash
2012-08-08 14:09:19 -07:00
brntbeer b7b3a9f898 changed to check env for bash 2012-08-08 13:53:36 -07:00
Indrek Juhkam 8b204db2f0 Use path and env variables in the inittab export 2012-07-31 21:44:31 +03:00
David Dollar 15643dcb3f changelog 2012-07-24 11:18:42 -04:00
David Dollar 5f0f2f5378 0.53.0 2012-07-24 11:18:20 -04:00
David Dollar c1b57b59cf put app root in $HOME 2012-07-24 11:18:05 -04:00
David Dollar 21d53818f2 add changelog 2012-07-24 11:11:04 -04:00
David Dollar 359d6f1c34 0.52.0 2012-07-24 11:10:16 -04:00
David Dollar 584f251e4a wrap command in a runner that sources .profile.d scripts 2012-07-24 11:09:54 -04:00
David Dollar 7d9c2b2ac4 fix upstart export specs 2012-07-24 10:50:34 -04:00
David Dollar fba4d9beff Merge pull request #229 from danielfarrell/autostart-upstart
Make upstart export start/stop with network
2012-07-18 13:55:01 -07:00
Daniel Farrell 0bde5fdab5 Make upstart export start/stop with network 2012-07-18 16:50:49 -04:00
Arnaud Lachaume ebe160d425 fixed the directory option 2012-07-14 11:48:24 +10:00
David Dollar 1beab80c1f update docs 2012-07-11 18:33:13 -04:00
David Dollar 7b270f9f4a changelog 2012-07-11 18:33:10 -04:00
David Dollar 03e5342067 0.51.0 2012-07-11 18:32:51 -04:00
David Dollar b1d57426fb dont try to colorize windows 2012-07-11 18:30:51 -04:00
David Dollar 06e5c52f35 add mswin32 dist 2012-07-11 18:30:38 -04:00
David Dollar 64ca839c0b update docs 2012-07-11 16:17:13 -04:00
David Dollar 80aebda023 update changelog 2012-07-11 16:17:10 -04:00
David Dollar 5dee2281a2 fix up release tasks 2012-07-11 16:16:29 -04:00
Daniel Farrell 0a61b1a62f Add capistrano export support 2012-06-22 15:49:19 -04:00
30 changed files with 373 additions and 62 deletions
-3
View File
@@ -16,9 +16,6 @@ notifications:
- http://dx-helper.herokuapp.com/travis - http://dx-helper.herokuapp.com/travis
rvm: rvm:
- 1.8.7
- 1.9.2 - 1.9.2
- 1.9.3 - 1.9.3
- jruby - jruby
- rbx
- ree
+84 -8
View File
@@ -1,17 +1,93 @@
## 0.48.0.pre2 (2012-06-17) ## 0.60.1 (2012-10-08)
* 0.48.0.pre2 [David Dollar] * sleep on select() to avoid spinning the cpu [Silvio Relli]
## 0.60.0 (2012-09-25)
* foreman run can run things from the Procfile like heroku run. [Dan Peterson]
## 0.59.0 (2012-09-15)
* Use /bin/sh instead of bash for foreman-runner [Jeremy Evans]
## 0.58.0 (2012-09-14)
* dont set HOME [David Dollar]
* Add StandardOutPath to launchd export [Aaron Kalin]
* Add command argument string splitting [Aaron Kalin]
* Cleanup launchd exporter [Aaron Kalin]
* Enable trim_mode via '-' in ERB templates [Aaron Kalin]
* Add support for setting environment variables [Aaron Kalin]
* foreman run should exit with the same code as its command [Omar Khan]
* Handle multiline strings in .env file [Szymon Nowak]
* Use path and env variables in the inittab export [Indrek Juhkam]
* fixed the directory option [Arnaud Lachaume]
* Add capistrano export support [Daniel Farrell]
## 0.57.0 (2012-08-21)
* fix startup checks for upstart exporter [Aditya Sanghi]
## 0.56.0 (2012-08-19)
* read .profile, not .profile.d [David Dollar]
## 0.55.0 (2012-08-14)
* use a forked process to exec a run with environment [David Dollar]
## 0.54.0 (2012-08-14)
* use Foreman::Process to extract command running [David Dollar]
* changed to check env for bash [brntbeer]
## 0.53.0 (2012-07-24)
* put app root in $HOME [David Dollar]
## 0.52.0 (2012-07-24)
* wrap command in a runner that sources .profile.d scripts [David Dollar]
* fix upstart export specs [David Dollar]
* Make upstart export start/stop with network [Daniel Farrell]
## 0.51.0 (2012-07-11)
* dont try to colorize windows [David Dollar]
## 0.50.0 (2012-07-11)
* handle windows [David Dollar]
## 0.49.0 (2012-07-11)
* 1.8 compatibility [David Dollar]
* use one pgroup for all of foreman and kill that since ruby 1.8 sucks at pgroups [David Dollar]
* better debugging [David Dollar]
## 0.48.0 (2012-07-10)
* allow old exporter format to work, but with deprecation warning [David Dollar]
* remove debugging code [David Dollar]
* Merge pull request #219 from MarkDBlackwell/patch-1 [David Dollar]
* Avoid crash by verifying the existence of SIGHUP before accessing it. [Mark D. Blackwell]
* allow color to be forced on [David Dollar] * allow color to be forced on [David Dollar]
* terminate gracefully if stdout goes away [David Dollar] * terminate gracefully if stdout goes away [David Dollar]
* always flush output [David Dollar] * always flush output [David Dollar]
* Merge pull request #212 from morgoth/added-version-command [David Dollar]
* added command for displaying foreman version [Wojciech Wnętrzak]
* Merge pull request #211 from morgoth/fixed-yaml-usage [David Dollar]
* fixed using YAML [Wojciech Wnętrzak]
* test on more things, but don't fail [David Dollar] * test on more things, but don't fail [David Dollar]
* changelog [David Dollar] * changelog [David Dollar]
* 0.48.0.pre1 [David Dollar]
## 0.48.0.pre1 (2012-06-11) * foreman doesn't work on ruby 1.8, may try to fix later [David Dollar]
* use bash [David Dollar]
* Massive refactoring for programmatic control and stability [David Dollar] * massive refactoring for programmatic control and stability [David Dollar]
* Procfile commands with shell interpolations now work again [David Dollar] * Merge pull request #164 from hsume2/master [David Dollar]
* Stop trying to test on Ruby 1.8 [David Dollar] * Only run tmux specs if tmux is installed [Henry Hsu]
* Do not assume BUNDLE_GEMFILE [Henry Hsu]
* Add support for starting procfile in tmux session [Henry Hsu]
## 0.47.0 (2012-06-07) ## 0.47.0 (2012-06-07)
+2 -2
View File
@@ -1,7 +1,7 @@
PATH PATH
remote: . remote: .
specs: specs:
foreman (0.50.0) foreman (0.60.2)
thor (>= 0.13.6) thor (>= 0.13.6)
GEM GEM
@@ -39,7 +39,7 @@ 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)
thor (0.15.4) thor (0.16.0)
timecop (0.3.5) timecop (0.3.5)
win32console (1.3.0-x86-mingw32) win32console (1.3.0-x86-mingw32)
xml-simple (1.0.15) xml-simple (1.0.15)
+11 -2
View File
@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# #
#/ Usage: foreman-runner [-d <dir>] <command> [<args>...] #/ Usage: foreman-runner [-d <dir>] [-p] <command> [<args>...]
#/ #/
#/ Run a command with exec, optionally changing directory first #/ Run a command with exec, optionally changing directory first
@@ -16,9 +16,12 @@ usage() {
exit exit
} }
while getopts ":hd:" OPT; do read_profile=""
while getopts ":hd:p" OPT; do
case $OPT in case $OPT in
d) cd "$OPTARG" ;; d) cd "$OPTARG" ;;
p) read_profile="1" ;;
h) usage ;; h) usage ;;
\?) error "invalid option: -$OPTARG" ;; \?) error "invalid option: -$OPTARG" ;;
:) error "option -$OPTARG requires an argument" ;; :) error "option -$OPTARG requires an argument" ;;
@@ -29,4 +32,10 @@ shift $((OPTIND-1))
[ -z "$1" ] && usage [ -z "$1" ] && usage
if [ "$read_profile" = "1" ]; then
if [ -f .profile ]; then
. .profile
fi
fi
exec "$@" exec "$@"
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
export FOO=bar
+12 -1
View File
@@ -4,14 +4,25 @@
<dict> <dict>
<key>Label</key> <key>Label</key>
<string><%= "#{app}-#{name}-#{num}" %></string> <string><%= "#{app}-#{name}-#{num}" %></string>
<key>EnvironmentVariables</key>
<dict>
<%- engine.env.merge("PORT" => port).each_pair do |var,env| -%>
<key><%= var.upcase %></key>
<string><%= env %></string>
<%- end -%>
</dict>
<key>ProgramArguments</key> <key>ProgramArguments</key>
<array> <array>
<string><%= process.command %></string> <%- command_args.each do |command| -%>
<string><%= command %></string>
<%- end -%>
</array> </array>
<key>KeepAlive</key> <key>KeepAlive</key>
<true/> <true/>
<key>RunAtLoad</key> <key>RunAtLoad</key>
<true/> <true/>
<key>StandardOutPath</key>
<string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string>
<key>StandardErrorPath</key> <key>StandardErrorPath</key>
<string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string> <string><%= log %>/<%= app %>-<%= name %>-<%=num%>.log</string>
<key>UserName</key> <key>UserName</key>
+8
View File
@@ -6,3 +6,11 @@ bash << "EOF"
EOF EOF
end script end script
start on (started network-interface
or started network-manager
or started networking)
stop on (stopping network-interface
or stopping network-manager
or stopping networking)
+16
View File
@@ -0,0 +1,16 @@
file pkg("foreman-#{version}-x86-mswin32.gem") => distribution_files do |t|
Bundler.with_clean_env do
sh "env PLATFORM=mswin32 gem build foreman.gemspec"
end
sh "mv foreman-#{version}-x86-mswin32.gem #{t.name}"
end
task "mswin32:build" => pkg("foreman-#{version}-x86-mswin32.gem")
task "mswin32:clean" do
clean pkg("foreman-#{version}-x86-mswin32.gem")
end
task "mswin32:release" => "mswin32:build" do |t|
sh "gem push #{pkg("foreman-#{version}-x86-mswin32.gem")} || echo 'error'"
end
+54
View File
@@ -0,0 +1,54 @@
if defined?(Capistrano)
Capistrano::Configuration.instance(:must_exist).load do
namespace :foreman do
desc <<-DESC
Export the Procfile to upstart. Will use sudo if available.
You can override any of these defaults by setting the variables shown below.
set :foreman_format, "upstart"
set :foreman_location, "/etc/init"
set :foreman_procfile, "Procfile"
set :foreman_app, application
set :foreman_user, user
set :foreman_log, "#{shared_path}/log"
set :foreman_concurrency, false
DESC
task :export, :roles => :app do
bundle_cmd = fetch(:bundle_cmd, "bundle")
foreman_format = fetch(:foreman_format, "upstart")
foreman_location = fetch(:foreman_location, "/etc/init")
foreman_procfile = fetch(:foreman_procfile, "Procfile")
foreman_app = fetch(:foreman_app, application)
foreman_user = fetch(:foreman_user, user)
foreman_log = fetch(:foreman_log, "#{shared_path}/log")
foreman_concurrency = fetch(:foreman_concurrency, false)
args = ["#{foreman_format} #{foreman_location}"]
args << "-f #{foreman_procfile}"
args << "-a #{foreman_app}"
args << "-u #{foreman_user}"
args << "-l #{foreman_log}"
args << "-c #{foreman_concurrency}" if foreman_concurrency
run "cd #{release_path} && #{sudo} #{bundle_cmd} exec foreman export #{args.join(' ')}"
end
desc "Start the application services"
task :start, :roles => :app do
run "#{sudo} start #{application}"
end
desc "Stop the application services"
task :stop, :roles => :app do
run "#{sudo} stop #{application}"
end
desc "Restart the application services"
task :restart, :roles => :app do
run "#{sudo} start #{application} || #{sudo} restart #{application}"
end
end
end
end
+21 -7
View File
@@ -75,13 +75,27 @@ class Foreman::CLI < Thor
def run(*args) def run(*args)
load_environment! load_environment!
begin
exec engine.env, args.shelljoin if File.exist?(procfile)
rescue Errno::EACCES engine.load_procfile(procfile)
error "not executable: #{args.first}"
rescue Errno::ENOENT
error "command not found: #{args.first}"
end end
pid = fork do
begin
engine.env.each { |k,v| ENV[k] = v }
if args.size == 1 && process = engine.process(args.first)
process.exec(:env => engine.env)
else
exec args.shelljoin
end
rescue Errno::EACCES
error "not executable: #{args.first}"
rescue Errno::ENOENT
error "command not found: #{args.first}"
end
end
Process.wait(pid)
exit $?.exitstatus
end end
desc "version", "Display Foreman gem version" desc "version", "Display Foreman gem version"
@@ -125,7 +139,7 @@ private ######################################################################
def procfile def procfile
case case
when options[:procfile] then options[:procfile] when options[:procfile] then options[:procfile]
when options[:root] then File.expand_path(File.join(options[:app_root], "Procfile")) when options[:root] then File.expand_path(File.join(options[:root], "Procfile"))
else "Procfile" else "Procfile"
end end
end end
+5 -2
View File
@@ -256,7 +256,9 @@ private
1.upto(formation[@names[process]]) do |n| 1.upto(formation[@names[process]]) do |n|
reader, writer = create_pipe reader, writer = create_pipe
begin begin
pid = process.run(:output => writer, :env => { "PORT" => port_for(process, n).to_s }) pid = process.run(:output => writer, :env => {
"PORT" => port_for(process, n).to_s
})
writer.puts "started with pid #{pid}" writer.puts "started with pid #{pid}"
rescue Errno::ENOENT rescue Errno::ENOENT
writer.puts "unknown command: #{process.command}" writer.puts "unknown command: #{process.command}"
@@ -271,7 +273,8 @@ private
Thread.new do Thread.new do
begin begin
loop do loop do
(IO.select(@readers.values).first || []).each do |reader| io = IO.select(@readers.values, nil, nil, 30)
(io.nil? ? [] : io.first).each do |reader|
data = reader.gets data = reader.gets
output_with_mutex name_for(@readers.invert[reader]), data output_with_mutex name_for(@readers.invert[reader]), data
end end
+3 -4
View File
@@ -31,7 +31,7 @@ class Foreman::Engine::CLI < Foreman::Engine
def color? def color?
return true if @@color_force return true if @@color_force
return true if Foreman.windows? return false if Foreman.windows?
return false unless self.respond_to?(:isatty) return false unless self.respond_to?(:isatty)
self.isatty && ENV["TERM"] self.isatty && ENV["TERM"]
end end
@@ -49,9 +49,8 @@ class Foreman::Engine::CLI < Foreman::Engine
def startup def startup
@colors = map_colors @colors = map_colors
proctitle "foreman: master" proctitle "foreman: master" unless Foreman.windows?
require "win32console" if Foreman.windows? Color.enable($stdout, options[:color])
Color.enable($stdout, options[:color]) unless $stdout.respond_to?(:color?)
end end
def output(name, data) def output(name, data)
+3 -1
View File
@@ -9,8 +9,10 @@ class Foreman::Env
if line =~ /\A([A-Za-z_0-9]+)=(.*)\z/ if line =~ /\A([A-Za-z_0-9]+)=(.*)\z/
key = $1 key = $1
case val = $2 case val = $2
# Remove single quotes
when /\A'(.*)'\z/ then ax[key] = $1 when /\A'(.*)'\z/ then ax[key] = $1
when /\A"(.*)"\z/ then ax[key] = $1.gsub(/\\(.)/, '\1') # Remove double quotes and unescape string preserving newline characters
when /\A"(.*)"\z/ then ax[key] = $1.gsub('\n', "\n").gsub(/\\(.)/, '\1')
else ax[key] = val else ax[key] = val
end end
end end
+1 -1
View File
@@ -119,7 +119,7 @@ private ######################################################################
end end
def write_template(name, target, binding) def write_template(name, target, binding)
compiled = ERB.new(export_template(name)).result(binding) compiled = ERB.new(export_template(name), nil, '-').result(binding)
write_file target, compiled write_file target, compiled
end end
+10 -1
View File
@@ -13,7 +13,16 @@ class Foreman::Export::Inittab < Foreman::Export::Base
1.upto(engine.formation[name]) do |num| 1.upto(engine.formation[name]) do |num|
id = app.slice(0, 2).upcase + sprintf("%02d", index) id = app.slice(0, 2).upcase + sprintf("%02d", index)
port = engine.port_for(process, num) port = engine.port_for(process, num)
inittab << "#{id}:4:respawn:/bin/su - #{user} -c 'PORT=#{port} #{process.command} >> #{log}/#{name}-#{num}.log 2>&1'"
commands = []
commands << "cd #{engine.root}"
commands << "export PORT=#{port}"
engine.env.each_pair do |var, env|
commands << "export #{var.upcase}=#{shell_quote(env)}"
end
commands << "#{process.command} >> #{log}/#{name}-#{num}.log 2>&1"
inittab << "#{id}:4:respawn:/bin/su - #{user} -c '#{commands.join(";")}'"
index += 1 index += 1
end end
end end
+2
View File
@@ -7,6 +7,8 @@ class Foreman::Export::Launchd < Foreman::Export::Base
super super
engine.each_process do |name, process| engine.each_process do |name, process|
1.upto(engine.formation[name]) do |num| 1.upto(engine.formation[name]) do |num|
port = engine.port_for(process, num)
command_args = process.command.split(" ")
write_template "launchd/launchd.plist.erb", "#{app}-#{name}-#{num}.plist", binding write_template "launchd/launchd.plist.erb", "#{app}-#{name}-#{num}.plist", binding
end end
end end
+47 -23
View File
@@ -21,6 +21,21 @@ class Foreman::Process
@options[:env] ||= {} @options[:env] ||= {}
end end
# Get environment-expanded command for a +Process+
#
# @param [Hash] custom_env ({}) Environment variables to merge with defaults
#
# @return [String] The expanded command
#
def expanded_command(custom_env={})
env = @options[:env].merge(custom_env)
expanded_command = command.dup
env.each do |key, val|
expanded_command.gsub!("$#{key}", val)
end
expanded_command
end
# Run a +Process+ # Run a +Process+
# #
# @param [Hash] options # @param [Hash] options
@@ -31,38 +46,45 @@ class Foreman::Process
# @returns [Fixnum] pid The +pid+ of the process # @returns [Fixnum] pid The +pid+ of the process
# #
def run(options={}) def run(options={})
env = options[:env] ? @options[:env].merge(options[:env]) : @options[:env] env = @options[:env].merge(options[:env] || {})
output = options[:output] || $stdout output = options[:output] || $stdout
if Foreman.windows? if Foreman.windows?
Dir.chdir(cwd) do Dir.chdir(cwd) do
expanded_command = command.dup Process.spawn env, expanded_command(env), :out => output, :err => output
env.each do |key, val|
expanded_command.gsub!("$#{key}", val)
end
Process.spawn env, expanded_command, :out => output, :err => output
end end
elsif Foreman.jruby? elsif Foreman.jruby?
Dir.chdir(cwd) do require "posix/spawn"
require "posix/spawn" wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
POSIX::Spawn.spawn env, command, :out => output, :err => output POSIX::Spawn.spawn env, wrapped_command, :out => output, :err => output
end
elsif Foreman.ruby_18? elsif Foreman.ruby_18?
Dir.chdir(cwd) do fork do
fork do $stdout.reopen output
$stdout.reopen output $stderr.reopen output
$stderr.reopen output env.each { |k,v| ENV[k] = v }
env.each { |k,v| ENV[k] = v } wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
exec command Kernel.exec wrapped_command
end
end end
else else
Dir.chdir(cwd) do wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
Process.spawn env, command, :out => output, :err => output Process.spawn env, wrapped_command, :out => output, :err => output
end
end end
end end
# Exec a +Process+
#
# @param [Hash] options
#
# @option options :env ({}) Environment variables to set for this execution
#
# @return Does not return
def exec(options={})
env = @options[:env].merge(options[:env] || {})
env.each { |k, v| ENV[k] = v }
Dir.chdir(cwd)
Kernel.exec expanded_command(env)
end
# Send a signal to this +Process+ # Send a signal to this +Process+
# #
# @param [String] signal The signal to send # @param [String] signal The signal to send
@@ -93,10 +115,12 @@ class Foreman::Process
!alive? !alive?
end end
private # Returns the working directory for this +Process+
#
# @returns [String]
#
def cwd def cwd
@options[:cwd] || "." File.expand_path(@options[:cwd] || ".")
end end
end end
+1 -1
View File
@@ -1,5 +1,5 @@
module Foreman module Foreman
VERSION = "0.50.0" VERSION = "0.60.2"
end end
+1 -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" "June 2012" "Foreman 0.49.0" "Foreman Manual" .TH "FOREMAN" "1" "August 2012" "Foreman 0.60.1" "Foreman Manual"
. .
.SH "NAME" .SH "NAME"
\fBforeman\fR \- manage Procfile\-based applications \fBforeman\fR \- manage Procfile\-based applications
+9
View File
@@ -72,6 +72,15 @@ describe "Foreman::CLI", :fakefs do
it "includes the environment" do it "includes the environment" do
forked_foreman("run #{resource_path("bin/env FOO")} -e #{resource_path(".env")}").should == "bar\n" forked_foreman("run #{resource_path("bin/env FOO")} -e #{resource_path(".env")}").should == "bar\n"
end end
it "can run a command from the Procfile" do
forked_foreman("run -f #{resource_path("Procfile")} test").should == "testing\n"
end
it "exits with the same exit code as the command" do
fork_and_get_exitstatus("run echo 1").should == 0
fork_and_get_exitstatus("run date 'invalid_date'").should == 1
end
end end
describe "version" do describe "version" do
+8
View File
@@ -90,6 +90,14 @@ describe "Foreman::Engine", :fakefs do
subject.env["OTHER"].should == 'escaped"quote' subject.env["OTHER"].should == 'escaped"quote'
end end
it "should handle multiline strings" do
File.open("/tmp/env", "w") do |f|
f.puts 'FOO="bar\nbaz"'
end
subject.load_env "/tmp/env"
subject.env["FOO"].should == "bar\nbaz"
end
it "should fail if specified and doesnt exist" do it "should fail if specified and doesnt exist" do
lambda { subject.load_env "/tmp/env" }.should raise_error(Errno::ENOENT) lambda { subject.load_env "/tmp/env" }.should raise_error(Errno::ENOENT)
end end
+10
View File
@@ -18,4 +18,14 @@ describe Foreman::Export::Launchd, :fakefs do
File.read("/tmp/init/app-bravo-1.plist").should == example_export_file("launchd/launchd-b.default") File.read("/tmp/init/app-bravo-1.plist").should == example_export_file("launchd/launchd-b.default")
end end
context "with multiple command arguments" do
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile", "charlie") }
it "splits each command argument" do
launchd.export
File.read("/tmp/init/app-alpha-1.plist").should == example_export_file("launchd/launchd-c.default")
end
end
end end
@@ -1,4 +1,4 @@
# ----- foreman app processes ----- # ----- foreman app processes -----
AP01:4:respawn:/bin/su - app -c 'PORT=5000 ./alpha >> /var/log/app/alpha-1.log 2>&1' AP01:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5000;./alpha >> /var/log/app/alpha-1.log 2>&1'
AP02:4:respawn:/bin/su - app -c 'PORT=5001 ./alpha >> /var/log/app/alpha-2.log 2>&1' AP02:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5001;./alpha >> /var/log/app/alpha-2.log 2>&1'
# ----- end foreman app processes ----- # ----- end foreman app processes -----
@@ -1,4 +1,4 @@
# ----- foreman app processes ----- # ----- foreman app processes -----
AP01:4:respawn:/bin/su - app -c 'PORT=5000 ./alpha >> /var/log/app/alpha-1.log 2>&1' AP01:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5000;./alpha >> /var/log/app/alpha-1.log 2>&1'
AP02:4:respawn:/bin/su - app -c 'PORT=5100 ./bravo >> /var/log/app/bravo-1.log 2>&1' AP02:4:respawn:/bin/su - app -c 'cd /tmp/app;export PORT=5100;./bravo >> /var/log/app/bravo-1.log 2>&1'
# ----- end foreman app processes ----- # ----- end foreman app processes -----
@@ -4,6 +4,11 @@
<dict> <dict>
<key>Label</key> <key>Label</key>
<string>app-alpha-1</string> <string>app-alpha-1</string>
<key>EnvironmentVariables</key>
<dict>
<key>PORT</key>
<string>5000</string>
</dict>
<key>ProgramArguments</key> <key>ProgramArguments</key>
<array> <array>
<string>./alpha</string> <string>./alpha</string>
@@ -12,6 +17,8 @@
<true/> <true/>
<key>RunAtLoad</key> <key>RunAtLoad</key>
<true/> <true/>
<key>StandardOutPath</key>
<string>/var/log/app/app-alpha-1.log</string>
<key>StandardErrorPath</key> <key>StandardErrorPath</key>
<string>/var/log/app/app-alpha-1.log</string> <string>/var/log/app/app-alpha-1.log</string>
<key>UserName</key> <key>UserName</key>
@@ -4,6 +4,11 @@
<dict> <dict>
<key>Label</key> <key>Label</key>
<string>app-bravo-1</string> <string>app-bravo-1</string>
<key>EnvironmentVariables</key>
<dict>
<key>PORT</key>
<string>5100</string>
</dict>
<key>ProgramArguments</key> <key>ProgramArguments</key>
<array> <array>
<string>./bravo</string> <string>./bravo</string>
@@ -12,6 +17,8 @@
<true/> <true/>
<key>RunAtLoad</key> <key>RunAtLoad</key>
<true/> <true/>
<key>StandardOutPath</key>
<string>/var/log/app/app-bravo-1.log</string>
<key>StandardErrorPath</key> <key>StandardErrorPath</key>
<string>/var/log/app/app-bravo-1.log</string> <string>/var/log/app/app-bravo-1.log</string>
<key>UserName</key> <key>UserName</key>
@@ -0,0 +1,30 @@
<?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>EnvironmentVariables</key>
<dict>
<key>PORT</key>
<string>5000</string>
</dict>
<key>ProgramArguments</key>
<array>
<string>./alpha</string>
<string>charlie</string>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/var/log/app/app-alpha-1.log</string>
<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>
+8
View File
@@ -6,3 +6,11 @@ bash << "EOF"
EOF EOF
end script end script
start on (started network-interface
or started network-manager
or started networking)
stop on (stopping network-interface
or stopping network-manager
or stopping networking)
+6
View File
@@ -58,6 +58,12 @@ def fork_and_capture(&blk)
end end
end end
def fork_and_get_exitstatus(args)
pid = Process.spawn("bundle exec bin/foreman #{args}", :out => "/dev/null", :err => "/dev/null")
Process.wait(pid)
$?.exitstatus
end
def mock_exit(&block) def mock_exit(&block)
block.should raise_error(SystemExit) block.should raise_error(SystemExit)
end end
+1 -1
View File
@@ -32,7 +32,7 @@ def latest_release
end end
def newer_release def newer_release
tags = %x{ git tag --contains v#{latest_release} }.split("\n").sort_by do |tag| tags = %x{ git tag --contains v#{latest_release} | grep -v pre }.split("\n").sort_by do |tag|
Gem::Version.new(tag[1..-1]) Gem::Version.new(tag[1..-1])
end end
tags[1] tags[1]