Compare commits
83 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
383c1f87af | ||
|
|
ce3003b026 | ||
|
|
e06f4b2f9e | ||
|
|
b721fd894e | ||
|
|
b8ea6fd4b3 | ||
|
|
dbda63263b | ||
|
|
93cdc31be0 | ||
|
|
4dfbe46690 | ||
|
|
0033f9caeb | ||
|
|
74839800a9 | ||
|
|
b75337e21e | ||
|
|
d94f941189 | ||
|
|
0b34f067cb | ||
|
|
dbe51832b0 | ||
|
|
3a2a53be95 | ||
|
|
b2bf95479e | ||
|
|
48f764e347 | ||
|
|
de62d0655e | ||
|
|
38aecff886 | ||
|
|
e4a3215257 | ||
|
|
c705b5fbef | ||
|
|
69216b4c5e | ||
|
|
5d2930745a | ||
|
|
8fc3d1ef24 | ||
|
|
d33e4fb0ed | ||
|
|
39b48b566f | ||
|
|
2f982ff9c7 | ||
|
|
1217ef1b56 | ||
|
|
c9943d70ec | ||
|
|
08dca57eb4 | ||
|
|
bb3377407a | ||
|
|
084b9493d1 | ||
|
|
279a251c78 | ||
|
|
a49ef286e8 | ||
|
|
0b3da59947 | ||
|
|
1f725dd68a | ||
|
|
2272f76479 | ||
|
|
cf4762071c | ||
|
|
d86b0bed1f | ||
|
|
12f825204b | ||
|
|
62c9d1db45 | ||
|
|
1127551369 | ||
|
|
8cb58b8517 | ||
|
|
d03e931b67 | ||
|
|
9ba2b32b36 | ||
|
|
cf5689a77a | ||
|
|
c23dbb79af | ||
|
|
7e55d8d3e2 | ||
|
|
d4f23d45a4 | ||
|
|
93fa1645e7 | ||
|
|
7bdada4a10 | ||
|
|
2b47d24ab7 | ||
|
|
24695348fb | ||
|
|
38b6482af5 | ||
|
|
501bc138c5 | ||
|
|
df8c05cd6c | ||
|
|
edcc4f3567 | ||
|
|
3759dbb463 | ||
|
|
b673931c05 | ||
|
|
137e43b040 | ||
|
|
79211d9bbf | ||
|
|
16d4b84a5d | ||
|
|
5ea4537046 | ||
|
|
d51433ff82 | ||
|
|
54ab74d305 | ||
|
|
e8b8f34f41 | ||
|
|
7535f1d3d8 | ||
|
|
3af0dfb4ae | ||
|
|
78547b8175 | ||
|
|
976fbc0bb0 | ||
|
|
28a9aa774f | ||
|
|
51f5ff3842 | ||
|
|
e1e18f62bb | ||
|
|
0a09117328 | ||
|
|
c3df12746f | ||
|
|
2ec6a23fb3 | ||
|
|
0d6b784de1 | ||
|
|
2dcd2c03db | ||
|
|
9d6d0bbb7d | ||
|
|
89c1314abe | ||
|
|
f33211d100 | ||
|
|
4317079bf3 | ||
|
|
c745c282c9 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
/.bundle
|
||||
/.rbenv-version
|
||||
/coverage
|
||||
/example/log/*
|
||||
/man/*.html
|
||||
|
||||
38
Changelog.md
38
Changelog.md
@@ -1,3 +1,41 @@
|
||||
## 0.42.0 (2012-04-18)
|
||||
|
||||
* Move read_environment to a public class method. [Phil Hagelberg]
|
||||
* Drop parka dependency [Phil Hagelberg]
|
||||
* add group support for supervisord [Raphael Randschau]
|
||||
* fix enviroment export [Raphael Randschau]
|
||||
|
||||
## 0.41.0 (2012-03-16)
|
||||
|
||||
* replace term-ansicolor with built-in colorization [David Dollar]
|
||||
* supervisord export template [Raphael Randschau]
|
||||
|
||||
## 0.40.0 (2012-02-24)
|
||||
|
||||
* support various quoting styles in .env [David Dollar]
|
||||
* remove load_env! as it's made unnecessary by foreman run [David Dollar]
|
||||
* Provide a useful error if `foreman check` fails to find a Procfile [R. Tyler Croy]
|
||||
* update docs [David Dollar]
|
||||
|
||||
## 0.39.0 (2012-02-07)
|
||||
|
||||
* rename bin/runner to bin/foreman-runner [David Dollar]
|
||||
* fix tgz release [David Dollar]
|
||||
* bundle update hpricot [John Firebaugh]
|
||||
* touch up .pkg release tasks [David Dollar]
|
||||
|
||||
## 0.38.0 (2012-02-02)
|
||||
|
||||
* bring back single process starting [David Dollar]
|
||||
* more attempts at getting ci working with jruby [David Dollar]
|
||||
* ignore .rbenv-version [David Dollar]
|
||||
* force to binary encoding if supported [David Dollar]
|
||||
|
||||
## 0.37.2 (2012-01-29)
|
||||
|
||||
* handle directories with spaces in runner [David Dollar]
|
||||
* update docs [David Dollar]
|
||||
|
||||
## 0.37.1 (2012-01-29)
|
||||
|
||||
* use binary pipes to better handle UTF-8 data [David Dollar]
|
||||
|
||||
5
Gemfile
5
Gemfile
@@ -11,14 +11,11 @@ platform :jruby do
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem 'parka'
|
||||
gem 'aws-s3'
|
||||
gem 'rake'
|
||||
gem 'ronn'
|
||||
gem 'fakefs', '~> 0.3.2'
|
||||
gem 'rr', '~> 1.0.2'
|
||||
gem 'rspec', '~> 2.0'
|
||||
gem 'ZenTest'
|
||||
gem 'aws-s3'
|
||||
gem "rubyzip"
|
||||
gem "simplecov", :require => false
|
||||
end
|
||||
|
||||
20
Gemfile.lock
20
Gemfile.lock
@@ -1,36 +1,27 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
foreman (0.37.2)
|
||||
term-ansicolor (~> 1.0.7)
|
||||
foreman (0.43.0)
|
||||
thor (>= 0.13.6)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
ZenTest (4.6.2)
|
||||
aws-s3 (0.6.2)
|
||||
builder
|
||||
mime-types
|
||||
xml-simple
|
||||
builder (3.0.0)
|
||||
crack (0.1.8)
|
||||
diff-lcs (1.1.3)
|
||||
fakefs (0.3.2)
|
||||
hpricot (0.8.2)
|
||||
hpricot (0.8.2-java)
|
||||
hpricot (0.8.6)
|
||||
hpricot (0.8.6-java)
|
||||
mime-types (1.16)
|
||||
multi_json (1.0.4)
|
||||
mustache (0.11.2)
|
||||
parka (0.6.2)
|
||||
crack
|
||||
rest-client
|
||||
thor
|
||||
posix-spawn (0.3.6)
|
||||
rake (0.9.2.2)
|
||||
rdiscount (1.6.5)
|
||||
rest-client (1.6.1)
|
||||
mime-types (>= 1.16)
|
||||
ronn (0.7.3)
|
||||
hpricot (>= 0.8.2)
|
||||
mustache (>= 0.7.0)
|
||||
@@ -44,12 +35,10 @@ GEM
|
||||
rspec-expectations (2.8.0)
|
||||
diff-lcs (~> 1.1.2)
|
||||
rspec-mocks (2.8.0)
|
||||
rubyzip (0.9.4)
|
||||
simplecov (0.5.4)
|
||||
multi_json (~> 1.0.3)
|
||||
simplecov-html (~> 0.5.3)
|
||||
simplecov-html (0.5.3)
|
||||
term-ansicolor (1.0.7)
|
||||
thor (0.14.6)
|
||||
win32console (1.3.0-x86-mingw32)
|
||||
xml-simple (1.0.15)
|
||||
@@ -60,16 +49,13 @@ PLATFORMS
|
||||
x86-mingw32
|
||||
|
||||
DEPENDENCIES
|
||||
ZenTest
|
||||
aws-s3
|
||||
fakefs (~> 0.3.2)
|
||||
foreman!
|
||||
parka
|
||||
posix-spawn (~> 0.3.6)
|
||||
rake
|
||||
ronn
|
||||
rr (~> 1.0.2)
|
||||
rspec (~> 2.0)
|
||||
rubyzip
|
||||
simplecov
|
||||
win32console (~> 1.3.0)
|
||||
|
||||
@@ -33,7 +33,7 @@ Manage Procfile-based applications
|
||||
David Dollar
|
||||
|
||||
#### Patches contributed by
|
||||
Adam Wiggins, Chris Continanza, Chris Lowder, Craig R Webster, Dan Farina, Dan Peterson, David Dollar, Fletcher Nichol, Florian Apolloner, Gabriel Burt, Gamaliel Toro, Greg Reinacker, Hugues Le Gendre, Hunter Nield, Iain Hecker, Jay Zeschin, Keith Rarick, Khaja Minhajuddin, Lincoln Stoll, Marcos Muino Garcia, Mark McGranaghan, Matt Griffin, Matt Haynes, Matthijs Langenberg, Michael Dwan, Michael van Rooijen, Mike Javorski, Nathan Broadbent, Nathan L Smith, Nick Zadrozny, Phil Hagelberg, Ricardo Chimal, Jr, Thom May, Tom Ward, brainopia, clifff, jc00ke
|
||||
[Contributor List](https://github.com/ddollar/foreman/contributors)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
2
Rakefile
2
Rakefile
@@ -1,6 +1,8 @@
|
||||
$:.unshift File.expand_path("../lib", __FILE__)
|
||||
require "foreman"
|
||||
|
||||
require "bundler/setup"
|
||||
|
||||
Dir[File.expand_path("../tasks/*.rake", __FILE__)].each do |task|
|
||||
load task
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
#/ Usage: runner [-d <dir>] <command>
|
||||
#/ Usage: foreman-runner [-d <dir>] <command>
|
||||
#/
|
||||
#/ Run a command with exec, optionally changing directory first
|
||||
|
||||
27
data/export/supervisord/app.conf.erb
Normal file
27
data/export/supervisord/app.conf.erb
Normal file
@@ -0,0 +1,27 @@
|
||||
<%
|
||||
app_names = []
|
||||
engine.procfile.entries.each do |process|
|
||||
next if (conc = self.concurrency[process.name]) < 1
|
||||
1.upto(self.concurrency[process.name]) do |num|
|
||||
port = engine.port_for(process, num, self.port)
|
||||
name = if (conc > 1); "#{process.name}-#{num}" else process.name; end
|
||||
environment = (engine.environment.map{ |var,env| %{#{var.upcase}="#{env}"} } + [%{PORT="#{port}"}])
|
||||
app_name = "#{app}-#{name}"
|
||||
app_names << app_name
|
||||
%>
|
||||
[program:<%= app_name %>]
|
||||
command=<%= process.command %>
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=<%= log_root %>/<%=process.name%>-<%=num%>-out.log
|
||||
stderr_logfile=<%= log_root %>/<%=process.name%>-<%=num%>-err.log
|
||||
user=<%= user %>
|
||||
directory=<%= engine.directory %>
|
||||
environment=<%= environment.join(',') %><%
|
||||
end
|
||||
end
|
||||
%>
|
||||
|
||||
[group:<%= app %>]
|
||||
programs=<%= app_names.join(',') %>
|
||||
2
dist/deb.rake
vendored
2
dist/deb.rake
vendored
@@ -4,7 +4,7 @@ file pkg("/apt-#{version}/foreman-#{version}.deb") => distribution_files("deb")
|
||||
assemble_distribution
|
||||
assemble_gems
|
||||
assemble resource("deb/foreman"), "bin/foreman", 0755
|
||||
File.chmod 0755, "bin/runner"
|
||||
File.chmod 0755, "bin/foreman-runner"
|
||||
end
|
||||
|
||||
assemble resource("deb/control"), "control"
|
||||
|
||||
4
dist/jruby.rake
vendored
4
dist/jruby.rake
vendored
@@ -1,5 +1,7 @@
|
||||
file pkg("foreman-#{version}-jruby.gem") => distribution_files do |t|
|
||||
sh "env PLATFORM=java gem build foreman.gemspec"
|
||||
Bundler.with_clean_env do
|
||||
sh "env PLATFORM=java gem build foreman.gemspec"
|
||||
end
|
||||
sh "mv foreman-#{version}-java.gem #{t.name}"
|
||||
end
|
||||
|
||||
|
||||
4
dist/mingw32.rake
vendored
4
dist/mingw32.rake
vendored
@@ -1,5 +1,7 @@
|
||||
file pkg("foreman-#{version}-mingw32.gem") => distribution_files do |t|
|
||||
sh "env PLATFORM=mingw32 gem build foreman.gemspec"
|
||||
Bundler.with_clean_env do
|
||||
sh "env PLATFORM=mingw32 gem build foreman.gemspec"
|
||||
end
|
||||
sh "mv foreman-#{version}-mingw32.gem #{t.name}"
|
||||
end
|
||||
|
||||
|
||||
15
dist/pkg.rake
vendored
15
dist/pkg.rake
vendored
@@ -13,7 +13,7 @@ file pkg("foreman-#{version}.pkg") => distribution_files do |t|
|
||||
|
||||
mkdir_p "pkg"
|
||||
mkdir_p "pkg/Resources"
|
||||
mkdir_p "pkg/foreman-#{version}.pkg"
|
||||
mkdir_p "pkg/foreman.pkg"
|
||||
|
||||
dist = File.read(resource("pkg/Distribution.erb"))
|
||||
dist = ERB.new(dist).result(binding)
|
||||
@@ -21,20 +21,21 @@ file pkg("foreman-#{version}.pkg") => distribution_files do |t|
|
||||
|
||||
dist = File.read(resource("pkg/PackageInfo.erb"))
|
||||
dist = ERB.new(dist).result(binding)
|
||||
File.open("pkg/foreman-#{version}.pkg/PackageInfo", "w") { |f| f.puts dist }
|
||||
File.open("pkg/foreman.pkg/PackageInfo", "w") { |f| f.puts dist }
|
||||
|
||||
mkdir_p "pkg/foreman-#{version}.pkg/Scripts"
|
||||
cp resource("pkg/postinstall"), "pkg/foreman-#{version}.pkg/Scripts/postinstall"
|
||||
chmod 0755, "pkg/foreman-#{version}.pkg/Scripts/postinstall"
|
||||
mkdir_p "pkg/foreman.pkg/Scripts"
|
||||
cp resource("pkg/postinstall"), "pkg/foreman.pkg/Scripts/postinstall"
|
||||
chmod 0755, "pkg/foreman.pkg/Scripts/postinstall"
|
||||
|
||||
sh %{ mkbom -s foreman pkg/foreman-#{version}.pkg/Bom }
|
||||
sh %{ mkbom -s foreman pkg/foreman.pkg/Bom }
|
||||
|
||||
Dir.chdir("foreman") do
|
||||
sh %{ pax -wz -x cpio . > ../pkg/foreman-#{version}.pkg/Payload }
|
||||
sh %{ pax -wz -x cpio . > ../pkg/foreman.pkg/Payload }
|
||||
end
|
||||
|
||||
sh %{ pkgutil --flatten pkg foreman-#{version}.pkg }
|
||||
|
||||
FileUtils.mkdir_p(File.dirname(t.name))
|
||||
cp_r "foreman-#{version}.pkg", t.name
|
||||
end
|
||||
end
|
||||
|
||||
6
dist/resources/pkg/Distribution.erb
vendored
6
dist/resources/pkg/Distribution.erb
vendored
@@ -10,14 +10,14 @@
|
||||
]]></script>
|
||||
<choices-outline>
|
||||
<line choice="git"/>
|
||||
<line choice="foreman-<%= version %>"/>
|
||||
<line choice="foreman"/>
|
||||
</choices-outline>
|
||||
<choice id="git" title="git" start_selected="false" start_enabled="false" selected="needs_git()" enabled="needs_git()">
|
||||
<pkg-ref id="git.pkg" />
|
||||
</choice>
|
||||
<choice id="foreman-<%= version %>" title="foreman">
|
||||
<choice id="foreman" title="foreman">
|
||||
<pkg-ref id="io.foreman.installer"/>
|
||||
</choice>
|
||||
<pkg-ref id="io.foreman.installer" installKBytes="<%= kbytes %>" version="<%= version %>" auth="Root">#foreman-<%= version %>.pkg</pkg-ref>
|
||||
<pkg-ref id="io.foreman.installer" installKBytes="<%= kbytes %>" version="<%= version %>" auth="Root">#foreman.pkg</pkg-ref>
|
||||
</installer-script>
|
||||
|
||||
|
||||
1
dist/resources/pkg/PackageInfo.erb
vendored
1
dist/resources/pkg/PackageInfo.erb
vendored
@@ -4,4 +4,3 @@
|
||||
<postinstall file="./postinstall"/>
|
||||
</scripts>
|
||||
</pkg-info>
|
||||
|
||||
|
||||
2
dist/tgz.rake
vendored
2
dist/tgz.rake
vendored
@@ -3,7 +3,7 @@ file pkg("foreman-#{version}.tgz") => distribution_files do |t|
|
||||
mkchdir("foreman") do
|
||||
assemble_distribution
|
||||
assemble_gems
|
||||
rm_rf "bin"
|
||||
rm_f "bin/foreman"
|
||||
assemble resource("tgz/foreman"), "foreman", 0755
|
||||
end
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@ Gem::Specification.new do |gem|
|
||||
gem.files = Dir["**/*"].select { |d| d =~ %r{^(README|bin/|data/|ext/|lib/|spec/|test/)} }
|
||||
gem.files << "man/foreman.1"
|
||||
|
||||
gem.add_dependency 'term-ansicolor', '~> 1.0.7'
|
||||
gem.add_dependency 'thor', '>= 0.13.6'
|
||||
gem.add_dependency 'thor', '>= 0.13.6'
|
||||
|
||||
if ENV["PLATFORM"] == "java"
|
||||
gem.add_dependency "posix-spawn", "~> 0.3.6"
|
||||
|
||||
@@ -4,14 +4,8 @@ module Foreman
|
||||
|
||||
class AppDoesNotExist < Exception; end
|
||||
|
||||
# load contents of env_file into ENV
|
||||
def self.load_env!(env_file = './.env')
|
||||
require 'foreman/engine'
|
||||
Foreman::Engine.load_env!(env_file)
|
||||
end
|
||||
|
||||
def self.runner
|
||||
File.expand_path("../../bin/runner", __FILE__)
|
||||
File.expand_path("../../bin/foreman-runner", __FILE__)
|
||||
end
|
||||
|
||||
def self.jruby?
|
||||
|
||||
@@ -10,7 +10,7 @@ class Foreman::CLI < Thor
|
||||
|
||||
class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile"
|
||||
|
||||
desc "start", "Start the application"
|
||||
desc "start [PROCESS]", "Start the application (or a specific PROCESS)"
|
||||
|
||||
class_option :procfile, :type => :string, :aliases => "-f", :desc => "Default: Procfile"
|
||||
class_option :app_root, :type => :string, :aliases => "-d", :desc => "Default: Procfile directory"
|
||||
@@ -27,8 +27,9 @@ class Foreman::CLI < Thor
|
||||
end
|
||||
end
|
||||
|
||||
def start
|
||||
def start(process=nil)
|
||||
check_procfile!
|
||||
engine.options[:concurrency] = "#{process}=1" if process
|
||||
engine.start
|
||||
end
|
||||
|
||||
@@ -53,6 +54,7 @@ class Foreman::CLI < Thor
|
||||
desc "check", "Validate your application's Procfile"
|
||||
|
||||
def check
|
||||
check_procfile!
|
||||
error "no processes defined" unless engine.procfile.entries.length > 0
|
||||
puts "valid procfile detected (#{engine.procfile.process_names.join(', ')})"
|
||||
end
|
||||
|
||||
40
lib/foreman/color.rb
Normal file
40
lib/foreman/color.rb
Normal file
@@ -0,0 +1,40 @@
|
||||
require "foreman"
|
||||
|
||||
module Foreman::Color
|
||||
|
||||
ANSI = {
|
||||
:reset => 0,
|
||||
:black => 30,
|
||||
:red => 31,
|
||||
:green => 32,
|
||||
:yellow => 33,
|
||||
:blue => 34,
|
||||
:magenta => 35,
|
||||
:cyan => 36,
|
||||
:white => 37,
|
||||
:bright_black => 30,
|
||||
:bright_red => 31,
|
||||
:bright_green => 32,
|
||||
:bright_yellow => 33,
|
||||
:bright_blue => 34,
|
||||
:bright_magenta => 35,
|
||||
:bright_cyan => 36,
|
||||
:bright_white => 37,
|
||||
}
|
||||
|
||||
def self.enable(io)
|
||||
io.extend(self)
|
||||
end
|
||||
|
||||
def color?
|
||||
return false unless self.respond_to?(:isatty)
|
||||
self.isatty && ENV["TERM"]
|
||||
end
|
||||
|
||||
def color(name)
|
||||
return "" unless color?
|
||||
return "" unless ansi = ANSI[name.to_sym]
|
||||
"\e[#{ansi}m"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,38 +1,33 @@
|
||||
require "foreman"
|
||||
require "foreman/color"
|
||||
require "foreman/process"
|
||||
require "foreman/procfile"
|
||||
require "foreman/utils"
|
||||
require "tempfile"
|
||||
require "timeout"
|
||||
require "term/ansicolor"
|
||||
require "fileutils"
|
||||
require "thread"
|
||||
|
||||
class Foreman::Engine
|
||||
|
||||
attr_reader :environment
|
||||
attr_reader :procfile
|
||||
attr_reader :directory
|
||||
attr_reader :options
|
||||
|
||||
extend Term::ANSIColor
|
||||
COLORS = %w( cyan yellow green magenta red blue intense_cyan intense_yellow
|
||||
intense_green intense_magenta intense_red, intense_blue )
|
||||
|
||||
COLORS = [ cyan, yellow, green, magenta, red, blue,
|
||||
intense_cyan, intense_yellow, intense_green, intense_magenta,
|
||||
intense_red, intense_blue ]
|
||||
Foreman::Color.enable($stdout)
|
||||
|
||||
def initialize(procfile, options={})
|
||||
@procfile = Foreman::Procfile.new(procfile)
|
||||
@directory = options[:app_root] || File.expand_path(File.dirname(procfile))
|
||||
@options = options
|
||||
@options = options.dup
|
||||
@environment = read_environment_files(options[:env])
|
||||
@output_mutex = Mutex.new
|
||||
end
|
||||
|
||||
def self.load_env!(env_file)
|
||||
@environment = read_environment_files(env_file)
|
||||
apply_environment!
|
||||
end
|
||||
|
||||
def start
|
||||
proctitle "ruby: foreman master"
|
||||
termtitle "#{File.basename(@directory)} - foreman"
|
||||
@@ -52,6 +47,26 @@ class Foreman::Engine
|
||||
base_port.to_i + offset + num - 1
|
||||
end
|
||||
|
||||
def apply_environment!
|
||||
environment.each { |k,v| ENV[k] = v }
|
||||
end
|
||||
|
||||
def self.read_environment(filename)
|
||||
return {} unless File.exists?(filename)
|
||||
|
||||
File.read(filename).split("\n").inject({}) do |hash, line|
|
||||
if line =~ /\A([A-Za-z_0-9]+)=(.*)\z/
|
||||
key, val = [$1, $2]
|
||||
case val
|
||||
when /\A'(.*)'\z/ then hash[key] = $1
|
||||
when /\A"(.*)"\z/ then hash[key] = $1.gsub(/\\(.)/, '\1')
|
||||
else hash[key] = val
|
||||
end
|
||||
end
|
||||
hash
|
||||
end
|
||||
end
|
||||
|
||||
private ######################################################################
|
||||
|
||||
def spawn_processes
|
||||
@@ -99,6 +114,7 @@ private ######################################################################
|
||||
(rs || []).each do |r|
|
||||
data = r.gets
|
||||
next unless data
|
||||
data.force_encoding("BINARY") if data.respond_to?(:force_encoding)
|
||||
ps, message = data.split(",", 2)
|
||||
color = colors[ps.split(".").first]
|
||||
info message, ps, color
|
||||
@@ -127,11 +143,11 @@ private ######################################################################
|
||||
rescue Errno::ECHILD
|
||||
end
|
||||
|
||||
def info(message, name="system", color=Term::ANSIColor.white)
|
||||
def info(message, name="system", color=:white)
|
||||
output = ""
|
||||
output += color
|
||||
output += $stdout.color(color)
|
||||
output += "#{Time.now.strftime("%H:%M:%S")} #{pad_process_name(name)} | "
|
||||
output += Term::ANSIColor.reset
|
||||
output += $stdout.color(:reset)
|
||||
output += message.chomp
|
||||
puts output
|
||||
end
|
||||
@@ -181,8 +197,8 @@ private ######################################################################
|
||||
end
|
||||
|
||||
def assign_colors
|
||||
procfile.entries.each do |entry|
|
||||
colors[entry.name] = next_color
|
||||
procfile.entries.each_with_index do |entry, idx|
|
||||
colors[entry.name] = COLORS[idx % COLORS.length]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -190,49 +206,15 @@ private ######################################################################
|
||||
readers.invert[reader]
|
||||
end
|
||||
|
||||
def next_color
|
||||
@current_color ||= -1
|
||||
@current_color += 1
|
||||
@current_color = 0 if COLORS.length < @current_color
|
||||
COLORS[@current_color]
|
||||
def read_environment_files(filenames)
|
||||
environment = {}
|
||||
|
||||
(filenames || "").split(",").map(&:strip).each do |filename|
|
||||
error "No such file: #{filename}" unless File.exists?(filename)
|
||||
environment.merge!(Foreman::Engine.read_environment(filename))
|
||||
end
|
||||
|
||||
environment.merge!(Foreman::Engine.read_environment(".env")) unless filenames
|
||||
environment
|
||||
end
|
||||
|
||||
module Env
|
||||
attr_reader :environment
|
||||
|
||||
def read_environment_files(filenames)
|
||||
environment = {}
|
||||
|
||||
(filenames || "").split(",").map(&:strip).each do |filename|
|
||||
error "No such file: #{filename}" unless File.exists?(filename)
|
||||
environment.merge!(read_environment(filename))
|
||||
end
|
||||
|
||||
environment.merge!(read_environment(".env")) unless filenames
|
||||
environment
|
||||
end
|
||||
|
||||
def read_environment(filename)
|
||||
return {} unless File.exists?(filename)
|
||||
|
||||
File.read(filename).split("\n").inject({}) do |hash, line|
|
||||
if line =~ /\A([A-Za-z_0-9]+)=(.*)\z/
|
||||
hash[$1] = $2
|
||||
end
|
||||
hash
|
||||
end
|
||||
end
|
||||
|
||||
def apply_environment!
|
||||
@environment.each { |k,v| ENV[k] = v }
|
||||
end
|
||||
|
||||
def error(message)
|
||||
puts "ERROR: #{message}"
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
include Env
|
||||
extend Env
|
||||
end
|
||||
|
||||
@@ -30,3 +30,5 @@ require "foreman/export/inittab"
|
||||
require "foreman/export/upstart"
|
||||
require "foreman/export/bluepill"
|
||||
require "foreman/export/runit"
|
||||
require "foreman/export/supervisord"
|
||||
|
||||
|
||||
26
lib/foreman/export/supervisord.rb
Normal file
26
lib/foreman/export/supervisord.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
require "erb"
|
||||
require "foreman/export"
|
||||
|
||||
class Foreman::Export::Supervisord < Foreman::Export::Base
|
||||
|
||||
def export
|
||||
error("Must specify a location") unless location
|
||||
|
||||
FileUtils.mkdir_p location
|
||||
|
||||
app = self.app || File.basename(engine.directory)
|
||||
user = self.user || app
|
||||
log_root = self.log || "/var/log/#{app}"
|
||||
template_root = self.template
|
||||
|
||||
Dir["#{location}/#{app}*.conf"].each do |file|
|
||||
say "cleaning up: #{file}"
|
||||
FileUtils.rm(file)
|
||||
end
|
||||
|
||||
app_template = export_template("supervisord", "app.conf.erb", template_root)
|
||||
app_config = ERB.new(app_template, 0, '<').result(binding)
|
||||
write_file "#{location}/#{app}.conf", app_config
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,5 +1,5 @@
|
||||
module Foreman
|
||||
|
||||
VERSION = "0.37.2"
|
||||
VERSION = "0.43.0"
|
||||
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.\" generated with Ronn/v0.7.3
|
||||
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
||||
.
|
||||
.TH "FOREMAN" "1" "January 2012" "Foreman 0.37.1" "Foreman Manual"
|
||||
.TH "FOREMAN" "1" "February 2012" "Foreman 0.42.0" "Foreman Manual"
|
||||
.
|
||||
.SH "NAME"
|
||||
\fBforeman\fR \- manage Procfile\-based applications
|
||||
@@ -10,10 +10,13 @@
|
||||
\fBforeman start [process]\fR
|
||||
.
|
||||
.br
|
||||
\fBforeman run <command>\fR
|
||||
.
|
||||
.br
|
||||
\fBforeman export <format> [location]\fR
|
||||
.
|
||||
.SH "DESCRIPTION"
|
||||
\fBForeman\fR is a manager for Procfile\-based applications\. Its aim is to abstract away the details of the Procfile format, and allow you to either run your application directly or export it to some other process management format\.
|
||||
Foreman is a manager for Procfile\-based applications\. Its aim is to abstract away the details of the Procfile format, and allow you to either run your application directly or export it to some other process management format\.
|
||||
.
|
||||
.SH "RUNNING"
|
||||
\fBforeman start\fR is used to run your application directly from the command line\.
|
||||
@@ -35,6 +38,9 @@ Specify the number of each process type to run\. The value passed in should be i
|
||||
\fB\-p\fR, \fB\-\-port\fR
|
||||
Specify which port to use as the base for this application\. Should be a multiple of 1000\.
|
||||
.
|
||||
.P
|
||||
\fBforeman run\fR is used to run one\-off commands using the same environment as your defined processes\.
|
||||
.
|
||||
.SH "EXPORTING"
|
||||
\fBforeman export\fR is used to export your application to another process management format\.
|
||||
.
|
||||
@@ -61,10 +67,14 @@ Specify the directory to place process logs in\.
|
||||
Specify which port to use as the base for this application\. Should be a multiple of 1000\.
|
||||
.
|
||||
.TP
|
||||
\fB\-t\fR, \fB\-\-template\fR
|
||||
Specify an alternate template to use for creating export files\. See \fIhttps://github\.com/ddollar/foreman/tree/master/data/export\fR for examples\.
|
||||
.
|
||||
.TP
|
||||
\fB\-u\fR, \fB\-\-user\fR
|
||||
Specify the user the application should be run as\. Defaults to the app name
|
||||
.
|
||||
.SH "OPTIONS"
|
||||
.SH "GLOBAL OPTIONS"
|
||||
These options control all modes of foreman\'s operation\.
|
||||
.
|
||||
.TP
|
||||
|
||||
@@ -4,11 +4,12 @@ foreman(1) -- manage Procfile-based applications
|
||||
## SYNOPSIS
|
||||
|
||||
`foreman start [process]`<br>
|
||||
`foreman run <command>`<br>
|
||||
`foreman export <format> [location]`
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
**Foreman** is a manager for Procfile-based applications. Its aim is to
|
||||
Foreman is a manager for Procfile-based applications. Its aim is to
|
||||
abstract away the details of the Procfile format, and allow you to either run
|
||||
your application directly or export it to some other process management
|
||||
format.
|
||||
@@ -33,6 +34,9 @@ The following options control how the application is run:
|
||||
Specify which port to use as the base for this application. Should be
|
||||
a multiple of 1000.
|
||||
|
||||
`foreman run` is used to run one-off commands using the same environment
|
||||
as your defined processes.
|
||||
|
||||
## EXPORTING
|
||||
|
||||
`foreman export` is used to export your application to another process
|
||||
@@ -58,11 +62,15 @@ The following options control how the application is run:
|
||||
Specify which port to use as the base for this application. Should be
|
||||
a multiple of 1000.
|
||||
|
||||
* `-t`, `--template`:
|
||||
Specify an alternate template to use for creating export files.
|
||||
See <https://github.com/ddollar/foreman/tree/master/data/export> for examples.
|
||||
|
||||
* `-u`, `--user`:
|
||||
Specify the user the application should be run as. Defaults to the
|
||||
app name
|
||||
|
||||
## OPTIONS
|
||||
## GLOBAL OPTIONS
|
||||
|
||||
These options control all modes of foreman's operation.
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ require "foreman/cli"
|
||||
|
||||
describe "Foreman::CLI", :fakefs do
|
||||
subject { Foreman::CLI.new }
|
||||
let(:engine) { subject.send(:engine) }
|
||||
let(:entries) { engine.procfile.entries.inject({}) { |h,e| h.update(e.name => e) } }
|
||||
|
||||
describe "start" do
|
||||
describe "with a non-existent Procfile" do
|
||||
@@ -22,6 +24,15 @@ describe "Foreman::CLI", :fakefs do
|
||||
mock.instance_of(Foreman::Engine).start
|
||||
subject.start
|
||||
end
|
||||
|
||||
it "can run a single process" do
|
||||
dont_allow(subject).error
|
||||
stub(engine).watch_for_output
|
||||
stub(engine).watch_for_termination
|
||||
mock(entries["alpha"]).spawn(1, is_a(IO), engine.directory, {}, 5000) { [] }
|
||||
mock(entries["bravo"]).spawn(0, is_a(IO), engine.directory, {}, 5100) { [] }
|
||||
subject.start("alpha")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -109,6 +120,14 @@ describe "Foreman::CLI", :fakefs do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "without a Procfile" do
|
||||
it "displays an error" do
|
||||
mock_error(subject, "Procfile does not exist.") do
|
||||
subject.check
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "run" do
|
||||
|
||||
31
spec/foreman/color_spec.rb
Normal file
31
spec/foreman/color_spec.rb
Normal file
@@ -0,0 +1,31 @@
|
||||
require "spec_helper"
|
||||
require "foreman/color"
|
||||
|
||||
describe Foreman::Color do
|
||||
|
||||
let(:io) { Object.new }
|
||||
|
||||
it "should extend an object with colorization" do
|
||||
Foreman::Color.enable(io)
|
||||
io.should respond_to(:color)
|
||||
end
|
||||
|
||||
it "should not colorize if the object does not respond to isatty" do
|
||||
mock(io).respond_to?(:isatty) { false }
|
||||
Foreman::Color.enable(io)
|
||||
io.color(:white).should == ""
|
||||
end
|
||||
|
||||
it "should not colorize if the object is not a tty" do
|
||||
mock(io).isatty { false }
|
||||
Foreman::Color.enable(io)
|
||||
io.color(:white).should == ""
|
||||
end
|
||||
|
||||
it "should colorize if the object is a tty" do
|
||||
mock(io).isatty { true }
|
||||
Foreman::Color.enable(io)
|
||||
io.color(:white).should == "\e[37m"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -4,6 +4,13 @@ require "foreman/engine"
|
||||
describe "Foreman::Engine", :fakefs do
|
||||
subject { Foreman::Engine.new("Procfile", {}) }
|
||||
|
||||
before do
|
||||
any_instance_of(Foreman::Engine) do |engine|
|
||||
stub(engine).proctitle
|
||||
stub(engine).termtitle
|
||||
end
|
||||
end
|
||||
|
||||
describe "initialize" do
|
||||
describe "without an existing Procfile" do
|
||||
it "raises an error" do
|
||||
@@ -46,14 +53,16 @@ describe "Foreman::Engine", :fakefs do
|
||||
before(:each) do
|
||||
write_procfile
|
||||
stub(Process).fork
|
||||
any_instance_of(Foreman::Engine) do |engine|
|
||||
stub(engine).info
|
||||
stub(engine).spawn_processes
|
||||
stub(engine).watch_for_termination
|
||||
end
|
||||
end
|
||||
|
||||
it "should read if specified" do
|
||||
File.open("/tmp/env", "w") { |f| f.puts("FOO=baz") }
|
||||
engine = Foreman::Engine.new("Procfile", :env => "/tmp/env")
|
||||
stub(engine).info
|
||||
mock(engine).spawn_processes
|
||||
mock(engine).watch_for_termination
|
||||
engine.environment.should == {"FOO"=>"baz"}
|
||||
engine.start
|
||||
end
|
||||
@@ -62,13 +71,21 @@ describe "Foreman::Engine", :fakefs do
|
||||
File.open("/tmp/env1", "w") { |f| f.puts("FOO=bar") }
|
||||
File.open("/tmp/env2", "w") { |f| f.puts("BAZ=qux") }
|
||||
engine = Foreman::Engine.new("Procfile", :env => "/tmp/env1,/tmp/env2")
|
||||
stub(engine).info
|
||||
mock(engine).spawn_processes
|
||||
mock(engine).watch_for_termination
|
||||
engine.environment.should == { "FOO"=>"bar", "BAZ"=>"qux" }
|
||||
engine.start
|
||||
end
|
||||
|
||||
it "should handle quoted values" do
|
||||
File.open("/tmp/env", "w") do |f|
|
||||
f.puts 'FOO=bar'
|
||||
f.puts 'BAZ="qux"'
|
||||
f.puts "FRED='barney'"
|
||||
f.puts 'OTHER="escaped\"quote"'
|
||||
end
|
||||
engine = Foreman::Engine.new("Procfile", :env => "/tmp/env")
|
||||
engine.environment.should == { "FOO" => "bar", "BAZ" => "qux", "FRED" => "barney", "OTHER" => 'escaped"quote' }
|
||||
end
|
||||
|
||||
it "should fail if specified and doesnt exist" do
|
||||
mock.instance_of(Foreman::Engine).error("No such file: /tmp/env")
|
||||
engine = Foreman::Engine.new("Procfile", :env => "/tmp/env")
|
||||
@@ -77,8 +94,6 @@ describe "Foreman::Engine", :fakefs do
|
||||
it "should read .env if none specified" do
|
||||
File.open(".env", "w") { |f| f.puts("FOO=qoo") }
|
||||
engine = Foreman::Engine.new("Procfile")
|
||||
mock(engine).spawn_processes
|
||||
mock(engine).watch_for_termination
|
||||
engine.environment.should == {"FOO"=>"qoo"}
|
||||
engine.start
|
||||
end
|
||||
@@ -95,7 +110,7 @@ describe "Foreman::Engine", :fakefs do
|
||||
stub(subject).watch_for_output
|
||||
stub(subject).watch_for_termination
|
||||
subject.start
|
||||
sleep 1
|
||||
Process.waitall
|
||||
mock(subject).info(/started with pid \d+/, "utf8.1", anything)
|
||||
mock(subject).info("\xff\x03\n", "utf8.1", anything)
|
||||
subject.send(:poll_readers)
|
||||
|
||||
85
spec/foreman/export/supervisord_spec.rb
Normal file
85
spec/foreman/export/supervisord_spec.rb
Normal file
@@ -0,0 +1,85 @@
|
||||
require "spec_helper"
|
||||
require "foreman/engine"
|
||||
require "foreman/export/supervisord"
|
||||
require "tmpdir"
|
||||
|
||||
describe Foreman::Export::Supervisord, :fakefs do
|
||||
let(:procfile) { FileUtils.mkdir_p("/tmp/app"); write_procfile("/tmp/app/Procfile") }
|
||||
let(:engine) { Foreman::Engine.new(procfile) }
|
||||
let(:options) { Hash.new }
|
||||
let(:supervisord) { Foreman::Export::Supervisord.new("/tmp/init", engine, options) }
|
||||
|
||||
before(:each) { load_export_templates_into_fakefs("supervisord") }
|
||||
before(:each) { stub(supervisord).say }
|
||||
|
||||
it "exports to the filesystem" do
|
||||
supervisord.export
|
||||
|
||||
File.read("/tmp/init/app.conf").should == example_export_file("supervisord/app.conf")
|
||||
end
|
||||
|
||||
it "cleans up if exporting into an existing dir" do
|
||||
mock(FileUtils).rm("/tmp/init/app.conf")
|
||||
supervisord.export
|
||||
supervisord.export
|
||||
end
|
||||
|
||||
context "with concurrency" do
|
||||
let(:options) { Hash[:concurrency => "alpha=2"] }
|
||||
|
||||
it "exports to the filesystem with concurrency" do
|
||||
supervisord.export
|
||||
File.read("/tmp/init/app.conf").should == example_export_file("supervisord/app-alpha-2.conf")
|
||||
end
|
||||
end
|
||||
|
||||
context "with alternate templates" do
|
||||
let(:template_root) { "/tmp/alternate" }
|
||||
let(:supervisord) { Foreman::Export::Supervisord.new("/tmp/init", engine, :template => template_root) }
|
||||
|
||||
before do
|
||||
FileUtils.mkdir_p template_root
|
||||
File.open("#{template_root}/app.conf.erb", "w") { |f| f.puts "alternate_template" }
|
||||
end
|
||||
|
||||
it "can export with alternate template files" do
|
||||
supervisord.export
|
||||
File.read("/tmp/init/app.conf").should == "alternate_template\n"
|
||||
end
|
||||
end
|
||||
|
||||
context "with alternate templates from home dir" do
|
||||
let(:default_template_root) {File.expand_path("#{ENV['HOME']}/.foreman/templates")}
|
||||
|
||||
before do
|
||||
ENV['_FOREMAN_SPEC_HOME'] = ENV['HOME']
|
||||
ENV['HOME'] = "/home/appuser"
|
||||
FileUtils.mkdir_p default_template_root
|
||||
File.open("#{default_template_root}/app.conf.erb", "w") { |f| f.puts "default_alternate_template" }
|
||||
end
|
||||
|
||||
after do
|
||||
ENV['HOME'] = ENV.delete('_FOREMAN_SPEC_HOME')
|
||||
end
|
||||
|
||||
it "can export with alternate template files" do
|
||||
supervisord.export
|
||||
File.read("/tmp/init/app.conf").should == "default_alternate_template\n"
|
||||
end
|
||||
end
|
||||
|
||||
context "environment export" do
|
||||
it "correctly translates environment when exporting" do
|
||||
File.open("/tmp/supervisord_env", "w") { |f| f.puts("QUEUE=fastqueue,slowqueue\nVERBOSE=1") }
|
||||
|
||||
engine = Foreman::Engine.new(procfile,:env => "/tmp/supervisord_env")
|
||||
supervisor = Foreman::Export::Supervisord.new("/tmp/init", engine, options)
|
||||
stub(supervisor).say
|
||||
|
||||
supervisor.export
|
||||
|
||||
File.read("/tmp/init/app.conf").should == example_export_file("supervisord/app-env-with-comma.conf")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -8,24 +8,6 @@ describe Foreman do
|
||||
it { should be_a String }
|
||||
end
|
||||
|
||||
describe "::load_env!(env_file)", :fakefs do
|
||||
after do
|
||||
ENV['FOO'] = nil
|
||||
end
|
||||
|
||||
it "should load env_file into ENV" do
|
||||
File.open("/tmp/env1", "w") { |f| f.puts("FOO=bar") }
|
||||
Foreman.load_env!("/tmp/env1")
|
||||
ENV['FOO'].should == 'bar'
|
||||
end
|
||||
|
||||
it "should assume env_file in ./.env" do
|
||||
File.open("./.env", "w") { |f| f.puts("FOO=bar") }
|
||||
Foreman.load_env!
|
||||
ENV['FOO'].should == 'bar'
|
||||
end
|
||||
end
|
||||
|
||||
describe "runner" do
|
||||
it "should exist" do
|
||||
File.exists?(Foreman.runner).should == true
|
||||
|
||||
24
spec/resources/export/supervisord/app-alpha-2.conf
Normal file
24
spec/resources/export/supervisord/app-alpha-2.conf
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
[program:app-alpha-1]
|
||||
command=./alpha
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=/var/log/app/alpha-1-out.log
|
||||
stderr_logfile=/var/log/app/alpha-1-err.log
|
||||
user=app
|
||||
directory=/tmp/app
|
||||
environment=PORT="5000"
|
||||
[program:app-alpha-2]
|
||||
command=./alpha
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=/var/log/app/alpha-2-out.log
|
||||
stderr_logfile=/var/log/app/alpha-2-err.log
|
||||
user=app
|
||||
directory=/tmp/app
|
||||
environment=PORT="5001"
|
||||
|
||||
[group:app]
|
||||
programs=app-alpha-1,app-alpha-2
|
||||
24
spec/resources/export/supervisord/app-env-with-comma.conf
Normal file
24
spec/resources/export/supervisord/app-env-with-comma.conf
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
[program:app-alpha]
|
||||
command=./alpha
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=/var/log/app/alpha-1-out.log
|
||||
stderr_logfile=/var/log/app/alpha-1-err.log
|
||||
user=app
|
||||
directory=/tmp/app
|
||||
environment=QUEUE="fastqueue,slowqueue",VERBOSE="1",PORT="5000"
|
||||
[program:app-bravo]
|
||||
command=./bravo
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=/var/log/app/bravo-1-out.log
|
||||
stderr_logfile=/var/log/app/bravo-1-err.log
|
||||
user=app
|
||||
directory=/tmp/app
|
||||
environment=QUEUE="fastqueue,slowqueue",VERBOSE="1",PORT="5100"
|
||||
|
||||
[group:app]
|
||||
programs=app-alpha,app-bravo
|
||||
21
spec/resources/export/supervisord/app-env.conf
Normal file
21
spec/resources/export/supervisord/app-env.conf
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
[program:app-alpha]
|
||||
command=./alpha
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=/var/log/app/alpha-1-out.log
|
||||
stderr_logfile=/var/log/app/alpha-1-err.log
|
||||
user=app
|
||||
directory=/tmp/app
|
||||
environment=FOO="bar",PORT="5000"
|
||||
[program:app-bravo]
|
||||
command=./bravo
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=/var/log/app/bravo-1-out.log
|
||||
stderr_logfile=/var/log/app/bravo-1-err.log
|
||||
user=app
|
||||
directory=/tmp/app
|
||||
environment=FOO="bar",PORT="5100"
|
||||
24
spec/resources/export/supervisord/app.conf
Normal file
24
spec/resources/export/supervisord/app.conf
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
[program:app-alpha]
|
||||
command=./alpha
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=/var/log/app/alpha-1-out.log
|
||||
stderr_logfile=/var/log/app/alpha-1-err.log
|
||||
user=app
|
||||
directory=/tmp/app
|
||||
environment=PORT="5000"
|
||||
[program:app-bravo]
|
||||
command=./bravo
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopsignal=QUIT
|
||||
stdout_logfile=/var/log/app/bravo-1-out.log
|
||||
stderr_logfile=/var/log/app/bravo-1-err.log
|
||||
user=app
|
||||
directory=/tmp/app
|
||||
environment=PORT="5100"
|
||||
|
||||
[group:app]
|
||||
programs=app-alpha,app-bravo
|
||||
@@ -27,14 +27,6 @@ task :pages => "man:commit" do
|
||||
}
|
||||
end
|
||||
|
||||
desc "Generate an authors list"
|
||||
task :authors do
|
||||
authors = %x{ git log --pretty=format:"%an" | sort -u }.split("\n")
|
||||
readme = File.read("README.md")
|
||||
readme.gsub!(/#### Patches contributed by\n([^\n]*)\n/m, "#### Patches contributed by\n#{authors.join(", ")}\n")
|
||||
File.open("README.md", "w") { |f| f.print readme }
|
||||
end
|
||||
|
||||
def latest_release
|
||||
latest = File.read("Changelog.md").split("\n").first.split(" ")[1]
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user