dist 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +49 -0
- data/Rakefile +1 -0
- data/bin/dist +29 -0
- data/dist.gemspec +19 -0
- data/lib/dependencies.yml +28 -0
- data/lib/dist.rb +9 -0
- data/lib/dist/builder.rb +206 -0
- data/lib/dist/configuration.rb +116 -0
- data/lib/dist/error.rb +11 -0
- data/lib/dist/package_computer.rb +82 -0
- data/lib/dist/version.rb +3 -0
- data/lib/dist/yaml_loader.rb +35 -0
- data/lib/gems.yml +17 -0
- data/lib/templates/config.erb +7 -0
- data/lib/templates/debian/config.erb +10 -0
- data/lib/templates/debian/control.erb +11 -0
- data/lib/templates/debian/postinst-db.erb +36 -0
- data/lib/templates/debian/postinst.erb +92 -0
- data/lib/templates/debian/postrm.erb +17 -0
- data/lib/templates/debian/prerm.erb +4 -0
- data/lib/templates/debian/templates.erb +14 -0
- data/lib/templates/logrotate.erb +9 -0
- data/lib/templates/upstart/main.erb +0 -0
- data/lib/templates/upstart/passenger.erb +13 -0
- data/lib/templates/upstart/service.erb +12 -0
- metadata +74 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 47c2058da7e8cd7faf4cc62f8e0d58cf9051fba7
|
4
|
+
data.tar.gz: 8bd348425978291120a8853007b8330a86a988e1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6a349d7c1e3a493ded27878a459b1bd3f4d6969f3c5adb02e6e1a35921239415fecea5f7aedb4478e5cebd8a30439b208fed96286baccff12b57f0c2c77217dc
|
7
|
+
data.tar.gz: c1f1ee8d6f1546637580ddc1de31dc892fe1df0b681a16ed0aec725644428b5c00476bdd0205f583a1d315fe395424fa0ad1afff98650778ae73335fd3771e8d
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Juan Wajnerman
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Dist
|
2
|
+
|
3
|
+
Generate packages to distribute Rails applications
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
$ gem install dist
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
In your Rails root, run:
|
12
|
+
|
13
|
+
$ dist
|
14
|
+
|
15
|
+
If it's the first time you run it, it will prompt you to run:
|
16
|
+
|
17
|
+
$ dist init
|
18
|
+
|
19
|
+
This will create a `config/dist.rb` file that contains some information about how to create the package.
|
20
|
+
|
21
|
+
A typical `config/dist.rb` file looks like this:
|
22
|
+
|
23
|
+
set :application, 'myrailsapp'
|
24
|
+
set :version, '1.0'
|
25
|
+
set :maintainer, 'John Doe <john@doe.com>'
|
26
|
+
set :description, 'My awesome Rails app'
|
27
|
+
set :summary, 'Demonstrates the usage of dist'
|
28
|
+
|
29
|
+
use :mail
|
30
|
+
|
31
|
+
## Settings
|
32
|
+
|
33
|
+
To prompt for settings while installing the package yo:
|
34
|
+
|
35
|
+
config :settings do
|
36
|
+
string :host, prompt: "Enter the host name"
|
37
|
+
end
|
38
|
+
|
39
|
+
This will prompt the user to enter a host name. The installer package will replace the key 'host' inside 'config/settings.yml' with the inputted value.
|
40
|
+
|
41
|
+
If settings.yml contains a 'production' key, 'host' will be replaced inside 'production'.
|
42
|
+
|
43
|
+
## Contributing
|
44
|
+
|
45
|
+
1. Fork it
|
46
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
47
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
48
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
49
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/dist
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'dist'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
options = {}
|
6
|
+
OptionParser.new do |opts|
|
7
|
+
opts.banner = "Usage: dist [switches] [command]"
|
8
|
+
|
9
|
+
opts.on('--skip-assets', 'Skip assets precompilation') do
|
10
|
+
options[:skip_assets] = true
|
11
|
+
end
|
12
|
+
|
13
|
+
opts.on('--local', 'Load gem dependencies and dependency packages definitions from local dist gem') do
|
14
|
+
options[:local] = true
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.on("-h", "--help", "Show this message") do
|
18
|
+
puts opts
|
19
|
+
exit
|
20
|
+
end
|
21
|
+
end.parse!
|
22
|
+
|
23
|
+
builder = Dist::Builder.new options
|
24
|
+
|
25
|
+
if ARGV == ['init']
|
26
|
+
builder.init
|
27
|
+
else
|
28
|
+
builder.build
|
29
|
+
end
|
data/dist.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'dist/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "dist"
|
8
|
+
gem.version = Dist::VERSION
|
9
|
+
gem.authors = ["Ary Borenszweig", "Juan Wajnerman"]
|
10
|
+
gem.email = ["aborenszweig@manas.com.ar", "jwajnerman@manas.com.ar"]
|
11
|
+
gem.description = %q{Generate packages to distribute Rails applications}
|
12
|
+
gem.summary = %q{Generate packages to distribute Rails applications}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
default:
|
2
|
+
- ruby1.9.1
|
3
|
+
- ruby1.9.1-dev
|
4
|
+
- build-essential
|
5
|
+
- libcurl4-openssl-dev
|
6
|
+
- libssl-dev
|
7
|
+
- libpcre3-dev
|
8
|
+
elasticsearch:
|
9
|
+
- elasticsearch
|
10
|
+
libcairo:
|
11
|
+
- libcairo2-dev
|
12
|
+
libpango:
|
13
|
+
- libpango1.0-dev
|
14
|
+
libxml2:
|
15
|
+
- libxml2-dev
|
16
|
+
libxslt:
|
17
|
+
- libxslt-dev
|
18
|
+
mail:
|
19
|
+
- mail-transport-agent
|
20
|
+
mysql:
|
21
|
+
- mysql-server
|
22
|
+
- libmysqlclient-dev
|
23
|
+
nodejs:
|
24
|
+
- nodejs
|
25
|
+
rabbitmq:
|
26
|
+
- rabbitmq-server
|
27
|
+
redis:
|
28
|
+
- redis-server
|
data/lib/dist.rb
ADDED
data/lib/dist/builder.rb
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'erb'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'yaml'
|
5
|
+
require 'set'
|
6
|
+
|
7
|
+
class Dist::Builder
|
8
|
+
include Dist::Error
|
9
|
+
include FileUtils::Verbose
|
10
|
+
|
11
|
+
OutputDir = "tmp/dist"
|
12
|
+
|
13
|
+
attr_reader :config
|
14
|
+
attr_reader :packages
|
15
|
+
|
16
|
+
def initialize(options = {})
|
17
|
+
@templates = {}
|
18
|
+
@options = options
|
19
|
+
end
|
20
|
+
|
21
|
+
def build
|
22
|
+
check_executable
|
23
|
+
load_configuration
|
24
|
+
compute_packages
|
25
|
+
compile_assets if !@options[:skip_assets] && assets_enabled
|
26
|
+
execute_before_build_commands
|
27
|
+
build_output
|
28
|
+
move_config_files
|
29
|
+
generate_logrotate
|
30
|
+
export_services
|
31
|
+
export_control
|
32
|
+
build_package
|
33
|
+
end
|
34
|
+
|
35
|
+
def init
|
36
|
+
@app_name = File.basename(FileUtils.pwd)
|
37
|
+
|
38
|
+
write_template 'config', 'config/dist.rb'
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def rails
|
44
|
+
@rails ||= begin
|
45
|
+
puts "Loading Rails..."
|
46
|
+
require './config/boot'
|
47
|
+
require './config/application'
|
48
|
+
Rails
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def execute_before_build_commands
|
53
|
+
config.before_build_commands.each do |command|
|
54
|
+
system command
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def assets_enabled
|
59
|
+
@assets_enabled ||= rails.configuration.assets.enabled rescue false
|
60
|
+
end
|
61
|
+
|
62
|
+
def has_database?
|
63
|
+
@has_database ||= begin
|
64
|
+
rails
|
65
|
+
defined? ActiveRecord
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def compile_assets
|
70
|
+
unless system 'bundle exec rake assets:clean assets:precompile'
|
71
|
+
error "failed to precompile assets"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def build_output
|
76
|
+
rmtree OutputDir
|
77
|
+
|
78
|
+
dirs = %W[
|
79
|
+
DEBIAN
|
80
|
+
etc/#{app_name}
|
81
|
+
etc/init
|
82
|
+
etc/logrotate.d
|
83
|
+
#{app_root}
|
84
|
+
#{app_root}/vendor
|
85
|
+
var/log/#{app_name}
|
86
|
+
var/lib/#{app_name}/bundle
|
87
|
+
var/lib/#{app_name}/gems
|
88
|
+
var/lib/#{app_name}/tmp
|
89
|
+
]
|
90
|
+
|
91
|
+
dirs.each { |dir| mkdir_p "#{OutputDir}/#{dir}" }
|
92
|
+
|
93
|
+
files = Dir['*'] - %w(log tmp test spec)
|
94
|
+
files.each do |file|
|
95
|
+
cp_r file, "#{OutputDir}/#{app_root}" unless file.end_with?('.deb')
|
96
|
+
end
|
97
|
+
|
98
|
+
ln_s "/var/lib/#{app_name}/bundle", "#{OutputDir}/#{app_root}/vendor/bundle"
|
99
|
+
ln_s "/var/lib/#{app_name}/gems", "#{OutputDir}/#{app_root}/.gems"
|
100
|
+
ln_s "/var/lib/#{app_name}/tmp", "#{OutputDir}/#{app_root}/tmp"
|
101
|
+
ln_s "/var/log/#{app_name}", "#{OutputDir}/#{app_root}/log"
|
102
|
+
ln_sf "/etc/#{app_name}/database.yml", "#{OutputDir}/#{app_root}/config/database.yml"
|
103
|
+
end
|
104
|
+
|
105
|
+
def move_config_files
|
106
|
+
config.sections.each do |section|
|
107
|
+
mv "#{OutputDir}/#{app_root}/config/#{section}.yml", "#{OutputDir}/etc/#{app_name}/"
|
108
|
+
ln_s "/etc/#{app_name}/#{section}.yml", "#{OutputDir}/#{app_root}/config/#{section}.yml"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def export_services
|
113
|
+
if File.exists? 'Procfile'
|
114
|
+
procfile = YAML.load_file 'Procfile'
|
115
|
+
rm_f "#{OutputDir}/etc/init/*"
|
116
|
+
|
117
|
+
procfile.each do |service_name, service_command|
|
118
|
+
next if service_name == 'web'
|
119
|
+
if service_command =~ /\Abundle\s+exec\s+(.*)/
|
120
|
+
service_command = $1
|
121
|
+
end
|
122
|
+
write_output_template 'upstart/service', "/etc/init/#{app_name}-#{service_name}.conf", binding
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
write_output_template 'upstart/main', "/etc/init/#{app_name}.conf"
|
127
|
+
write_output_template 'upstart/passenger', "/etc/init/#{app_name}-passenger.conf"
|
128
|
+
end
|
129
|
+
|
130
|
+
def generate_logrotate
|
131
|
+
write_output_template 'logrotate', "/etc/logrotate.d/#{app_name}"
|
132
|
+
end
|
133
|
+
|
134
|
+
def export_control
|
135
|
+
%w(control postinst prerm postrm config templates).each do |control_file|
|
136
|
+
write_output_template "debian/#{control_file}", "/DEBIAN/#{control_file}"
|
137
|
+
end
|
138
|
+
|
139
|
+
%w(postinst prerm postrm config).each do |control_file|
|
140
|
+
chmod 0755, "#{OutputDir}/DEBIAN/#{control_file}"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def check_executable
|
145
|
+
['fakeroot', 'dpkg-deb'].each do |executable|
|
146
|
+
`which #{executable}`
|
147
|
+
if !$?.success?
|
148
|
+
error "missing #{executable} executable, plese install it"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def build_package
|
154
|
+
unless system "fakeroot dpkg-deb --build #{OutputDir} #{output_filename}"
|
155
|
+
error "failed to build package"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def app_name
|
160
|
+
@app_name ||= config.application
|
161
|
+
end
|
162
|
+
|
163
|
+
def app_root
|
164
|
+
@app_root ||= "/usr/share/#{app_name}"
|
165
|
+
end
|
166
|
+
|
167
|
+
def output_filename
|
168
|
+
@output_filename ||= "#{app_name}_#{config.version}.deb"
|
169
|
+
end
|
170
|
+
|
171
|
+
def installed_size
|
172
|
+
@installed_size ||= `du -sk ./#{OutputDir}`.split[0]
|
173
|
+
end
|
174
|
+
|
175
|
+
def load_configuration
|
176
|
+
@config = Dist::Configuration.new
|
177
|
+
end
|
178
|
+
|
179
|
+
def compute_packages
|
180
|
+
@packages = Dist::PackageComputer.new(@config, @options).packages
|
181
|
+
end
|
182
|
+
|
183
|
+
def write_template(source, target, binding_object = binding)
|
184
|
+
template = @templates[source] ||= ERB.new(template(source), nil, '<>')
|
185
|
+
puts "write #{target} from template #{source}"
|
186
|
+
File.open(target, 'w') { |f| f.write template.result(binding_object) }
|
187
|
+
end
|
188
|
+
|
189
|
+
def write_output_template(source, target, binding_object = binding)
|
190
|
+
write_template source, "#{OutputDir}#{target}", binding_object
|
191
|
+
end
|
192
|
+
|
193
|
+
def template(file)
|
194
|
+
File.read(File.expand_path("../../templates/#{file}.erb", __FILE__))
|
195
|
+
end
|
196
|
+
|
197
|
+
def render(file)
|
198
|
+
template = @templates[file] ||= ERB.new(template(file), nil, '<>')
|
199
|
+
template.result(binding)
|
200
|
+
end
|
201
|
+
|
202
|
+
def system(*args)
|
203
|
+
puts *args
|
204
|
+
Kernel::system *args
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
class Dist::Configuration
|
2
|
+
include Dist::Error
|
3
|
+
|
4
|
+
attr_reader :dependencies
|
5
|
+
attr_reader :sections
|
6
|
+
attr_reader :after_install_commands
|
7
|
+
attr_reader :before_build_commands
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@vars = {}
|
11
|
+
@dependencies = []
|
12
|
+
@sections = []
|
13
|
+
@after_install_commands = []
|
14
|
+
@before_build_commands = []
|
15
|
+
|
16
|
+
config_contents = File.read("config/dist.rb") rescue error("config/dist.rb file not found. Please run `dist init`.")
|
17
|
+
instance_eval config_contents
|
18
|
+
end
|
19
|
+
|
20
|
+
def set(name, value)
|
21
|
+
@vars[name] = value
|
22
|
+
end
|
23
|
+
|
24
|
+
def get(name)
|
25
|
+
if @vars.has_key?(name)
|
26
|
+
@vars[name]
|
27
|
+
else
|
28
|
+
error "missing setting '#{name}'"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def use(service)
|
33
|
+
@dependencies << service
|
34
|
+
end
|
35
|
+
|
36
|
+
def config(section, &block)
|
37
|
+
config_section = Section.new(section)
|
38
|
+
config_section.instance_eval &block
|
39
|
+
@sections << config_section
|
40
|
+
end
|
41
|
+
|
42
|
+
def after_install(command)
|
43
|
+
@after_install_commands << command
|
44
|
+
end
|
45
|
+
|
46
|
+
def before_build(command)
|
47
|
+
@before_build_commands << command
|
48
|
+
end
|
49
|
+
|
50
|
+
def method_missing(name, *args)
|
51
|
+
if args.empty? && value = @vars[name]
|
52
|
+
return value
|
53
|
+
end
|
54
|
+
super
|
55
|
+
end
|
56
|
+
|
57
|
+
class Section
|
58
|
+
include Dist::Error
|
59
|
+
|
60
|
+
attr_reader :name
|
61
|
+
attr_reader :properties
|
62
|
+
|
63
|
+
def initialize(name)
|
64
|
+
@name = name
|
65
|
+
@properties = []
|
66
|
+
|
67
|
+
@filename = "config/#{name}.yml"
|
68
|
+
unless File.exists?(@filename)
|
69
|
+
error_at "config :#{name}", "the file '#{@filename}' doesn't exist."
|
70
|
+
end
|
71
|
+
|
72
|
+
@yaml = YAML.load_file @filename
|
73
|
+
@yaml = @yaml['production'] || @yaml
|
74
|
+
end
|
75
|
+
|
76
|
+
def string(name, options = {})
|
77
|
+
add_property name, :string, options
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_property(name, type, options = {})
|
81
|
+
unless @yaml.has_key?(name.to_s)
|
82
|
+
error_at "#{type}: :#{name}", "the property '#{name}' inside the file '#{@filename} doesn't exist."
|
83
|
+
end
|
84
|
+
|
85
|
+
@properties << Property.new(self, name, type, options)
|
86
|
+
end
|
87
|
+
|
88
|
+
def to_s
|
89
|
+
name.to_s
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class Property
|
94
|
+
attr_reader :name
|
95
|
+
attr_reader :type
|
96
|
+
|
97
|
+
def initialize(section, name, type, options = {})
|
98
|
+
@section = section
|
99
|
+
@name = name
|
100
|
+
@type = type
|
101
|
+
@options = options
|
102
|
+
end
|
103
|
+
|
104
|
+
def full_name
|
105
|
+
"#{@section.name}/#{name}"
|
106
|
+
end
|
107
|
+
|
108
|
+
def default_value
|
109
|
+
@options[:default]
|
110
|
+
end
|
111
|
+
|
112
|
+
def prompt
|
113
|
+
@options[:prompt] || "#{@section.name} #{name}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/lib/dist/error.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
class Dist::PackageComputer
|
2
|
+
def initialize(config, options = {})
|
3
|
+
@config = config
|
4
|
+
@yaml_loader = Dist::YamlLoader.new options
|
5
|
+
end
|
6
|
+
|
7
|
+
def packages
|
8
|
+
compute_packages
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def compute_packages
|
14
|
+
puts "Computing packages..."
|
15
|
+
@gems_yml = @yaml_loader.load 'gems'
|
16
|
+
@dependencies_yml = @yaml_loader.load 'dependencies'
|
17
|
+
@dependencies = Set.new
|
18
|
+
@packages = Set.new
|
19
|
+
@indent = 1
|
20
|
+
add_default_dependencies
|
21
|
+
add_dependencies_from_use
|
22
|
+
add_dependencies_from_bundle
|
23
|
+
@packages = @packages.to_a
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_default_dependencies
|
27
|
+
add_packages_from_dependency('default')
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_dependencies_from_use
|
31
|
+
@config.dependencies.each do |dependency|
|
32
|
+
if @dependencies.add?(dependency)
|
33
|
+
add_packages_from_dependency(dependency)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_dependencies_from_bundle
|
39
|
+
Bundler.load.specs.each do |spec|
|
40
|
+
gem_depenencies = @gems_yml[spec.name]
|
41
|
+
if gem_depenencies
|
42
|
+
printed_gem = false
|
43
|
+
gem_depenencies.each do |dependency|
|
44
|
+
if @dependencies.add?(dependency)
|
45
|
+
unless printed_gem
|
46
|
+
puts_with_indent "gem :#{spec.name}"
|
47
|
+
printed_gem = true
|
48
|
+
end
|
49
|
+
with_indent do
|
50
|
+
add_packages_from_dependency(dependency)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_packages_from_dependency(dependency)
|
59
|
+
puts_with_indent "use :#{dependency}"
|
60
|
+
with_indent do
|
61
|
+
dependency_packages = @dependencies_yml[dependency.to_s]
|
62
|
+
if dependency_packages
|
63
|
+
dependency_packages.each do |package|
|
64
|
+
puts_with_indent "package :#{package}"
|
65
|
+
@packages << package
|
66
|
+
end
|
67
|
+
else
|
68
|
+
error_at "use :#{dependency}", "could not find packages for dependency '#{dependency}'."
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def puts_with_indent(string)
|
74
|
+
puts "#{' ' * @indent}#{string}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def with_indent
|
78
|
+
@indent += 1
|
79
|
+
yield
|
80
|
+
@indent -= 1
|
81
|
+
end
|
82
|
+
end
|
data/lib/dist/version.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
class Dist::YamlLoader
|
2
|
+
include Dist::Error
|
3
|
+
|
4
|
+
def initialize(options = {})
|
5
|
+
@local = options[:local]
|
6
|
+
unless @local
|
7
|
+
require "net/https"
|
8
|
+
require "uri"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def load(filename)
|
13
|
+
@local ? load_from_local_file(filename) : load_from_url(filename)
|
14
|
+
end
|
15
|
+
|
16
|
+
def load_from_local_file(filename)
|
17
|
+
YAML.load_file File.expand_path("../../#{filename}.yml", __FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def load_from_url(filename)
|
21
|
+
uri = URI.parse("https://raw.githubusercontent.com/manastech/dist/master/lib/#{filename}.yml")
|
22
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
23
|
+
http.use_ssl = true
|
24
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
25
|
+
|
26
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
27
|
+
response = http.request(request)
|
28
|
+
if response.code != '200'
|
29
|
+
error "fetching '#{uri}' got status code #{response.code}. You can try running dist with --local if the problem persists."
|
30
|
+
end
|
31
|
+
YAML.load response.body
|
32
|
+
rescue SocketError => ex
|
33
|
+
error "couldn't fetch '#{uri}'. You can try running dist --local if you don't have internet access.\n(Exception is: #{ex.message})"
|
34
|
+
end
|
35
|
+
end
|
data/lib/gems.yml
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
. /usr/share/debconf/confmodule
|
3
|
+
|
4
|
+
db_input high <%= app_name %>/http_port
|
5
|
+
<% config.sections.each do |section| %>
|
6
|
+
<% section.properties.each do |property| %>
|
7
|
+
db_input high <%= app_name %>/<%= property.full_name %>
|
8
|
+
<% end %>
|
9
|
+
<% end %>
|
10
|
+
db_go
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Package: <%= app_name %>
|
2
|
+
Version: <%= config.version %>
|
3
|
+
Installed-Size: <%= installed_size %>
|
4
|
+
Section: devel
|
5
|
+
Priority: optional
|
6
|
+
Architecture: all
|
7
|
+
Pre-Depends: debconf
|
8
|
+
Depends: <%= packages.join ', ' %>
|
9
|
+
Maintainer: <%= config.maintainer %>
|
10
|
+
Description: <%= config.description %>
|
11
|
+
<%= config.summary %>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Configure database
|
2
|
+
if [ ! -e /etc/<%= app_name %>/database.yml ]; then
|
3
|
+
db_password=`ruby1.9.1 -e "print (0...16).map{ (('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a)[rand(62)] }.join"`
|
4
|
+
|
5
|
+
tmpfile=`mktemp`
|
6
|
+
cat << EOF > $tmpfile
|
7
|
+
CREATE DATABASE IF NOT EXISTS <%= app_name %>;
|
8
|
+
GRANT ALL ON <%= app_name %>.* TO '<%= app_name %>'@'localhost' IDENTIFIED BY '$db_password';
|
9
|
+
EOF
|
10
|
+
mysql --defaults-file=/etc/mysql/debian.cnf < $tmpfile
|
11
|
+
rm $tmpfile
|
12
|
+
|
13
|
+
cat << EOF > /etc/<%= app_name %>/database.yml
|
14
|
+
production:
|
15
|
+
adapter: mysql2
|
16
|
+
encoding: utf8
|
17
|
+
reconnect: true
|
18
|
+
database: <%= app_name %>
|
19
|
+
pool: 5
|
20
|
+
username: <%= app_name %>
|
21
|
+
password: $db_password
|
22
|
+
EOF
|
23
|
+
fi
|
24
|
+
|
25
|
+
chmod 0640 /etc/<%= app_name %>/database.yml
|
26
|
+
chown -R root:<%= app_name %> /etc/<%= app_name %>/database.yml
|
27
|
+
|
28
|
+
# Get the current DB version to check if it actually exists
|
29
|
+
$BUNDLE exec rake db:version
|
30
|
+
|
31
|
+
# Create or upgrade the database
|
32
|
+
if [ $? -eq 0 ]; then
|
33
|
+
$BUNDLE exec rake db:migrate
|
34
|
+
else
|
35
|
+
$BUNDLE exec rake db:setup
|
36
|
+
fi
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
. /usr/share/debconf/confmodule
|
4
|
+
|
5
|
+
case "$1" in
|
6
|
+
configure)
|
7
|
+
# Configure HTTP port
|
8
|
+
db_get <%= app_name %>/http_port && http_port="$RET"
|
9
|
+
echo "HTTP_PORT=$http_port" > /etc/default/<%= app_name %>
|
10
|
+
|
11
|
+
# Fill YAML configuration files
|
12
|
+
<% i = 0 %>
|
13
|
+
<% config.sections.each do |section| %>
|
14
|
+
<% section.properties.each do |property| %>
|
15
|
+
db_get <%= app_name %>/<%= property.full_name %> && property<%= i %>="$RET"
|
16
|
+
<% i += 1 %>
|
17
|
+
<% end %>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
tmpfile=`mktemp`
|
21
|
+
cat << EOF > $tmpfile
|
22
|
+
require 'yaml'
|
23
|
+
|
24
|
+
<% i = 0 %>
|
25
|
+
<% config.sections.each do |section| %>
|
26
|
+
yaml = YAML.load_file '<%= app_root %>/config/<%= section.name %>.yml'
|
27
|
+
hash = yaml['production'] || yaml
|
28
|
+
<% section.properties.each do |property| %>
|
29
|
+
hash['<%= property.name %>'] = ARGV[<%= i %>]
|
30
|
+
<% i += 1 %>
|
31
|
+
<% end %>
|
32
|
+
File.open('<%= app_root %>/config/<%= section.name %>.yml', 'w') do |file|
|
33
|
+
YAML.dump yaml, file
|
34
|
+
end
|
35
|
+
<% end %>
|
36
|
+
EOF
|
37
|
+
ruby1.9.1 $tmpfile <%= (0 ... i).map { |n| "$property#{n}" }.join ' ' %>
|
38
|
+
rm $tmpfile
|
39
|
+
|
40
|
+
# Create user and group for application and set permissions to some files and directories
|
41
|
+
|
42
|
+
if ! getent group <%= app_name %> >/dev/null; then
|
43
|
+
addgroup --system <%= app_name %> >/dev/null
|
44
|
+
fi
|
45
|
+
|
46
|
+
if ! getent passwd <%= app_name %> >/dev/null; then
|
47
|
+
adduser \
|
48
|
+
--system \
|
49
|
+
--disabled-login \
|
50
|
+
--ingroup <%= app_name %> \
|
51
|
+
--no-create-home \
|
52
|
+
--home /nonexistent \
|
53
|
+
--gecos "<%= app_name %>" \
|
54
|
+
--shell /bin/false \
|
55
|
+
<%= app_name %> >/dev/null
|
56
|
+
fi
|
57
|
+
chmod 0775 /var/log/<%= app_name %>/
|
58
|
+
touch /var/log/<%= app_name %>/production.log
|
59
|
+
chmod 0664 /var/log/<%= app_name %>/*
|
60
|
+
chmod 0775 /var/lib/<%= app_name %>/tmp
|
61
|
+
chown -R root:<%= app_name %> /etc/<%= app_name %>/
|
62
|
+
chown -R <%= app_name %>:<%= app_name %> /var/log/<%= app_name %>/
|
63
|
+
chown -R <%= app_name %>:<%= app_name %> /var/lib/<%= app_name %>/tmp
|
64
|
+
|
65
|
+
|
66
|
+
# Install base gems and the application bundle
|
67
|
+
cd <%= app_root %>
|
68
|
+
export RAILS_ENV=production
|
69
|
+
export GEM_HOME=<%= app_root %>/.gems
|
70
|
+
export GEM_PATH=
|
71
|
+
|
72
|
+
gem1.9.1 install bundler --no-ri --no-rdoc --conservative
|
73
|
+
gem1.9.1 install rake -v=0.9.2.2 --no-ri --no-rdoc --conservative
|
74
|
+
gem1.9.1 install passenger -v=3.0.11 --no-ri --no-rdoc --conservative
|
75
|
+
|
76
|
+
BUNDLE=<%= app_root %>/.gems/bin/bundle
|
77
|
+
|
78
|
+
$BUNDLE install --deployment --without=development test assets
|
79
|
+
$BUNDLE clean
|
80
|
+
|
81
|
+
<%= render 'debian/postinst-db' if has_database? %>
|
82
|
+
|
83
|
+
<% config.after_install_commands.each do |command| %>
|
84
|
+
$BUNDLE exec <%= command%>
|
85
|
+
<% end %>
|
86
|
+
|
87
|
+
start <%= app_name %>
|
88
|
+
|
89
|
+
;;
|
90
|
+
esac
|
91
|
+
|
92
|
+
exit 0
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
if [ "$1" = purge ]; then
|
4
|
+
rm -f /etc/<%= app_name %>/database.yml
|
5
|
+
rm -Rf /var/lib/<%= app_name %>/bundle/*
|
6
|
+
rm -Rf /var/lib/<%= app_name %>/gems/*
|
7
|
+
rm -Rf /var/lib/<%= app_name %>/tmp/*
|
8
|
+
rm -Rf /var/log/<%= app_name %>/*
|
9
|
+
rm -Rf <%= app_root %>/.bundle
|
10
|
+
rm -f /etc/default/<%= app_name %>
|
11
|
+
|
12
|
+
if [ -e /usr/share/debconf/confmodule ]; then
|
13
|
+
. /usr/share/debconf/confmodule
|
14
|
+
db_purge
|
15
|
+
fi
|
16
|
+
fi
|
17
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Template: <%= app_name %>/http_port
|
2
|
+
Type: string
|
3
|
+
Default: 80
|
4
|
+
Description: TCP Port for web application
|
5
|
+
|
6
|
+
<% config.sections.each do |section| %>
|
7
|
+
<% section.properties.each do |property| %>
|
8
|
+
Template: <%= app_name %>/<%= property.full_name %>
|
9
|
+
Type: <%= property.type %>
|
10
|
+
Default: <%= property.default_value %>
|
11
|
+
Description: <%= property.prompt %>
|
12
|
+
|
13
|
+
<% end %>
|
14
|
+
<% end %>
|
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
start on starting <%= app_name %>
|
2
|
+
stop on stopping <%= app_name %>
|
3
|
+
respawn
|
4
|
+
|
5
|
+
chdir <%= app_root %>
|
6
|
+
env GEM_HOME=<%= app_root %>/.gems
|
7
|
+
env HOME=<%= app_root %>
|
8
|
+
expect fork
|
9
|
+
|
10
|
+
script
|
11
|
+
. /etc/default/<%= app_name %>
|
12
|
+
.gems/bin/passenger start -e production -p $HTTP_PORT --user <%= app_name %>
|
13
|
+
end script
|
@@ -0,0 +1,12 @@
|
|
1
|
+
start on starting <%= app_name %>
|
2
|
+
stop on stopping <%= app_name %>
|
3
|
+
respawn
|
4
|
+
|
5
|
+
chdir <%= app_root %>
|
6
|
+
env GEM_HOME=<%= app_root %>/.gems
|
7
|
+
env RAILS_ENV=production
|
8
|
+
env HOME=<%= app_root %>
|
9
|
+
setuid <%= app_name %>
|
10
|
+
setgid <%= app_name %>
|
11
|
+
|
12
|
+
exec .gems/bin/bundle exec <%= service_command %> >> /var/log/<%= app_name %>/<%= service_name %>.log 2>&1
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dist
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ary Borenszweig
|
8
|
+
- Juan Wajnerman
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-06-25 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Generate packages to distribute Rails applications
|
15
|
+
email:
|
16
|
+
- aborenszweig@manas.com.ar
|
17
|
+
- jwajnerman@manas.com.ar
|
18
|
+
executables:
|
19
|
+
- dist
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- .gitignore
|
24
|
+
- Gemfile
|
25
|
+
- LICENSE.txt
|
26
|
+
- README.md
|
27
|
+
- Rakefile
|
28
|
+
- bin/dist
|
29
|
+
- dist.gemspec
|
30
|
+
- lib/dependencies.yml
|
31
|
+
- lib/dist.rb
|
32
|
+
- lib/dist/builder.rb
|
33
|
+
- lib/dist/configuration.rb
|
34
|
+
- lib/dist/error.rb
|
35
|
+
- lib/dist/package_computer.rb
|
36
|
+
- lib/dist/version.rb
|
37
|
+
- lib/dist/yaml_loader.rb
|
38
|
+
- lib/gems.yml
|
39
|
+
- lib/templates/config.erb
|
40
|
+
- lib/templates/debian/config.erb
|
41
|
+
- lib/templates/debian/control.erb
|
42
|
+
- lib/templates/debian/postinst-db.erb
|
43
|
+
- lib/templates/debian/postinst.erb
|
44
|
+
- lib/templates/debian/postrm.erb
|
45
|
+
- lib/templates/debian/prerm.erb
|
46
|
+
- lib/templates/debian/templates.erb
|
47
|
+
- lib/templates/logrotate.erb
|
48
|
+
- lib/templates/upstart/main.erb
|
49
|
+
- lib/templates/upstart/passenger.erb
|
50
|
+
- lib/templates/upstart/service.erb
|
51
|
+
homepage: ''
|
52
|
+
licenses: []
|
53
|
+
metadata: {}
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options: []
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
requirements: []
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 2.0.14
|
71
|
+
signing_key:
|
72
|
+
specification_version: 4
|
73
|
+
summary: Generate packages to distribute Rails applications
|
74
|
+
test_files: []
|