Compare commits

...
12 Commits
10 changed files with 115 additions and 9 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
PATH PATH
remote: . remote: .
specs: specs:
foreman (0.31.0) foreman (0.32.0)
term-ansicolor (~> 1.0.5) term-ansicolor (~> 1.0.5)
thor (>= 0.13.6) thor (>= 0.13.6)
+2 -1
View File
@@ -20,7 +20,8 @@ http://blog.daviddollar.org/2011/05/06/introducing-foreman.html
## Manual ## Manual
See the [man page](http://ddollar.github.com/foreman) for usage. * [man page](http://ddollar.github.com/foreman)
* [wiki](http://github.com/ddollar/foreman/wiki)
## Authorship ## Authorship
+2 -2
View File
@@ -1,2 +1,2 @@
#!/bin/sh #!/usr/bin/env ruby
exec $1 2>&1 exec "#{ARGV.join(' ')} 2>&1"
+23 -3
View File
@@ -5,15 +5,23 @@ require "thor"
require "yaml" require "yaml"
class Foreman::CLI < Thor class Foreman::CLI < Thor
class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile" class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile"
desc "start", "Start the application" desc "start", "Start the application"
method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env" method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
method_option :port, :type => :numeric, :aliases => "-p" method_option :port, :type => :numeric, :aliases => "-p"
method_option :concurrency, :type => :string, :aliases => "-c", :banner => '"alpha=5,bar=3"' method_option :concurrency, :type => :string, :aliases => "-c", :banner => '"alpha=5,bar=3"'
class << self
# Hackery. Take the run method away from Thor so that we can redefine it.
def is_thor_reserved_word?(word, type)
return false if word == 'run'
super
end
end
def start def start
check_procfile! check_procfile!
engine.start engine.start
@@ -53,7 +61,20 @@ class Foreman::CLI < Thor
error "no processes defined" unless engine.procfile.entries.length > 0 error "no processes defined" unless engine.procfile.entries.length > 0
display "valid procfile detected (#{engine.procfile.process_names.join(', ')})" display "valid procfile detected (#{engine.procfile.process_names.join(', ')})"
end end
desc "run COMMAND", "Run a command using your application's environment"
def run(*args)
engine.apply_environment!
begin
exec args.join(" ")
rescue Errno::EACCES
error "not executable: #{args.first}"
rescue Errno::ENOENT
error "command not found: #{args.first}"
end
end
private ###################################################################### private ######################################################################
def check_procfile! def check_procfile!
@@ -87,5 +108,4 @@ private ######################################################################
defaults = YAML::load_file(".foreman") || {} defaults = YAML::load_file(".foreman") || {}
Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options)) Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options))
end end
end end
+7 -1
View File
@@ -72,10 +72,16 @@ private ######################################################################
def kill_all(signal="SIGTERM") def kill_all(signal="SIGTERM")
running_processes.each do |pid, process| running_processes.each do |pid, process|
info "sending #{signal} to pid #{pid}" info "sending #{signal} to pid #{pid}"
Process.kill(signal, pid) rescue Errno::ESRCH kill(signal, -pid) or kill(signal, pid)
end end
end end
def kill(signal, pid)
Process.kill signal, pid
rescue Errno::ESRCH
false
end
def terminate_gracefully def terminate_gracefully
info "sending SIGTERM to all processes" info "sending SIGTERM to all processes"
kill_all "SIGTERM" kill_all "SIGTERM"
+2
View File
@@ -30,11 +30,13 @@ private
def fork_with_io(command) def fork_with_io(command)
reader, writer = IO.pipe reader, writer = IO.pipe
pid = fork do pid = fork do
Process.setpgrp
trap("INT", "IGNORE") trap("INT", "IGNORE")
$stdout.reopen writer $stdout.reopen writer
reader.close reader.close
exec Foreman.runner, replace_command_env(command) exec Foreman.runner, replace_command_env(command)
end end
Process.detach pid
[ reader, pid ] [ reader, pid ]
end end
+1 -1
View File
@@ -1,5 +1,5 @@
module Foreman module Foreman
VERSION = "0.31.0" VERSION = "0.32.0"
end end
+49
View File
@@ -89,5 +89,54 @@ describe "Foreman::CLI" do
end end
end end
end end
describe "run" do
describe "with a valid Procfile" do
before { write_procfile }
describe "and a command" do
let(:command) { ["ls", "-l"] }
before(:each) do
stub(subject).exec
end
it "should load the environment file" do
write_env
preserving_env do
subject.run *command
ENV["FOO"].should == "bar"
end
ENV["FOO"].should be_nil
end
it "should runute the command as a string" do
mock(subject).exec(command.join(" "))
subject.run *command
end
end
describe "and a non-existent command" do
let(:command) { "iuhtngrglhulhdfg" }
it "should print an error" do
mock_error(subject, "command not found: #{command}") do
subject.run command
end
end
end
describe "and a non-executable command" do
let(:command) { __FILE__ }
it "should print an error" do
mock_error(subject, "not executable: #{command}") do
subject.run command
end
end
end
end
end
end end
+18
View File
@@ -0,0 +1,18 @@
require "spec_helper"
describe "spec helpers" do
describe "#preserving_env" do
after { ENV.delete "FOO" }
it "should remove added environment vars" do
preserving_env { ENV["FOO"] = "baz" }
ENV["FOO"].should == nil
end
it "should reset modified environment vars" do
ENV["FOO"] = "bar"
preserving_env { ENV["FOO"] = "baz"}
ENV["FOO"].should == "bar"
end
end
end
+10
View File
@@ -63,6 +63,16 @@ def example_export_file(filename)
data data
end end
def preserving_env
old_env = ENV.to_hash
begin
yield
ensure
ENV.clear
ENV.update(old_env)
end
end
RSpec.configure do |config| RSpec.configure do |config|
config.color_enabled = true config.color_enabled = true
config.include FakeFS::SpecHelpers config.include FakeFS::SpecHelpers