dist 0.0.2
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.
- 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: []
|