foreman 0.27.0 → 0.28.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/bin/runner ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ exec $1 2>&1
@@ -3,7 +3,7 @@ Bluepill.application("<%= app %>", :foreground => false, :log_file => "/var/log/
3
3
  app.uid = "<%= user %>"
4
4
  app.gid = "<%= user %>"
5
5
 
6
- <% engine.processes.each do |process| %>
6
+ <% engine.procfile.entries.each do |process| %>
7
7
  <% 1.upto(concurrency[process.name]) do |num| %>
8
8
  <% port = engine.port_for(process, num, options[:port]) %>
9
9
  app.process("<%= process.name %>-<%=num%>") do |process|
@@ -19,7 +19,7 @@ Bluepill.application("<%= app %>", :foreground => false, :log_file => "/var/log/
19
19
  process.monitor_children do |children|
20
20
  children.stop_command "kill -QUIT {{PID}}"
21
21
  end
22
-
22
+
23
23
  process.group = "<%= app %>-<%= process.name %>"
24
24
  end
25
25
  <% end %>
data/lib/foreman.rb CHANGED
@@ -9,5 +9,10 @@ module Foreman
9
9
  require 'foreman/engine'
10
10
  Foreman::Engine.load_env!(env_file)
11
11
  end
12
+
13
+ def self.runner
14
+ File.expand_path("../../bin/runner", __FILE__)
15
+ end
16
+
12
17
  end
13
18
 
data/lib/foreman/cli.rb CHANGED
@@ -8,20 +8,15 @@ class Foreman::CLI < Thor
8
8
 
9
9
  class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile"
10
10
 
11
- desc "start [PROCESS]", "Start the application, or a specific process"
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
- def start(process=nil)
17
+ def start
18
18
  check_procfile!
19
-
20
- if process
21
- engine.execute(process)
22
- else
23
- engine.start
24
- end
19
+ engine.start
25
20
  end
26
21
 
27
22
  desc "export FORMAT LOCATION", "Export the application to another process management format"
@@ -55,8 +50,8 @@ class Foreman::CLI < Thor
55
50
  desc "check", "Validate your application's Procfile"
56
51
 
57
52
  def check
58
- error "no processes defined" unless engine.processes.length > 0
59
- display "valid procfile detected (#{engine.processes.map(&:name).join(', ')})"
53
+ error "no processes defined" unless engine.procfile.entries.length > 0
54
+ display "valid procfile detected (#{engine.procfile.process_names.join(', ')})"
60
55
  end
61
56
 
62
57
  private ######################################################################
@@ -23,6 +23,7 @@ class Foreman::Engine
23
23
  @directory = File.expand_path(File.dirname(procfile))
24
24
  @options = options
25
25
  @environment = read_environment_files(options[:env])
26
+ @output_mutex = Mutex.new
26
27
  end
27
28
 
28
29
  def self.load_env!(env_file)
@@ -32,34 +33,17 @@ class Foreman::Engine
32
33
 
33
34
  def start
34
35
  proctitle "ruby: foreman master"
35
- termtitle "#{File.basename(@directory)} - foreman (#{processes.size} processes)"
36
-
37
- processes.each do |process|
38
- process.color = next_color
39
- fork process
40
- end
41
-
42
- trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
43
- trap("INT") { puts "SIGINT received"; terminate_gracefully }
44
-
45
- watch_for_termination
46
- end
47
-
48
- def execute(name)
49
- error "no such process: #{name}" unless process = procfile[name]
50
- process.color = next_color
51
- fork process
36
+ termtitle "#{File.basename(@directory)} - foreman"
52
37
 
53
38
  trap("TERM") { puts "SIGTERM received"; terminate_gracefully }
54
39
  trap("INT") { puts "SIGINT received"; terminate_gracefully }
55
40
 
41
+ assign_colors
42
+ spawn_processes
43
+ watch_for_output
56
44
  watch_for_termination
57
45
  end
58
46
 
59
- def processes
60
- procfile.processes
61
- end
62
-
63
47
  def port_for(process, num, base_port=nil)
64
48
  base_port ||= 5000
65
49
  offset = procfile.process_names.index(process.name) * 100
@@ -68,47 +52,20 @@ class Foreman::Engine
68
52
 
69
53
  private ######################################################################
70
54
 
71
- def fork(process)
55
+ def spawn_processes
72
56
  concurrency = Foreman::Utils.parse_concurrency(@options[:concurrency])
73
57
 
74
- 1.upto(concurrency[process.name]) do |num|
75
- fork_individual(process, num, port_for(process, num, @options[:port]))
76
- end
77
- end
78
-
79
- def fork_individual(process, num, port)
80
- apply_environment!
81
-
82
- ENV["PORT"] = port.to_s
83
- ENV["PS"] = "#{process.name}.#{num}"
84
-
85
- pid = Process.fork do
86
- run(process)
58
+ procfile.entries.each do |entry|
59
+ reader, writer = IO.pipe
60
+ entry.spawn(concurrency[entry.name], writer, @directory, @environment, base_port).each do |process|
61
+ running_processes[process.pid] = process
62
+ readers[process] = reader
63
+ end
87
64
  end
88
-
89
- info "started with pid #{pid}", process
90
- running_processes[pid] = process
91
65
  end
92
66
 
93
- def run(process)
94
- proctitle "ruby: foreman #{process.name}"
95
- trap("SIGINT", "IGNORE")
96
-
97
- begin
98
- Dir.chdir directory do
99
- PTY.spawn(process.command) do |stdin, stdout, pid|
100
- trap("SIGTERM") { Process.kill("SIGTERM", pid) }
101
- until stdin.eof?
102
- info stdin.gets, process
103
- end
104
- end
105
- end
106
- rescue PTY::ChildExited, Interrupt, Errno::EIO, Errno::ENOENT
107
- begin
108
- info "process exiting", process
109
- rescue Interrupt
110
- end
111
- end
67
+ def base_port
68
+ options[:port] || 5000
112
69
  end
113
70
 
114
71
  def kill_all(signal="SIGTERM")
@@ -120,29 +77,59 @@ private ######################################################################
120
77
  def terminate_gracefully
121
78
  info "sending SIGTERM to all processes"
122
79
  kill_all "SIGTERM"
123
- Timeout.timeout(3) { Process.waitall }
80
+ Timeout.timeout(5) { Process.waitall }
124
81
  rescue Timeout::Error
125
82
  info "sending SIGKILL to all processes"
126
83
  kill_all "SIGKILL"
127
84
  end
128
85
 
86
+ def watch_for_output
87
+ Thread.new do
88
+ begin
89
+ loop do
90
+ rs, ws = IO.select(readers.values, [], [], 1)
91
+ (rs || []).each do |r|
92
+ ps, message = r.gets.split(",", 2)
93
+ color = colors[ps.split(".").first]
94
+ info message, ps, color
95
+ end
96
+ end
97
+ rescue Exception => ex
98
+ puts ex.message
99
+ puts ex.backtrace
100
+ end
101
+ end
102
+ end
103
+
129
104
  def watch_for_termination
130
105
  pid, status = Process.wait2
131
106
  process = running_processes.delete(pid)
132
- info "process terminated", process
107
+ info "process terminated", process.name
133
108
  terminate_gracefully
134
109
  kill_all
135
110
  rescue Errno::ECHILD
136
111
  end
137
112
 
138
- def info(message, process=nil)
139
- print process.color if process
140
- print "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(process)} | "
113
+ def info(message, name="system", color=Term::ANSIColor.white)
114
+ print color
115
+ print "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
141
116
  print Term::ANSIColor.reset
142
117
  print message.chomp
143
118
  puts
144
119
  end
145
120
 
121
+ def print(message=nil)
122
+ @output_mutex.synchronize do
123
+ $stdout.print message
124
+ end
125
+ end
126
+
127
+ def puts(message=nil)
128
+ @output_mutex.synchronize do
129
+ $stdout.puts message
130
+ end
131
+ end
132
+
146
133
  def error(message)
147
134
  puts "ERROR: #{message}"
148
135
  exit 1
@@ -156,9 +143,8 @@ private ######################################################################
156
143
  end
157
144
  end
158
145
 
159
- def pad_process_name(process)
160
- name = process ? "#{ENV["PS"]}" : "system"
161
- name.ljust(longest_process_name + 3) # add 3 for process number padding
146
+ def pad_process_name(name="system")
147
+ name.to_s.ljust(longest_process_name + 3) # add 3 for process number padding
162
148
  end
163
149
 
164
150
  def proctitle(title)
@@ -173,6 +159,24 @@ private ######################################################################
173
159
  @running_processes ||= {}
174
160
  end
175
161
 
162
+ def readers
163
+ @readers ||= {}
164
+ end
165
+
166
+ def colors
167
+ @colors ||= {}
168
+ end
169
+
170
+ def assign_colors
171
+ procfile.entries.each do |entry|
172
+ colors[entry.name] = next_color
173
+ end
174
+ end
175
+
176
+ def process_by_reader(reader)
177
+ readers.invert[reader]
178
+ end
179
+
176
180
  def next_color
177
181
  @current_color ||= -1
178
182
  @current_color += 1
@@ -12,7 +12,7 @@ class Foreman::Export::Inittab < Foreman::Export::Base
12
12
  inittab = []
13
13
  inittab << "# ----- foreman #{app} processes -----"
14
14
 
15
- engine.processes.inject(1) do |index, process|
15
+ engine.procfile.entries.inject(1) do |index, process|
16
16
  1.upto(concurrency[process.name]) do |num|
17
17
  id = app.slice(0, 2).upcase + sprintf("%02d", index)
18
18
  port = engine.port_for(process, num, options[:port])
@@ -3,58 +3,58 @@ require "foreman/export"
3
3
 
4
4
  class Foreman::Export::Runit < Foreman::Export::Base
5
5
  ENV_VARIABLE_REGEX = /([a-zA-Z_]+[a-zA-Z0-9_]*)=(\S+)/
6
-
6
+
7
7
  def export(location, options={})
8
8
  error("Must specify a location") unless location
9
-
9
+
10
10
  app = options[:app] || File.basename(engine.directory)
11
11
  user = options[:user] || app
12
12
  log_root = options[:log] || "/var/log/#{app}"
13
13
  template_root = options[:template]
14
-
14
+
15
15
  concurrency = Foreman::Utils.parse_concurrency(options[:concurrency])
16
-
16
+
17
17
  run_template = export_template('runit', 'run.erb', template_root)
18
18
  log_run_template = export_template('runit', 'log_run.erb', template_root)
19
19
 
20
- engine.processes.each do |process|
20
+ engine.procfile.entries.each do |process|
21
21
  1.upto(concurrency[process.name]) do |num|
22
22
  process_directory = "#{location}/#{app}-#{process.name}-#{num}"
23
23
  process_env_directory = "#{process_directory}/env"
24
24
  process_log_directory = "#{process_directory}/log"
25
-
25
+
26
26
  create_directory process_directory
27
27
  create_directory process_env_directory
28
28
  create_directory process_log_directory
29
-
29
+
30
30
  run = ERB.new(run_template).result(binding)
31
31
  write_file "#{process_directory}/run", run
32
-
32
+
33
33
  port = engine.port_for(process, num, options[:port])
34
34
  environment_variables = {'PORT' => port}.
35
35
  merge(engine.environment).
36
36
  merge(inline_variables(process.command))
37
-
37
+
38
38
  environment_variables.each_pair do |var, env|
39
39
  write_file "#{process_env_directory}/#{var.upcase}", env
40
40
  end
41
-
41
+
42
42
  log_run = ERB.new(log_run_template).result(binding)
43
43
  write_file "#{process_log_directory}/run", log_run
44
-
44
+
45
45
  end
46
46
  end
47
-
47
+
48
48
  end
49
-
49
+
50
50
  private
51
51
  def create_directory(location)
52
52
  say "creating: #{location}"
53
53
  FileUtils.mkdir(location)
54
54
  end
55
-
55
+
56
56
  def inline_variables(command)
57
- variable_name_regex =
57
+ variable_name_regex =
58
58
  Hash[*command.scan(ENV_VARIABLE_REGEX).flatten]
59
59
  end
60
- end
60
+ end
@@ -26,7 +26,7 @@ class Foreman::Export::Upstart < Foreman::Export::Base
26
26
 
27
27
  process_template = export_template("upstart", "process.conf.erb", template_root)
28
28
 
29
- engine.processes.each do |process|
29
+ engine.procfile.entries.each do |process|
30
30
  next if (conc = concurrency[process.name]) < 1
31
31
  process_master_template = export_template("upstart", "process_master.conf.erb", template_root)
32
32
  process_master_config = ERB.new(process_master_template).result(binding)
@@ -2,13 +2,58 @@ require "foreman"
2
2
 
3
3
  class Foreman::Process
4
4
 
5
- attr_reader :name
6
- attr_reader :command
7
- attr_accessor :color
5
+ attr_reader :entry
6
+ attr_reader :num
7
+ attr_reader :pid
8
+ attr_reader :port
8
9
 
9
- def initialize(name, command)
10
- @name = name
11
- @command = command
10
+ def initialize(entry, num, port)
11
+ @entry = entry
12
+ @num = num
13
+ @port = port
14
+ end
15
+
16
+ def run(pipe, basedir, environment)
17
+ Dir.chdir(basedir) do
18
+ with_environment(environment.merge("PORT" => port.to_s)) do
19
+ run_process entry.command
20
+ end
21
+ end
22
+ end
23
+
24
+ def name
25
+ "%s.%s" % [ entry.name, num ]
26
+ end
27
+
28
+ private
29
+
30
+ def run_process(command)
31
+ io = IO.popen([Foreman.runner, replace_command_env(command)], "w+")
32
+ @pid = io.pid
33
+ trap("SIGTERM") { "got sigterm for %d" % @pid }
34
+ output pipe, "started with pid %d" % @pid
35
+ Thread.new do
36
+ until io.eof?
37
+ output pipe, io.gets
38
+ end
39
+ end
40
+ end
41
+
42
+ def output(pipe, message)
43
+ pipe.puts "%s,%s" % [ name, message ]
44
+ end
45
+
46
+ def replace_command_env(command)
47
+ command.gsub(/\$(\w+)/) { |e| ENV[e[1..-1]] }
48
+ end
49
+
50
+ def with_environment(environment)
51
+ old_env = ENV.each_pair.inject({}) { |h,(k,v)| h.update(k => v) }
52
+ environment.each { |k,v| ENV[k] = v }
53
+ ret = yield
54
+ ENV.clear
55
+ old_env.each { |k,v| ENV[k] = v}
56
+ ret
12
57
  end
13
58
 
14
59
  end
@@ -1,4 +1,5 @@
1
1
  require "foreman"
2
+ require "foreman/procfile_entry"
2
3
 
3
4
  # A valid Procfile entry is captured by this regex.
4
5
  # All other lines are ignored.
@@ -10,18 +11,18 @@ require "foreman"
10
11
  #
11
12
  class Foreman::Procfile
12
13
 
13
- attr_reader :processes
14
+ attr_reader :entries
14
15
 
15
16
  def initialize(filename)
16
- @processes = parse_procfile(filename)
17
+ @entries = parse_procfile(filename)
17
18
  end
18
19
 
19
- def process_names
20
- processes.map(&:name)
20
+ def [](name)
21
+ entries.detect { |entry| entry.name == name }
21
22
  end
22
23
 
23
- def [](name)
24
- processes.detect { |process| process.name == name }
24
+ def process_names
25
+ entries.map(&:name)
25
26
  end
26
27
 
27
28
  private
@@ -29,7 +30,7 @@ private
29
30
  def parse_procfile(filename)
30
31
  File.read(filename).split("\n").map do |line|
31
32
  if line =~ /^([A-Za-z0-9_]+):\s*(.+)$/
32
- Foreman::Process.new($1, $2)
33
+ Foreman::ProcfileEntry.new($1, $2)
33
34
  end
34
35
  end.compact
35
36
  end
@@ -0,0 +1,22 @@
1
+ require "foreman"
2
+
3
+ class Foreman::ProcfileEntry
4
+
5
+ attr_reader :name
6
+ attr_reader :command
7
+ attr_accessor :color
8
+
9
+ def initialize(name, command)
10
+ @name = name
11
+ @command = command
12
+ end
13
+
14
+ def spawn(num, pipe, basedir, environment, base_port)
15
+ (1..num).to_a.map do |n|
16
+ process = Foreman::Process.new(self, n, base_port + (n-1))
17
+ process.run(pipe, basedir, environment)
18
+ process
19
+ end
20
+ end
21
+
22
+ end
@@ -1,5 +1,5 @@
1
1
  module Foreman
2
2
 
3
- VERSION = "0.27.0"
3
+ VERSION = "0.28.0.pre1"
4
4
 
5
5
  end
@@ -24,8 +24,9 @@ describe "Foreman::Engine" do
24
24
  describe "start" do
25
25
  it "forks the processes" do
26
26
  write_procfile
27
- mock(subject).fork(subject.procfile["alpha"])
28
- mock(subject).fork(subject.procfile["bravo"])
27
+ mock.instance_of(Foreman::Process).run_process("./alpha")
28
+ mock.instance_of(Foreman::Process).run_process("./bravo")
29
+ mock(subject).watch_for_output
29
30
  mock(subject).watch_for_termination
30
31
  subject.start
31
32
  end
@@ -33,29 +34,14 @@ describe "Foreman::Engine" do
33
34
  it "handles concurrency" do
34
35
  write_procfile
35
36
  engine = Foreman::Engine.new("Procfile",:concurrency => "alpha=2")
36
- mock(engine).fork_individual(engine.procfile["alpha"], 1, 5000)
37
- mock(engine).fork_individual(engine.procfile["alpha"], 2, 5001)
38
- mock(engine).fork_individual(engine.procfile["bravo"], 1, 5100)
37
+ mock.instance_of(Foreman::Process).run_process("./alpha").twice
38
+ mock.instance_of(Foreman::Process).run_process("./bravo")
39
+ mock(engine).watch_for_output
39
40
  mock(engine).watch_for_termination
40
41
  engine.start
41
42
  end
42
43
  end
43
44
 
44
- describe "execute" do
45
- it "runs the processes" do
46
- write_procfile
47
- mock(subject).fork(subject.procfile["alpha"])
48
- mock(subject).watch_for_termination
49
- subject.execute("alpha")
50
- end
51
-
52
- it "shows an error running a process that doesnt exist" do
53
- write_procfile
54
- mock(subject).puts("ERROR: no such process: foo")
55
- lambda { subject.execute("foo") }.should raise_error(SystemExit)
56
- end
57
- end
58
-
59
45
  describe "environment" do
60
46
  before(:each) do
61
47
  write_procfile
@@ -66,9 +52,10 @@ describe "Foreman::Engine" do
66
52
  File.open("/tmp/env", "w") { |f| f.puts("FOO=baz") }
67
53
  engine = Foreman::Engine.new("Procfile", :env => "/tmp/env")
68
54
  stub(engine).info
55
+ mock(engine).spawn_processes
69
56
  mock(engine).watch_for_termination
70
57
  engine.environment.should == {"FOO"=>"baz"}
71
- engine.execute("alpha")
58
+ engine.start
72
59
  end
73
60
 
74
61
  it "should read more than one if specified" do
@@ -76,9 +63,10 @@ describe "Foreman::Engine" do
76
63
  File.open("/tmp/env2", "w") { |f| f.puts("BAZ=qux") }
77
64
  engine = Foreman::Engine.new("Procfile", :env => "/tmp/env1,/tmp/env2")
78
65
  stub(engine).info
66
+ mock(engine).spawn_processes
79
67
  mock(engine).watch_for_termination
80
68
  engine.environment.should == { "FOO"=>"bar", "BAZ"=>"qux" }
81
- engine.execute("alpha")
69
+ engine.start
82
70
  end
83
71
 
84
72
  it "should fail if specified and doesnt exist" do
@@ -89,11 +77,10 @@ describe "Foreman::Engine" do
89
77
  it "should read .env if none specified" do
90
78
  File.open(".env", "w") { |f| f.puts("FOO=qoo") }
91
79
  engine = Foreman::Engine.new("Procfile")
92
- stub(engine).info
80
+ mock(engine).spawn_processes
93
81
  mock(engine).watch_for_termination
94
- mock(engine).fork_individual(anything, anything, anything)
95
82
  engine.environment.should == {"FOO"=>"qoo"}
96
- engine.execute("bravo")
83
+ engine.start
97
84
  end
98
85
  end
99
86
  end
@@ -13,8 +13,7 @@ describe Foreman::Export::Bluepill do
13
13
 
14
14
  it "exports to the filesystem" do
15
15
  bluepill.export("/tmp/init", :concurrency => "alpha=2")
16
-
17
16
  File.read("/tmp/init/app.pill").should == example_export_file("bluepill/app.pill")
18
17
  end
19
18
 
20
- end
19
+ end
@@ -19,7 +19,7 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
19
19
  process.monitor_children do |children|
20
20
  children.stop_command "kill -QUIT {{PID}}"
21
21
  end
22
-
22
+
23
23
  process.group = "app-alpha"
24
24
  end
25
25
 
@@ -37,7 +37,7 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
37
37
  process.monitor_children do |children|
38
38
  children.stop_command "kill -QUIT {{PID}}"
39
39
  end
40
-
40
+
41
41
  process.group = "app-alpha"
42
42
  end
43
43
 
@@ -57,7 +57,7 @@ Bluepill.application("app", :foreground => false, :log_file => "/var/log/bluepil
57
57
  process.monitor_children do |children|
58
58
  children.stop_command "kill -QUIT {{PID}}"
59
59
  end
60
-
60
+
61
61
  process.group = "app-bravo"
62
62
  end
63
63
 
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.0
5
- prerelease:
4
+ version: 0.28.0.pre1
5
+ prerelease: 7
6
6
  platform: ruby
7
7
  authors:
8
8
  - David Dollar
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-05 00:00:00.000000000Z
12
+ date: 2011-12-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: term-ansicolor
16
- requirement: &70283570808260 !ruby/object:Gem::Requirement
16
+ requirement: &70324999098260 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.0.5
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70283570808260
24
+ version_requirements: *70324999098260
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: thor
27
- requirement: &70283570807760 !ruby/object:Gem::Requirement
27
+ requirement: &70324999097620 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 0.13.6
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70283570807760
35
+ version_requirements: *70324999097620
36
36
  description: Process manager for applications with multiple components
37
37
  email: ddollar@gmail.com
38
38
  executables:
@@ -41,6 +41,7 @@ extensions: []
41
41
  extra_rdoc_files: []
42
42
  files:
43
43
  - bin/foreman
44
+ - bin/runner
44
45
  - data/example/error
45
46
  - data/example/log/neverdie.log
46
47
  - data/example/Procfile
@@ -63,6 +64,7 @@ files:
63
64
  - lib/foreman/export.rb
64
65
  - lib/foreman/process.rb
65
66
  - lib/foreman/procfile.rb
67
+ - lib/foreman/procfile_entry.rb
66
68
  - lib/foreman/utils.rb
67
69
  - lib/foreman/version.rb
68
70
  - lib/foreman.rb
@@ -104,16 +106,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
104
106
  version: '0'
105
107
  segments:
106
108
  - 0
107
- hash: -3613490576676930257
109
+ hash: 710611056517005467
108
110
  required_rubygems_version: !ruby/object:Gem::Requirement
109
111
  none: false
110
112
  requirements:
111
- - - ! '>='
113
+ - - ! '>'
112
114
  - !ruby/object:Gem::Version
113
- version: '0'
114
- segments:
115
- - 0
116
- hash: -3613490576676930257
115
+ version: 1.3.1
117
116
  requirements: []
118
117
  rubyforge_project:
119
118
  rubygems_version: 1.8.10