foreman 0.31.0 → 0.32.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -20,7 +20,8 @@ http://blog.daviddollar.org/2011/05/06/introducing-foreman.html
20
20
 
21
21
  ## Manual
22
22
 
23
- See the [man page](http://ddollar.github.com/foreman) for usage.
23
+ * [man page](http://ddollar.github.com/foreman)
24
+ * [wiki](http://github.com/ddollar/foreman/wiki)
24
25
 
25
26
  ## Authorship
26
27
 
data/bin/runner CHANGED
@@ -1,2 +1,2 @@
1
- #!/bin/sh
2
- exec $1 2>&1
1
+ #!/usr/bin/env ruby
2
+ exec "#{ARGV.join(' ')} 2>&1"
@@ -5,15 +5,23 @@ require "thor"
5
5
  require "yaml"
6
6
 
7
7
  class Foreman::CLI < Thor
8
-
8
+
9
9
  class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile"
10
-
10
+
11
11
  desc "start", "Start the application"
12
12
 
13
13
  method_option :env, :type => :string, :aliases => "-e", :desc => "Specify an environment file to load, defaults to .env"
14
14
  method_option :port, :type => :numeric, :aliases => "-p"
15
15
  method_option :concurrency, :type => :string, :aliases => "-c", :banner => '"alpha=5,bar=3"'
16
16
 
17
+ class << self
18
+ # Hackery. Take the run method away from Thor so that we can redefine it.
19
+ def is_thor_reserved_word?(word, type)
20
+ return false if word == 'run'
21
+ super
22
+ end
23
+ end
24
+
17
25
  def start
18
26
  check_procfile!
19
27
  engine.start
@@ -53,7 +61,20 @@ class Foreman::CLI < Thor
53
61
  error "no processes defined" unless engine.procfile.entries.length > 0
54
62
  display "valid procfile detected (#{engine.procfile.process_names.join(', ')})"
55
63
  end
56
-
64
+
65
+ desc "run COMMAND", "Run a command using your application's environment"
66
+
67
+ def run(*args)
68
+ engine.apply_environment!
69
+ begin
70
+ exec args.join(" ")
71
+ rescue Errno::EACCES
72
+ error "not executable: #{args.first}"
73
+ rescue Errno::ENOENT
74
+ error "command not found: #{args.first}"
75
+ end
76
+ end
77
+
57
78
  private ######################################################################
58
79
 
59
80
  def check_procfile!
@@ -87,5 +108,4 @@ private ######################################################################
87
108
  defaults = YAML::load_file(".foreman") || {}
88
109
  Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options))
89
110
  end
90
-
91
111
  end
@@ -72,10 +72,16 @@ private ######################################################################
72
72
  def kill_all(signal="SIGTERM")
73
73
  running_processes.each do |pid, process|
74
74
  info "sending #{signal} to pid #{pid}"
75
- Process.kill(signal, pid) rescue Errno::ESRCH
75
+ kill(signal, -pid) or kill(signal, pid)
76
76
  end
77
77
  end
78
78
 
79
+ def kill(signal, pid)
80
+ Process.kill signal, pid
81
+ rescue Errno::ESRCH
82
+ false
83
+ end
84
+
79
85
  def terminate_gracefully
80
86
  info "sending SIGTERM to all processes"
81
87
  kill_all "SIGTERM"
@@ -30,11 +30,13 @@ private
30
30
  def fork_with_io(command)
31
31
  reader, writer = IO.pipe
32
32
  pid = fork do
33
+ Process.setpgrp
33
34
  trap("INT", "IGNORE")
34
35
  $stdout.reopen writer
35
36
  reader.close
36
37
  exec Foreman.runner, replace_command_env(command)
37
38
  end
39
+ Process.detach pid
38
40
  [ reader, pid ]
39
41
  end
40
42
 
@@ -1,5 +1,5 @@
1
1
  module Foreman
2
2
 
3
- VERSION = "0.31.0"
3
+ VERSION = "0.32.0"
4
4
 
5
5
  end
@@ -89,5 +89,54 @@ describe "Foreman::CLI" do
89
89
  end
90
90
  end
91
91
  end
92
+
93
+ describe "run" do
94
+ describe "with a valid Procfile" do
95
+ before { write_procfile }
96
+
97
+ describe "and a command" do
98
+ let(:command) { ["ls", "-l"] }
99
+
100
+ before(:each) do
101
+ stub(subject).exec
102
+ end
103
+
104
+ it "should load the environment file" do
105
+ write_env
106
+ preserving_env do
107
+ subject.run *command
108
+ ENV["FOO"].should == "bar"
109
+ end
110
+
111
+ ENV["FOO"].should be_nil
112
+ end
113
+
114
+ it "should runute the command as a string" do
115
+ mock(subject).exec(command.join(" "))
116
+ subject.run *command
117
+ end
118
+ end
119
+
120
+ describe "and a non-existent command" do
121
+ let(:command) { "iuhtngrglhulhdfg" }
122
+
123
+ it "should print an error" do
124
+ mock_error(subject, "command not found: #{command}") do
125
+ subject.run command
126
+ end
127
+ end
128
+ end
129
+
130
+ describe "and a non-executable command" do
131
+ let(:command) { __FILE__ }
132
+
133
+ it "should print an error" do
134
+ mock_error(subject, "not executable: #{command}") do
135
+ subject.run command
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
92
141
 
93
142
  end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe "spec helpers" do
4
+ describe "#preserving_env" do
5
+ after { ENV.delete "FOO" }
6
+
7
+ it "should remove added environment vars" do
8
+ preserving_env { ENV["FOO"] = "baz" }
9
+ ENV["FOO"].should == nil
10
+ end
11
+
12
+ it "should reset modified environment vars" do
13
+ ENV["FOO"] = "bar"
14
+ preserving_env { ENV["FOO"] = "baz"}
15
+ ENV["FOO"].should == "bar"
16
+ end
17
+ end
18
+ end
@@ -63,6 +63,16 @@ def example_export_file(filename)
63
63
  data
64
64
  end
65
65
 
66
+ def preserving_env
67
+ old_env = ENV.to_hash
68
+ begin
69
+ yield
70
+ ensure
71
+ ENV.clear
72
+ ENV.update(old_env)
73
+ end
74
+ end
75
+
66
76
  RSpec.configure do |config|
67
77
  config.color_enabled = true
68
78
  config.include FakeFS::SpecHelpers
metadata CHANGED
@@ -1,63 +1,45 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: foreman
3
- version: !ruby/object:Gem::Version
4
- hash: 99
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.32.0
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 31
9
- - 0
10
- version: 0.31.0
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - David Dollar
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-01-04 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- type: :runtime
22
- requirement: &id001 !ruby/object:Gem::Requirement
12
+ date: 2012-01-12 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: term-ansicolor
16
+ requirement: &70189245337240 !ruby/object:Gem::Requirement
23
17
  none: false
24
- requirements:
18
+ requirements:
25
19
  - - ~>
26
- - !ruby/object:Gem::Version
27
- hash: 29
28
- segments:
29
- - 1
30
- - 0
31
- - 5
20
+ - !ruby/object:Gem::Version
32
21
  version: 1.0.5
33
- version_requirements: *id001
34
- prerelease: false
35
- name: term-ansicolor
36
- - !ruby/object:Gem::Dependency
37
22
  type: :runtime
38
- requirement: &id002 !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ version_requirements: *70189245337240
25
+ - !ruby/object:Gem::Dependency
26
+ name: thor
27
+ requirement: &70189245321980 !ruby/object:Gem::Requirement
39
28
  none: false
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- hash: 39
44
- segments:
45
- - 0
46
- - 13
47
- - 6
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
48
32
  version: 0.13.6
49
- version_requirements: *id002
33
+ type: :runtime
50
34
  prerelease: false
51
- name: thor
35
+ version_requirements: *70189245321980
52
36
  description: Process manager for applications with multiple components
53
37
  email: ddollar@gmail.com
54
- executables:
38
+ executables:
55
39
  - foreman
56
40
  extensions: []
57
-
58
41
  extra_rdoc_files: []
59
-
60
- files:
42
+ files:
61
43
  - bin/foreman
62
44
  - bin/runner
63
45
  - data/example/error
@@ -95,6 +77,7 @@ files:
95
77
  - spec/foreman/export_spec.rb
96
78
  - spec/foreman/process_spec.rb
97
79
  - spec/foreman_spec.rb
80
+ - spec/helper_spec.rb
98
81
  - spec/resources/export/bluepill/app.pill
99
82
  - spec/resources/export/runit/app-alpha-1-log-run
100
83
  - spec/resources/export/runit/app-alpha-1-run
@@ -112,36 +95,32 @@ files:
112
95
  - man/foreman.1
113
96
  homepage: http://github.com/ddollar/foreman
114
97
  licenses: []
115
-
116
98
  post_install_message:
117
99
  rdoc_options: []
118
-
119
- require_paths:
100
+ require_paths:
120
101
  - lib
121
- required_ruby_version: !ruby/object:Gem::Requirement
102
+ required_ruby_version: !ruby/object:Gem::Requirement
122
103
  none: false
123
- requirements:
124
- - - ">="
125
- - !ruby/object:Gem::Version
126
- hash: 3
127
- segments:
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ segments:
128
109
  - 0
129
- version: "0"
130
- required_rubygems_version: !ruby/object:Gem::Requirement
110
+ hash: -1641968407225152398
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
112
  none: false
132
- requirements:
133
- - - ">="
134
- - !ruby/object:Gem::Version
135
- hash: 3
136
- segments:
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ segments:
137
118
  - 0
138
- version: "0"
119
+ hash: -1641968407225152398
139
120
  requirements: []
140
-
141
121
  rubyforge_project:
142
122
  rubygems_version: 1.8.10
143
123
  signing_key:
144
124
  specification_version: 3
145
125
  summary: Process manager for applications with multiple components
146
126
  test_files: []
147
-