Compare commits

..

44 Commits

Author SHA1 Message Date
David Dollar
26bb0ed54e 0.61.0 2013-01-14 08:18:05 -05:00
David Dollar
44002953f6 Merge pull request #277 from pcasaretto/add-timeout-switch
Add timeout switch to CLI - fixes #178
2013-01-14 05:12:12 -08:00
David Dollar
bb2c3a2d04 Merge pull request #264 from asanghi/master
shared_path is set in documentation leading to early evaluation
2013-01-14 05:10:47 -08:00
David Dollar
88cdaacc67 Merge pull request #258 from mclazarus/master
Don't quote shell escaped values.
2013-01-14 05:10:36 -08:00
David Dollar
faf7b3c40f Merge pull request #279 from evanj/master
Fix --directory option: its actually --root
2013-01-14 05:10:11 -08:00
David Dollar
21dd610eaf Merge pull request #280 from BIAINC/windows/host-support
Strip Windows Line Endings
2013-01-14 05:10:01 -08:00
David Dollar
fe65c7510d Merge pull request #288 from crohr/remove-rubygems-requirement
Remove explicit requirement on rubygems.
2013-01-14 05:08:27 -08:00
David Dollar
cd2c255296 Merge pull request #291 from liveh2o/master
JRuby 1.9 doesn't require posix/spawn
2013-01-14 05:08:10 -08:00
David Dollar
92c1909217 Merge pull request #300 from mattv/output-blank-lines
Don't ignore blank lines in the output
2013-01-14 05:07:31 -08:00
David Dollar
af57bf3d52 Merge pull request #302 from ctrochalakis/process_group_fix
Ensure foreman is the process group leader
2013-01-14 05:07:21 -08:00
David Dollar
443994d3b5 Merge pull request #303 from fxposter/master
Fix for high CPU load. Fixes #260 and #299.
2013-01-14 05:06:44 -08:00
David Dollar
2faa3fb6ff Merge pull request #313 from sonots/fix_color
Fix color bug: not intense_cyan but bright_cyan
2013-01-14 05:02:52 -08:00
nseo
0d53f6bd6c fix more 2013-01-13 22:10:12 +09:00
nseo
1d2bcdbc56 fix color 2013-01-12 01:10:25 +09:00
Pavel Forkert
aceea1472a Fix #299 and #260
Some processes close their output channels and IO.select keeps
returning them as "readable", while IO#gets returns nil on them, thus
spending a lot of CPU looping through the same reader continuously
2013-01-07 02:30:56 +02:00
Christos Trochalakis
44726e377e Ensure foreman is the process group leader
Foreman should be the process leader before killing processes using
his process group id.

Before that foreman was broken when it was not spawned from a shell.
2012-12-27 15:47:02 +02:00
Matt Venables
61eca5a1d8 Don't ignore blank lines in the output
This fixes the stdout code to ensure that empty lines are outputted.
Many times, these blank lines are intentional, so foreman should not
suppress them.

This fixes #286
2012-12-21 11:12:52 -05:00
David Dollar
553ac7f81f Merge pull request #295 from petedmarsh/master
Add license to gemspec
2012-12-03 05:56:14 -08:00
petedmarsh
6790cf02a9 Add license to gemspec 2012-12-03 13:52:27 +00:00
Adam Hutchison
7ad41da592 Since JRuby 1.9 doesn't require posix/spawn, only follow that path if JRuby is loaded and running in 1.8 mode. 2012-11-27 22:07:50 -07:00
Cyril Rohr
8ee7b7afdf Remove explicit requirement on rubygems.
It's better to not force the use of a package manager. Better to add it
to the global RUBYOPT if needed. Also, this fixes a dependency issue
when using the .deb package (rubygems1.9.1 is not required, and should
not be).
2012-11-12 21:10:10 +01:00
Aditya Sanghi
2620b90808 Dont use shared_path variable before multistage has a chance at it 2012-11-02 14:04:27 +05:30
Paul Morton
89bdc3ab8e Strip Windows Line Endings 2012-10-18 09:28:39 -07:00
Evan Jones
60a11eb981 Fix man page: --directory is actually --root. 2012-10-18 11:48:50 -04:00
Paulo Luis Franchini Casaretto
61c222deb8 Add timeout switch to CLI 2012-10-17 16:05:10 -03:00
David Dollar
8fe86e98c8 update docs 2012-10-08 10:47:40 -04:00
David Dollar
5c1ffdb7dc changelog 2012-10-08 10:47:21 -04:00
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
Kevin McAllister
8fbee31a2d Remove expectation of double quotes around environment variables from
test comparisons
2012-09-14 21:33:57 -04:00
Kevin McAllister
7b4eabf0c5 Remove explicit wrapping of Shellwords.escape in double quotes
According to http://www.ruby-doc.org/stdlib-1.9.3/libdoc/shellwords/rdoc/Shellwords.html#method-c-shellescape

"Note that a resulted string should be used unquoted and is not
intended for use in double quotes nor in single quotes."
2012-09-14 21:33:57 -04:00
Dan Peterson
e99f3173ef foreman run can run things from the Procfile like heroku run. 2012-09-14 10:43:03 -03:00
21 changed files with 113 additions and 38 deletions

View File

@@ -19,4 +19,3 @@ rvm:
- 1.9.2
- 1.9.3
- jruby
- ree

View File

@@ -1,3 +1,33 @@
## 0.60.2 (2012-10-08)
* Fix for nil value on io select loop, fixes #260 [Silvio Relli]
## 0.60.1 (2012-10-08)
* 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]

View File

@@ -1,7 +1,7 @@
PATH
remote: .
specs:
foreman (0.59.0)
foreman (0.61.0)
thor (>= 0.13.6)
GEM

View File

@@ -3,6 +3,7 @@ require "foreman/version"
Gem::Specification.new do |gem|
gem.name = "foreman"
gem.license = "MIT"
gem.version = Foreman::VERSION
gem.author = "David Dollar"

View File

@@ -8,8 +8,8 @@ module Foreman
File.expand_path("../../bin/foreman-runner", __FILE__)
end
def self.jruby?
defined?(RUBY_PLATFORM) and RUBY_PLATFORM == "java"
def self.jruby_18?
defined?(RUBY_PLATFORM) and RUBY_PLATFORM == "java" and ruby_18?
end
def self.ruby_18?

View File

@@ -12,7 +12,7 @@ if defined?(Capistrano)
set :foreman_procfile, "Procfile"
set :foreman_app, application
set :foreman_user, user
set :foreman_log, "#{shared_path}/log"
set :foreman_log, 'shared_path/log'
set :foreman_concurrency, false
DESC
task :export, :roles => :app do

View File

@@ -23,6 +23,7 @@ class Foreman::CLI < Thor
method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
method_option :formation, :type => :string, :aliases => "-m", :banner => '"alpha=5,bar=3"'
method_option :port, :type => :numeric, :aliases => "-p"
method_option :timeout, :type => :numeric, :aliases => "-t", :desc => "Specify the amount of time (in seconds) processes have to shudown gracefully before receiving a SIGKILL, defaults to 5."
class << self
# Hackery. Take the run method away from Thor so that we can redefine it.
@@ -75,10 +76,19 @@ class Foreman::CLI < Thor
def run(*args)
load_environment!
if File.exist?(procfile)
engine.load_procfile(procfile)
end
pid = fork do
begin
engine.env.each { |k,v| ENV[k] = v }
exec args.shelljoin
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

View File

@@ -25,6 +25,7 @@ class Foreman::Engine
@options = options.dup
@options[:formation] ||= (options[:concurrency] || "all=1")
@options[:timeout] ||= 5
@env = {}
@mutex = Mutex.new
@@ -37,6 +38,9 @@ class Foreman::Engine
# Start the processes registered to this +Engine+
#
def start
# Make sure foreman is the process group leader.
Process.setpgrp unless Foreman.windows?
trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
trap("INT") { puts "SIGINT received"; terminate_gracefully }
trap("HUP") { puts "SIGHUP received"; terminate_gracefully } if ::Signal.list.keys.include? 'HUP'
@@ -109,7 +113,7 @@ class Foreman::Engine
end
else
begin
Process.kill "-#{signal}", Process.pid
Process.kill "-#{signal}", Process.getpgrp
rescue Errno::ESRCH, Errno::EPERM
end
end
@@ -273,9 +277,14 @@ private
Thread.new do
begin
loop do
(IO.select(@readers.values).first || []).each do |reader|
data = reader.gets
output_with_mutex name_for(@readers.invert[reader]), data
io = IO.select(@readers.values, nil, nil, 30)
(io.nil? ? [] : io.first).each do |reader|
if reader.eof?
@readers.delete_if { |key, value| value == reader }
else
data = reader.gets
output_with_mutex name_for(@readers.invert[reader]), data
end
end
end
rescue Exception => ex
@@ -304,7 +313,7 @@ private
system "sending SIGTERM to all processes"
killall "SIGTERM"
end
Timeout.timeout(5) do
Timeout.timeout(options[:timeout]) do
watch_for_termination while @running.length > 0
end
rescue Timeout::Error

View File

@@ -44,8 +44,8 @@ class Foreman::Engine::CLI < Foreman::Engine
end
FOREMAN_COLORS = %w( cyan yellow green magenta red blue intense_cyan intense_yellow
intense_green intense_magenta intense_red, intense_blue )
FOREMAN_COLORS = %w( cyan yellow green magenta red blue bright_cyan bright_yellow
bright_green bright_magenta bright_red bright_blue )
def startup
@colors = map_colors
@@ -54,7 +54,7 @@ class Foreman::Engine::CLI < Foreman::Engine
end
def output(name, data)
data.to_s.chomp.split("\n").each do |message|
data.to_s.lines.map(&:chomp).each do |message|
output = ""
output += $stdout.color(@colors[name.split(".").first].to_sym)
output += "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
@@ -89,7 +89,7 @@ private
@names.values.each_with_index do |name, index|
colors[name] = FOREMAN_COLORS[index % FOREMAN_COLORS.length]
end
colors["system"] = "intense_white"
colors["system"] = "bright_white"
colors
end

View File

@@ -5,7 +5,7 @@ class Foreman::Env
attr_reader :entries
def initialize(filename)
@entries = File.read(filename).split("\n").inject({}) do |ax, line|
@entries = File.read(filename).gsub("\r\n","\n").split("\n").inject({}) do |ax, line|
if line =~ /\A([A-Za-z_0-9]+)=(.*)\z/
key = $1
case val = $2

View File

@@ -91,7 +91,7 @@ private ######################################################################
end
def shell_quote(value)
'"' + Shellwords.escape(value) + '"'
Shellwords.escape(value)
end
# deprecated

View File

@@ -1,5 +1,4 @@
require "foreman"
require "rubygems"
class Foreman::Process
@@ -21,6 +20,21 @@ class Foreman::Process
@options[:env] ||= {}
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+
#
# @param [Hash] options
@@ -31,18 +45,14 @@ class Foreman::Process
# @returns [Fixnum] pid The +pid+ of the process
#
def run(options={})
env = options[:env] ? @options[:env].merge(options[:env]) : @options[:env]
env = @options[:env].merge(options[:env] || {})
output = options[:output] || $stdout
if Foreman.windows?
Dir.chdir(cwd) do
expanded_command = command.dup
env.each do |key, val|
expanded_command.gsub!("$#{key}", val)
end
Process.spawn env, expanded_command, :out => output, :err => output
Process.spawn env, expanded_command(env), :out => output, :err => output
end
elsif Foreman.jruby?
elsif Foreman.jruby_18?
require "posix/spawn"
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
POSIX::Spawn.spawn env, wrapped_command, :out => output, :err => output
@@ -52,7 +62,7 @@ class Foreman::Process
$stderr.reopen output
env.each { |k,v| ENV[k] = v }
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
exec wrapped_command
Kernel.exec wrapped_command
end
else
wrapped_command = "#{Foreman.runner} -d '#{cwd}' -p -- #{command}"
@@ -60,6 +70,20 @@ class Foreman::Process
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+
#
# @param [String] signal The signal to send

View File

@@ -82,7 +82,7 @@ class Foreman::Procfile
private
def parse(filename)
File.read(filename).split("\n").map do |line|
File.read(filename).gsub("\r\n","\n").split("\n").map do |line|
if line =~ /^([A-Za-z0-9_]+):\s*(.+)$/
[$1, $2]
end

View File

@@ -1,5 +1,5 @@
module Foreman
VERSION = "0.59.0"
VERSION = "0.61.0"
end

View File

@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "FOREMAN" "1" "July 2012" "Foreman 0.57.0" "Foreman Manual"
.TH "FOREMAN" "1" "October 2012" "" ""
.
.SH "NAME"
\fBforeman\fR \- manage Procfile\-based applications
@@ -90,7 +90,7 @@ Specify the user the application should be run as\. Defaults to the app name
These options control all modes of foreman\'s operation\.
.
.TP
\fB\-d\fR, \fB\-\-directory\fR
\fB\-d\fR, \fB\-\-root\fR
Specify an alternate application root\. This defaults to the directory containing the Procfile\.
.
.TP

View File

@@ -84,7 +84,7 @@ The following options control how the application is run:
These options control all modes of foreman's operation.
* `-d`, `--directory`:
* `-d`, `--root`:
Specify an alternate application root. This defaults to the directory
containing the Procfile.

View File

@@ -73,6 +73,10 @@ describe "Foreman::CLI", :fakefs do
forked_foreman("run #{resource_path("bin/env FOO")} -e #{resource_path(".env")}").should == "bar\n"
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

View File

@@ -38,7 +38,7 @@ describe Foreman::Export::Upstart, :fakefs do
engine.env['KEY'] = 'd"\|d'
upstart.export
"foobarfoo".should include "bar"
File.read("/tmp/init/app-alpha-1.conf").should =~ /KEY="d\\"\\\\\\\|d/
File.read("/tmp/init/app-alpha-1.conf").should =~ /KEY=d\\"\\\\\\\|d/
end
context "with a formation" do

View File

@@ -8,7 +8,7 @@ stdout_logfile=/var/log/app/alpha-1.log
stderr_logfile=/var/log/app/alpha-1.error.log
user=app
directory=/tmp/app
environment=PORT="5000"
environment=PORT=5000
[program:app-bravo-1]
command=./bravo
autostart=true
@@ -18,7 +18,7 @@ stdout_logfile=/var/log/app/bravo-1.log
stderr_logfile=/var/log/app/bravo-1.error.log
user=app
directory=/tmp/app
environment=PORT="5100"
environment=PORT=5100
[group:app]
programs=app-alpha-1,app-bravo-1

View File

@@ -8,7 +8,7 @@ stdout_logfile=/var/log/app/alpha-1.log
stderr_logfile=/var/log/app/alpha-1.error.log
user=app
directory=/tmp/app
environment=PORT="5000"
environment=PORT=5000
[program:app-alpha-2]
command=./alpha
autostart=true
@@ -18,7 +18,7 @@ stdout_logfile=/var/log/app/alpha-2.log
stderr_logfile=/var/log/app/alpha-2.error.log
user=app
directory=/tmp/app
environment=PORT="5001"
environment=PORT=5001
[group:app]
programs=app-alpha-1,app-alpha-2

View File

@@ -1,5 +1,3 @@
require "rubygems"
require "simplecov"
SimpleCov.start do
add_filter "/spec/"