pkgr 0.3.4 → 1.0.1.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +68 -463
- data/bin/pkgr +4 -52
- data/lib/pkgr.rb +13 -29
- data/lib/pkgr/app.rb +19 -4
- data/lib/pkgr/builder.rb +207 -0
- data/lib/pkgr/buildpack.rb +80 -0
- data/lib/pkgr/cli.rb +34 -158
- data/lib/pkgr/config.rb +65 -0
- data/lib/pkgr/data/distributions/debian/build_dependencies.yml +14 -0
- data/lib/pkgr/data/{debian → distributions/debian}/cron.d +0 -0
- data/lib/pkgr/data/distributions/debian/default.erb +12 -0
- data/lib/pkgr/data/distributions/debian/dependencies.yml +17 -0
- data/lib/pkgr/data/distributions/debian/hooks/postinstall.sh +27 -0
- data/lib/pkgr/data/distributions/debian/hooks/preinstall.sh +9 -0
- data/lib/pkgr/data/{debian → distributions/debian}/logrotate.erb +0 -0
- data/lib/pkgr/data/distributions/debian/runner.erb +122 -0
- data/lib/pkgr/data/distributions/debian/upstart/master.conf.erb +7 -0
- data/lib/pkgr/data/distributions/debian/upstart/process.conf.erb +7 -0
- data/lib/pkgr/data/distributions/debian/upstart/process_master.conf.erb +2 -0
- data/lib/pkgr/dispatcher.rb +51 -0
- data/lib/pkgr/distributions.rb +18 -0
- data/lib/pkgr/distributions/debian.rb +157 -0
- data/lib/pkgr/git.rb +24 -0
- data/lib/pkgr/process.rb +18 -0
- data/lib/pkgr/templates/dir_template.rb +14 -0
- data/lib/pkgr/templates/file_template.rb +38 -0
- data/lib/pkgr/version.rb +1 -1
- metadata +93 -26
- data/lib/pkgr/data/debian/changelog +0 -0
- data/lib/pkgr/data/debian/compat.erb +0 -1
- data/lib/pkgr/data/debian/control.erb +0 -12
- data/lib/pkgr/data/debian/copyright.erb +0 -17
- data/lib/pkgr/data/debian/default.erb +0 -11
- data/lib/pkgr/data/debian/dirs.erb +0 -2
- data/lib/pkgr/data/debian/docs.erb +0 -0
- data/lib/pkgr/data/debian/init.d.erb +0 -155
- data/lib/pkgr/data/debian/install.erb +0 -16
- data/lib/pkgr/data/debian/links.erb +0 -5
- data/lib/pkgr/data/debian/postinst.erb +0 -59
- data/lib/pkgr/data/debian/prerm.erb +0 -57
- data/lib/pkgr/data/debian/rules.erb +0 -7
- data/lib/pkgr/pkgr.rake +0 -50
- data/lib/pkgr/railtie.rb +0 -7
data/bin/pkgr
CHANGED
@@ -1,56 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require 'pkgr/cli'
|
3
|
+
require "pkgr/cli"
|
5
4
|
|
6
|
-
|
5
|
+
STDERR.sync = true
|
6
|
+
STDOUT.sync = true
|
7
7
|
|
8
|
-
|
9
|
-
opts.banner = <<BANNER
|
10
|
-
* Description
|
11
|
-
pkgr #{Pkgr::VERSION} - Package Rails apps effortlessly.
|
12
|
-
* Usage
|
13
|
-
pkgr --uri GIT_REPOSITORY --config database.yml:http://path/to/database.yml --config ...
|
14
|
-
BANNER
|
15
|
-
|
16
|
-
opts.separator ""
|
17
|
-
opts.separator "* Common options"
|
18
|
-
opts.on("--uri=", "Sets the Git repository URI (FILE, HTTP, SSH, GIT, etc.) [required]") do |v|
|
19
|
-
OPTIONS[:uri] = v
|
20
|
-
end
|
21
|
-
opts.on("-c=", "--config=", "Download a configuration file into the config/ folder of the app (HTTP or FILE URIs)") do |v|
|
22
|
-
OPTIONS[:config_files] ||= []
|
23
|
-
OPTIONS[:config_files] << v
|
24
|
-
end
|
25
|
-
opts.on("-b=", "--bump=", "Sets the app version [required]") do |v|
|
26
|
-
OPTIONS[:version] = v
|
27
|
-
end
|
28
|
-
opts.on("-n=", "--name=", "Sets the app name [optional]") do |v|
|
29
|
-
OPTIONS[:name] = v
|
30
|
-
end
|
31
|
-
opts.on("--ref=", "Sets the git reference to checkout [default=#{OPTIONS[:ref]}]") do |v|
|
32
|
-
OPTIONS[:ref] = v
|
33
|
-
end
|
34
|
-
opts.on("--host=", "Sets the build machine hostname. If none, the process will stop just before building the package.") do |v|
|
35
|
-
OPTIONS[:host] = v
|
36
|
-
end
|
37
|
-
|
38
|
-
opts.separator ""
|
39
|
-
opts.separator "* Other"
|
40
|
-
opts.on_tail("-h", "--help", "Show this message") do
|
41
|
-
puts opts
|
42
|
-
exit
|
43
|
-
end
|
44
|
-
opts.on_tail("--version", "Show version") do
|
45
|
-
puts Pkgr::VERSION
|
46
|
-
exit
|
47
|
-
end
|
48
|
-
end.parse!
|
49
|
-
|
50
|
-
begin
|
51
|
-
cli = Pkgr::CLI.new(OPTIONS)
|
52
|
-
cli.run
|
53
|
-
rescue Pkgr::CLI::Error, StandardError => e
|
54
|
-
puts e.message
|
55
|
-
puts e.backtrace if $DEBUG
|
56
|
-
end
|
8
|
+
Pkgr::CLI.start
|
data/lib/pkgr.rb
CHANGED
@@ -1,35 +1,19 @@
|
|
1
|
-
require 'pkgr/
|
2
|
-
require 'pkgr/
|
1
|
+
require 'pkgr/version'
|
2
|
+
require 'pkgr/cli'
|
3
|
+
require 'pkgr/dispatcher'
|
4
|
+
require 'mixlib/log'
|
3
5
|
|
4
6
|
module Pkgr
|
5
|
-
|
7
|
+
extend Mixlib::Log
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
+
module Errors
|
10
|
+
class Base < StandardError; end
|
11
|
+
class UnknownAppType < Base; end
|
12
|
+
class ConfigurationInvalid < Base; end
|
9
13
|
end
|
10
14
|
|
11
|
-
|
12
|
-
|
13
|
-
def self.setup_config(root)
|
14
|
-
puts "Setting up configuration file..."
|
15
|
-
target = File.join(root, "config", "pkgr.yml")
|
16
|
-
FileUtils.mkdir_p(File.dirname(target))
|
17
|
-
if File.exist?(target)
|
18
|
-
puts "'#{target}' already exists. Skipped."
|
19
|
-
else
|
20
|
-
FileUtils.cp(File.expand_path("../pkgr/data/pkgr.yml", __FILE__), target, :verbose => true)
|
21
|
-
puts "Edit '#{target}' and fill in the required information, then enter 'rake pkgr:generate' to generate the debian files."
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
|
26
|
-
def self.mkdir(target)
|
27
|
-
if File.directory?(target)
|
28
|
-
puts "#{target} directory already exists. Skipped."
|
29
|
-
elsif File.file?(target)
|
30
|
-
raise "#{target} already exists and is a file. Aborting."
|
31
|
-
else
|
32
|
-
FileUtils.mkdir_p target, :verbose => true
|
33
|
-
end
|
15
|
+
def data_dir
|
16
|
+
File.expand_path("../pkgr/data", __FILE__)
|
34
17
|
end
|
35
|
-
|
18
|
+
module_function :data_dir
|
19
|
+
end
|
data/lib/pkgr/app.rb
CHANGED
@@ -22,6 +22,7 @@ module Pkgr
|
|
22
22
|
@config = YAML::load_file(path)
|
23
23
|
raise ArgumentError, "The given configuration file at '#{path}' is not a well-formed YAML file. Please fix it or remove it and run 'rake pkgr:setup'" unless @config.kind_of?(Hash)
|
24
24
|
@config['_path'] = path
|
25
|
+
normalize_name!
|
25
26
|
end
|
26
27
|
|
27
28
|
def write_config
|
@@ -215,8 +216,8 @@ module Pkgr
|
|
215
216
|
#{debian_steps.join(" &&\n")}'
|
216
217
|
}
|
217
218
|
sh cmd
|
218
|
-
# Fetch
|
219
|
-
sh "scp #{host}:/tmp/#{name}_#{version}
|
219
|
+
# Fetch all package files, and put it in the `pkg` directory
|
220
|
+
sh "scp #{host}:/tmp/#{name}_#{version}* pkg/"
|
220
221
|
end
|
221
222
|
end
|
222
223
|
|
@@ -252,7 +253,7 @@ module Pkgr
|
|
252
253
|
|
253
254
|
private
|
254
255
|
def bundler_version
|
255
|
-
@config.fetch('bundler_version') { '1.
|
256
|
+
@config.fetch('bundler_version') { '1.3.5' }
|
256
257
|
end
|
257
258
|
|
258
259
|
def debian_file(filename)
|
@@ -260,5 +261,19 @@ module Pkgr
|
|
260
261
|
raise "The debian/changelog file does not exist. Please generate it first." unless File.exist?(file)
|
261
262
|
file
|
262
263
|
end
|
264
|
+
|
265
|
+
def normalize_name!
|
266
|
+
# debian packages can not contain capitalized letters nor underscores
|
267
|
+
if (raw_name = @config.fetch('name', '')) =~ /[A-Z_-]/
|
268
|
+
normalized_name = raw_name.
|
269
|
+
gsub(/[A-Z]/) { |m| "_#{m.downcase}" }. # underscore each word
|
270
|
+
gsub(/[_-]+/, '-'). # normalize underscores/dashes
|
271
|
+
sub(/^-/, '') # strip leading dash
|
272
|
+
puts "Normalized application name to %s (original: %s)." % [
|
273
|
+
normalized_name.inspect, raw_name.inspect
|
274
|
+
] unless normalized_name == raw_name
|
275
|
+
@config['name'] = normalized_name
|
276
|
+
end
|
277
|
+
end
|
263
278
|
end
|
264
|
-
end
|
279
|
+
end
|
data/lib/pkgr/builder.rb
ADDED
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'pkgr/config'
|
4
|
+
require 'pkgr/distributions'
|
5
|
+
require 'pkgr/process'
|
6
|
+
|
7
|
+
module Pkgr
|
8
|
+
class Builder
|
9
|
+
attr_reader :tarball, :config
|
10
|
+
|
11
|
+
# Accepts a path to a tarball (gzipped or not), or you can pass '-' to read from stdin.
|
12
|
+
def initialize(tarball, config)
|
13
|
+
@tarball = tarball
|
14
|
+
@config = config
|
15
|
+
Pkgr.debug "Initializing builder with the following config: #{config.inspect}"
|
16
|
+
end
|
17
|
+
|
18
|
+
# Launch the full packaging procedure
|
19
|
+
def call
|
20
|
+
check
|
21
|
+
setup
|
22
|
+
extract
|
23
|
+
compile
|
24
|
+
write_env
|
25
|
+
write_init
|
26
|
+
package
|
27
|
+
end
|
28
|
+
|
29
|
+
# Check configuration, and verifies that the current distribution's requirements are satisfied
|
30
|
+
def check
|
31
|
+
raise Errors::ConfigurationInvalid, config.errors.join("; ") unless config.valid?
|
32
|
+
distribution.check(config)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Setup the build directory structure
|
36
|
+
def setup
|
37
|
+
Dir.chdir(build_dir) do
|
38
|
+
distribution.templates(config.name).each do |template|
|
39
|
+
template.install(config.sesame)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Extract the given tarball to the target directory
|
45
|
+
def extract
|
46
|
+
raise "#{source_dir} does not exist" unless File.directory?(source_dir)
|
47
|
+
|
48
|
+
opts = {}
|
49
|
+
if tarball == "-"
|
50
|
+
# FIXME: not really happy with reading everything in memory
|
51
|
+
opts[:input] = $stdin.read
|
52
|
+
end
|
53
|
+
|
54
|
+
tarball_extract = Mixlib::ShellOut.new("tar xzf #{tarball} -C #{source_dir}", opts)
|
55
|
+
tarball_extract.run_command
|
56
|
+
tarball_extract.error!
|
57
|
+
end
|
58
|
+
|
59
|
+
# Pass the app through the buildpack
|
60
|
+
def compile
|
61
|
+
if buildpack_for_app
|
62
|
+
puts "-----> #{buildpack_for_app.banner} app"
|
63
|
+
|
64
|
+
FileUtils.mkdir_p(compile_cache_dir)
|
65
|
+
|
66
|
+
run_hook config.before_precompile
|
67
|
+
buildpack_for_app.compile(source_dir, compile_cache_dir)
|
68
|
+
buildpack_for_app.release(source_dir, compile_cache_dir)
|
69
|
+
else
|
70
|
+
raise Errors::UnknownAppType, "Can't find a buildpack for your app"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Parses the output of buildpack/bin/release executable to find out its default Procfile commands.
|
75
|
+
# Then merges those with the ones from the app's Procfile (if any).
|
76
|
+
# Finally, generates a binstub in vendor/pkgr/processes/ so that these commands can be called using the app's executable.
|
77
|
+
def write_env
|
78
|
+
FileUtils.mkdir_p proc_dir
|
79
|
+
|
80
|
+
procfile_entries.each do |process|
|
81
|
+
process_file = File.join(proc_dir, process.name)
|
82
|
+
|
83
|
+
File.open(process_file, "w+") do |f|
|
84
|
+
f << process.command
|
85
|
+
f << " $@"
|
86
|
+
end
|
87
|
+
|
88
|
+
FileUtils.chmod 0755, process_file
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Write startup scripts.
|
93
|
+
def write_init
|
94
|
+
FileUtils.mkdir_p scaling_dir
|
95
|
+
Dir.chdir(scaling_dir) do
|
96
|
+
distribution.initializers_for(config.name, procfile_entries).each do |(process, file)|
|
97
|
+
process_config = config.dup
|
98
|
+
process_config.process_name = process.name
|
99
|
+
process_config.process_command = process.command
|
100
|
+
file.install(process_config.sesame)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Launch the FPM command that will generate the package.
|
106
|
+
def package
|
107
|
+
Pkgr.info "Running command: #{fpm_command}"
|
108
|
+
app_package = Mixlib::ShellOut.new(fpm_command)
|
109
|
+
app_package.run_command
|
110
|
+
app_package.error!
|
111
|
+
end
|
112
|
+
|
113
|
+
# Make sure to get rid of the build directory
|
114
|
+
def teardown
|
115
|
+
FileUtils.rm_rf(build_dir)
|
116
|
+
end
|
117
|
+
|
118
|
+
def procfile_entries
|
119
|
+
@procfile_entries ||= begin
|
120
|
+
default_process_types = YAML.load_file(release_file)["default_process_types"]
|
121
|
+
|
122
|
+
entries = if File.exist?(procfile)
|
123
|
+
File.read(procfile).gsub("\r\n","\n").split("\n").map do |line|
|
124
|
+
if line =~ /^([A-Za-z0-9_]+):\s*(.+)$/
|
125
|
+
[$1, $2]
|
126
|
+
end
|
127
|
+
end.compact
|
128
|
+
else
|
129
|
+
[]
|
130
|
+
end
|
131
|
+
|
132
|
+
default_process_types.merge(Hash[entries]).map{|name, command| Process.new(name, command)}
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Path to the release file generated after the buildpack compilation.
|
137
|
+
def release_file
|
138
|
+
File.join(source_dir, ".release")
|
139
|
+
end
|
140
|
+
|
141
|
+
# Path to the directory containing the main app files.
|
142
|
+
def source_dir
|
143
|
+
File.join(build_dir, "opt/#{config.name}")
|
144
|
+
end
|
145
|
+
|
146
|
+
# Build directory. Will be used by fpm to make the package.
|
147
|
+
def build_dir
|
148
|
+
@build_dir ||= Dir.mktmpdir
|
149
|
+
end
|
150
|
+
|
151
|
+
def vendor_dir
|
152
|
+
File.join(source_dir, "vendor", "pkgr")
|
153
|
+
end
|
154
|
+
|
155
|
+
# Directory where binstubs will be created for the corresponding Procfile commands.
|
156
|
+
def proc_dir
|
157
|
+
File.join(vendor_dir, "processes")
|
158
|
+
end
|
159
|
+
|
160
|
+
def scaling_dir
|
161
|
+
File.join(vendor_dir, "scaling")
|
162
|
+
end
|
163
|
+
|
164
|
+
# Returns the path to the app's (supposedly present) Procfile.
|
165
|
+
def procfile
|
166
|
+
File.join(source_dir, "Procfile")
|
167
|
+
end
|
168
|
+
|
169
|
+
# Directory where the buildpacks can store stuff.
|
170
|
+
def compile_cache_dir
|
171
|
+
config.compile_cache_dir || File.join(source_dir, ".git/cache")
|
172
|
+
end
|
173
|
+
|
174
|
+
# Returns the current distribution we're packaging for.
|
175
|
+
def distribution
|
176
|
+
@distribution ||= Distributions.current
|
177
|
+
end
|
178
|
+
|
179
|
+
# List of available buildpacks for the current distribution.
|
180
|
+
def buildpacks
|
181
|
+
distribution.buildpacks
|
182
|
+
end
|
183
|
+
|
184
|
+
# Buildpack detected for the app, if any.
|
185
|
+
def buildpack_for_app
|
186
|
+
raise "#{source_dir} does not exist" unless File.directory?(source_dir)
|
187
|
+
@buildpack_for_app ||= buildpacks.find do |buildpack|
|
188
|
+
buildpack.setup
|
189
|
+
buildpack.detect(source_dir)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def fpm_command
|
194
|
+
distribution.fpm_command(build_dir, config)
|
195
|
+
end
|
196
|
+
|
197
|
+
protected
|
198
|
+
def run_hook(file)
|
199
|
+
return true if file.nil?
|
200
|
+
Dir.chdir(source_dir) do
|
201
|
+
app_package = Mixlib::ShellOut.new("bash '#{file}'")
|
202
|
+
app_package.run_command
|
203
|
+
app_package.error!
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Pkgr
|
4
|
+
class Buildpack
|
5
|
+
class << self
|
6
|
+
attr_writer :buildpack_cache_dir
|
7
|
+
|
8
|
+
def buildpack_cache_dir
|
9
|
+
@buildpack_cache_dir ||= File.expand_path("~/.pkgr/buildpacks").tap do |dir|
|
10
|
+
FileUtils.mkdir_p(dir)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :url, :banner
|
16
|
+
|
17
|
+
def initialize(url)
|
18
|
+
@url = url
|
19
|
+
end
|
20
|
+
|
21
|
+
def buildpack_cache_dir
|
22
|
+
self.class.buildpack_cache_dir
|
23
|
+
end
|
24
|
+
|
25
|
+
def detect(path)
|
26
|
+
buildpack_detect = Mixlib::ShellOut.new("#{dir}/bin/detect \"#{path}\"")
|
27
|
+
buildpack_detect.run_command
|
28
|
+
@banner = buildpack_detect.stdout.chomp
|
29
|
+
buildpack_detect.exitstatus == 0
|
30
|
+
end
|
31
|
+
|
32
|
+
def compile(path, compile_cache_dir)
|
33
|
+
Dir.chdir(path) do
|
34
|
+
IO.popen(%{ env -i PATH="$PATH" #{dir}/bin/compile "#{path}" "#{compile_cache_dir}" }) do |io|
|
35
|
+
until io.eof?
|
36
|
+
data = io.gets
|
37
|
+
print data
|
38
|
+
end
|
39
|
+
end
|
40
|
+
raise "compile failed" unless $?.exitstatus.zero?
|
41
|
+
end
|
42
|
+
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def release(path, compile_cache_dir)
|
47
|
+
buildpack_release = Mixlib::ShellOut.new("#{dir}/bin/release \"#{path}\" \"#{compile_cache_dir}\" > #{path}/.release")
|
48
|
+
buildpack_release.run_command
|
49
|
+
buildpack_release.exitstatus == 0
|
50
|
+
end
|
51
|
+
|
52
|
+
def dir
|
53
|
+
File.join(buildpack_cache_dir, File.basename(url, ".git"))
|
54
|
+
end
|
55
|
+
|
56
|
+
def exists?
|
57
|
+
File.directory?(dir)
|
58
|
+
end
|
59
|
+
|
60
|
+
def setup
|
61
|
+
exists? ? refresh : install
|
62
|
+
end
|
63
|
+
|
64
|
+
def refresh
|
65
|
+
Dir.chdir(dir) do
|
66
|
+
buildpack_refresh = Mixlib::ShellOut.new("git fetch origin && git reset --hard origin/master")
|
67
|
+
buildpack_refresh.run_command
|
68
|
+
buildpack_refresh.error!
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def install
|
73
|
+
Dir.chdir(buildpack_cache_dir) do
|
74
|
+
buildpack_install = Mixlib::ShellOut.new("git clone \"#{url}\"")
|
75
|
+
buildpack_install.run_command
|
76
|
+
buildpack_install.error!
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/pkgr/cli.rb
CHANGED
@@ -1,164 +1,40 @@
|
|
1
|
-
require
|
2
|
-
require 'fileutils'
|
1
|
+
require "thor"
|
3
2
|
require 'pkgr'
|
4
|
-
require 'uri'
|
5
3
|
|
6
4
|
module Pkgr
|
7
|
-
class CLI
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
generate
|
41
|
-
bump
|
42
|
-
build
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def valid?
|
47
|
-
@errors.clear
|
48
|
-
@errors.push("You must pass a repository URI through --uri") if uri.nil?
|
49
|
-
@errors.push("You must pass a version number through --bump") if version.nil?
|
50
|
-
@errors.empty?
|
51
|
-
end
|
52
|
-
|
53
|
-
def build
|
54
|
-
if host.nil?
|
55
|
-
puts "Can't build the package. You must pass the --host option for this."
|
56
|
-
else
|
57
|
-
@app.build_debian_package(host)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def bump
|
62
|
-
@app.bump!(:custom, version)
|
63
|
-
end
|
64
|
-
|
65
|
-
def bundle
|
66
|
-
sh "bundle install"
|
67
|
-
sh "git add -f Gemfile.lock"
|
68
|
-
sh "if git status --porcelain | grep Gemfile.lock; then git commit -m '[pkgr] Update Gemfile.lock.'; fi"
|
69
|
-
end
|
70
|
-
|
71
|
-
def checkout
|
72
|
-
sh "if git branch | grep '#{pkgr_branch}'; then git checkout #{pkgr_branch}; else git checkout -b #{pkgr_branch} #{ref}; fi"
|
73
|
-
end
|
74
|
-
|
75
|
-
def clone_repository
|
76
|
-
parsed_uri = URI.parse(uri)
|
77
|
-
case parsed_uri.scheme
|
78
|
-
when nil, "file"
|
79
|
-
@dir = parsed_uri.path
|
80
|
-
else
|
81
|
-
@dir = File.basename(uri, ".git")
|
82
|
-
sh "git clone #{uri}"
|
83
|
-
end
|
84
|
-
@dir = File.expand_path @dir
|
85
|
-
end
|
86
|
-
|
87
|
-
def configure_app
|
88
|
-
@app = Pkgr::App.new(dir, "config/pkgr.yml")
|
89
|
-
@app.config['git_ref'] = pkgr_branch
|
90
|
-
@app.config['config_files'].push(*Dir["config/*.yml"].map{|f| File.basename(f)}).uniq!
|
91
|
-
if name.nil?
|
92
|
-
@app.config['name'] = File.basename(dir) if @app.name.nil?
|
93
|
-
else
|
94
|
-
@app.config['name'] = name
|
95
|
-
end
|
96
|
-
raise Error, "The app is not correctly configured: #{@app.errors.join(", ")}" unless @app.valid?
|
97
|
-
@app.write_config
|
98
|
-
end
|
99
|
-
|
100
|
-
# Download the given config files
|
101
|
-
def copy_remote_config_files
|
102
|
-
(config_files || []).each do |file|
|
103
|
-
filename, file_uri = file.split("::")
|
104
|
-
if file_uri.nil?
|
105
|
-
file_uri = filename
|
106
|
-
filename = File.basename(file_uri)
|
107
|
-
end
|
108
|
-
|
109
|
-
file_uri = File.expand_path(file_uri) if URI.parse(file_uri).scheme.nil?
|
110
|
-
target = "config/#{filename}"
|
111
|
-
puts "Copying #{file_uri} into #{target}..."
|
112
|
-
File.open(target, "w+") { |f| f << open(file_uri).read }
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def copy_example_config_files
|
117
|
-
[".example", ".dist"].each do |pattern|
|
118
|
-
Dir["config/*.yml#{pattern}"].each do |file|
|
119
|
-
target = File.basename(file, pattern)
|
120
|
-
unless File.exist?("config/#{target}")
|
121
|
-
FileUtils.cp(file, "config/#{target}")
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def generate
|
128
|
-
@app.generate_required_files
|
129
|
-
sh "git add debian/"
|
130
|
-
sh "if git status --porcelain | grep debian/; then git commit -m '[pkgr] Add debian files.'; fi"
|
131
|
-
sh "git add bin/"
|
132
|
-
sh "if git status --porcelain | grep bin/; then git commit -m '[pkgr] Add executable file.'; fi"
|
133
|
-
end
|
134
|
-
|
135
|
-
def pkgr_branch
|
136
|
-
"pkgr-#{ref}"
|
137
|
-
end
|
138
|
-
|
139
|
-
def setup
|
140
|
-
Pkgr.setup(dir)
|
141
|
-
|
142
|
-
gemfile = File.read("Gemfile")
|
143
|
-
unless gemfile =~ /^gem 'pkgr'/
|
144
|
-
File.open("Gemfile", "a") do |f|
|
145
|
-
f.puts
|
146
|
-
f.puts "gem 'pkgr'"
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
unless gemfile =~ /^gem 'thin'/
|
151
|
-
File.open("Gemfile", "a") do |f|
|
152
|
-
f.puts
|
153
|
-
f.puts "gem 'thin'"
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
sh "git add Gemfile"
|
158
|
-
sh" if git status --porcelain | grep Gemfile; then git commit -m '[pkgr] Update Gemfile.'; fi"
|
159
|
-
sh "git add -f config/*.yml"
|
160
|
-
sh" if git status --porcelain | grep config/*.yml; then git commit -m '[pkgr] Update configuration files.'; fi"
|
5
|
+
class CLI < Thor
|
6
|
+
class_option :verbose, :type => :boolean, :default => false, :desc => "Run verbosely"
|
7
|
+
class_option :debug, :type => :boolean, :default => false, :desc => "Run very verbosely"
|
8
|
+
class_option :name, :type => :string, :desc => "Application name (if directory given, it will default to the directory name)"
|
9
|
+
|
10
|
+
desc "package TARBALL", "Package the given tarball or directory"
|
11
|
+
|
12
|
+
method_option :target, :type => :string, :default => "deb", :desc => "Target package to build (only 'deb' supported for now)"
|
13
|
+
method_option :changelog, :type => :string, :desc => "Changelog"
|
14
|
+
method_option :architecture, :type => :string, :default => "x86_64", :desc => "Target architecture for the package"
|
15
|
+
method_option :homepage, :type => :string, :desc => "Project homepage"
|
16
|
+
method_option :description, :type => :string, :desc => "Project description"
|
17
|
+
method_option :version, :type => :string, :desc => "Package version (if git directory given, it will use the latest git tag available)"
|
18
|
+
method_option :iteration, :type => :string, :default => Time.now.strftime("%Y%m%d%H%M%S"), :desc => "Package iteration (you should keep the default here)"
|
19
|
+
method_option :user, :type => :string, :desc => "User to run the app under (defaults to your app name)"
|
20
|
+
method_option :group, :type => :string, :desc => "Group to run the app under (defaults to your app name)"
|
21
|
+
method_option :compile_cache_dir, :type => :string, :desc => "Where to store the files cached between packaging runs"
|
22
|
+
method_option :dependencies, :type => :array, :default => [], :desc => "Specific system dependencies that you want to install with the package"
|
23
|
+
method_option :build_dependencies, :type => :array, :default => [], :desc => "Specific system dependencies that must be present before building"
|
24
|
+
method_option :before_precompile, :type => :string, :desc => "Provide a script to run just before the buildpack compilation"
|
25
|
+
method_option :host, :type => :string, :desc => "Remote host to build on (default: local machine)"
|
26
|
+
method_option :auto, :type => :boolean, :default => false, :desc => "Automatically attempt to install missing dependencies"
|
27
|
+
|
28
|
+
def package(tarball)
|
29
|
+
Pkgr.level = Logger::INFO if options[:verbose]
|
30
|
+
Pkgr.level = Logger::DEBUG if options[:debug]
|
31
|
+
|
32
|
+
packager = Dispatcher.new(tarball, options)
|
33
|
+
packager.call
|
34
|
+
rescue Pkgr::Errors::Base => e
|
35
|
+
Pkgr.error "#{e.class.name} : #{e.message}"
|
36
|
+
puts "* ERROR: #{e.message}"
|
37
|
+
exit 1
|
161
38
|
end
|
162
39
|
end
|
163
|
-
|
164
40
|
end
|