rubypack 0.1.0 → 1.0.0
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 +4 -4
- data/.gitignore +2 -0
- data/README.md +111 -7
- data/bin/rubypack +88 -0
- data/lib/rubypack/builder.rb +96 -0
- data/lib/rubypack/bundler_controller.rb +40 -0
- data/lib/rubypack/compressor.rb +71 -0
- data/lib/rubypack/compressors/all.rb +2 -0
- data/lib/rubypack/compressors/tgz_compressor.rb +22 -0
- data/lib/rubypack/compressors/zip_compressor.rb +22 -0
- data/lib/rubypack/deployer.rb +69 -0
- data/lib/rubypack/listing.rb +19 -0
- data/lib/rubypack/rubypack_file.rb +101 -0
- data/lib/rubypack/shell_output.rb +46 -0
- data/lib/rubypack/version.rb +1 -1
- data/lib/rubypack.rb +8 -5
- data/rubypack.gemspec +16 -13
- metadata +34 -10
- data/bin/console +0 -14
- data/bin/setup +0 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bc226695dfc183b20bcc0eeaaeaf37ce09de7ade
|
|
4
|
+
data.tar.gz: 9009bba0cced0663a976df1c3bb26293dfe36579
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 10dd8d1298926a9fef8293977323006eb62a2ca2d3719dc37e270c4add56ab6ef03cec600523f22e2902fd0c3de8c8e580c19ef48fb60ce390a3baa2c800e253
|
|
7
|
+
data.tar.gz: 31c478263d3de4343ec17860a9c9c78653791195fa5f573a0ffef95e2863714ac703d71073a7738f5e9ddabc929a9453653418f3c691e718609fa86263c8c1c8
|
data/.gitignore
CHANGED
data/README.md
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# Rubypack
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
|
3
|
+
This gem provides some utilities to build a package of your application with aims to provide a runnable standalone application that can be shared or deployed in production systems.
|
|
6
4
|
|
|
7
5
|
## Installation
|
|
8
6
|
|
|
@@ -22,17 +20,123 @@ Or install it yourself as:
|
|
|
22
20
|
|
|
23
21
|
## Usage
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
To build a package of your application, you need to define a new file named `.rubypack` on the root directory of your application.
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
The content of the .rubypack file:
|
|
26
|
+
```ruby
|
|
27
|
+
name 'TestApp'
|
|
28
|
+
version '3.1'
|
|
29
|
+
|
|
30
|
+
exclude '*.log'
|
|
31
|
+
include 'js/node_modules/**/**'
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Then run the following command to build your package:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
$ rubypack build
|
|
38
|
+
|
|
39
|
+
Reading .rubypack file...
|
|
40
|
+
Name: TestApp
|
|
41
|
+
Version: 3.1
|
|
42
|
+
[ OK ]
|
|
43
|
+
Downloading gems...
|
|
44
|
+
[ OK ]
|
|
45
|
+
Generating list of files...
|
|
46
|
+
Action: exclude, Filter: *.log
|
|
47
|
+
Action: include, Filter: js/node_modules/**/**
|
|
48
|
+
Files count: 33
|
|
49
|
+
[ OK ]
|
|
50
|
+
Creating copy of files...
|
|
51
|
+
[ OK ]
|
|
52
|
+
Creating package...
|
|
53
|
+
File created: /repo/my_application/TestApp-3.1.tgz.rpack
|
|
54
|
+
[ OK ]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The previous command will generate a file with extension '.tgz.rpack'. It will automatically include all the required gems for all the platforms in the package.
|
|
58
|
+
|
|
59
|
+
The application can be deployed using the following command:
|
|
28
60
|
|
|
29
|
-
|
|
61
|
+
```bash
|
|
62
|
+
$ rubypack deploy --filename TestApp-3.1.tgz.rpack --directory /production/app/
|
|
63
|
+
Unpacking file...
|
|
64
|
+
Directory created: /production/app/
|
|
65
|
+
[ OK ]
|
|
66
|
+
Installing gems...
|
|
67
|
+
[ OK ]
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The previous command will install all the gems required by your application in local mode, without using network or rubygems, and using the `Gemfile.lock` to install the proper gems inside the `vendor` folder.
|
|
71
|
+
|
|
72
|
+
To view more details about what is happening, you can use the `--verbose` switch. Also with `--help` you can see the different commands available.
|
|
73
|
+
|
|
74
|
+
### Available commands
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
$ rubypack --help
|
|
78
|
+
RubyPack 0.1.0 (c) 2017 Jorge del Rio
|
|
79
|
+
A ruby package generation and execution manager.
|
|
80
|
+
|
|
81
|
+
Commands:
|
|
82
|
+
build Create a new package.
|
|
83
|
+
deploy Install the application package and all the gems.
|
|
84
|
+
list List the files to be included in the package.
|
|
85
|
+
|
|
86
|
+
Options:
|
|
87
|
+
-h, --help Show this message
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Build command
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
$ rubypack build --help
|
|
94
|
+
build - Builds a package of your application.
|
|
95
|
+
|
|
96
|
+
Options:
|
|
97
|
+
-c, --config=<s> The config file to use (default: .rubypack)
|
|
98
|
+
-o, --output-directory=<s> The directory where the final package is going to be created. (Default: .)
|
|
99
|
+
-m, --compressor=<s> The compressor utility to use. Possible values: tgz, zip. (Default: tgz)
|
|
100
|
+
-n, --no-overwrite Do not overwrite the output file if it already exists.
|
|
101
|
+
-v, --verbose Verbose output for debugging.
|
|
102
|
+
-q, --quiet Do not output anything.
|
|
103
|
+
-h, --help Show this message
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Deploy command
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
$ rubypack deploy --help
|
|
110
|
+
deploy - Install the application package and all the gems.
|
|
111
|
+
|
|
112
|
+
Options:
|
|
113
|
+
-f, --filename=<s> The file deploy
|
|
114
|
+
-d, --directory=<s> The directory where the final package is going to be deployed.
|
|
115
|
+
-v, --verbose Verbose output for debugging.
|
|
116
|
+
-c, --compressor=<s> The compressor utility to use. Possible values: tgz, zip.
|
|
117
|
+
-h, --help Show this message
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### List command
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
$ rubypack list --help
|
|
124
|
+
list - List the files to be included in the package.
|
|
125
|
+
|
|
126
|
+
Options:
|
|
127
|
+
-c, --config=<s> The config file to use (default: .rubypack)
|
|
128
|
+
-v, --verbose Verbose output for debugging.
|
|
129
|
+
-h, --help Show this message
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
## Development
|
|
30
134
|
|
|
31
135
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
32
136
|
|
|
33
137
|
## Contributing
|
|
34
138
|
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
|
139
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/newint33h/rubypack.git. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
|
36
140
|
|
|
37
141
|
|
|
38
142
|
## License
|
data/bin/rubypack
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'trollop'
|
|
5
|
+
require 'rubypack'
|
|
6
|
+
|
|
7
|
+
SUB_COMMANDS = %w(build deploy list)
|
|
8
|
+
global_opts = Trollop::options do
|
|
9
|
+
banner "RubyPack #{Rubypack::VERSION} (c) 2017 Jorge del Rio\n" \
|
|
10
|
+
"A ruby package generation and execution manager.\n\n" \
|
|
11
|
+
"Commands:\n" \
|
|
12
|
+
" build Create a new package.\n" \
|
|
13
|
+
" deploy Install the application package and all the gems.\n" \
|
|
14
|
+
" list List the files to be included in the package.\n\n" \
|
|
15
|
+
"Options:\n"
|
|
16
|
+
stop_on SUB_COMMANDS
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
cmd = ARGV.shift
|
|
20
|
+
cmd_opts = case cmd
|
|
21
|
+
when 'build'
|
|
22
|
+
Trollop::options do
|
|
23
|
+
banner "build - Builds a package of your application.\n\n" \
|
|
24
|
+
"Options:\n"
|
|
25
|
+
opt :config,
|
|
26
|
+
'The config file to use',
|
|
27
|
+
type: :string,
|
|
28
|
+
default: Rubypack::RubypackFile::DEFAULT_FILENAME
|
|
29
|
+
opt :output_directory,
|
|
30
|
+
'The directory where the final package is going to be created.',
|
|
31
|
+
type: :string,
|
|
32
|
+
default: '.'
|
|
33
|
+
opt :compressor,
|
|
34
|
+
'The compressor utility to use. Possible values: tgz, zip.',
|
|
35
|
+
type: :string,
|
|
36
|
+
default: 'tgz'
|
|
37
|
+
opt :no_overwrite,
|
|
38
|
+
'Do not overwrite the output file if it already exists.'
|
|
39
|
+
opt :verbose,
|
|
40
|
+
'Verbose output for debugging.'
|
|
41
|
+
opt :quiet,
|
|
42
|
+
'Do not output anything.'
|
|
43
|
+
end
|
|
44
|
+
when 'deploy'
|
|
45
|
+
Trollop::options do
|
|
46
|
+
banner "deploy - Install the application package and all the gems.\n\n" \
|
|
47
|
+
"Options:\n"
|
|
48
|
+
opt :filename,
|
|
49
|
+
'The file deploy',
|
|
50
|
+
type: :string,
|
|
51
|
+
required: true
|
|
52
|
+
opt :directory,
|
|
53
|
+
'The directory where the final package is going to be deployed.',
|
|
54
|
+
type: :string,
|
|
55
|
+
required: true
|
|
56
|
+
opt :verbose,
|
|
57
|
+
'Verbose output for debugging.'
|
|
58
|
+
opt :compressor,
|
|
59
|
+
'The compressor utility to use. Possible values: tgz, zip.',
|
|
60
|
+
type: :string
|
|
61
|
+
end
|
|
62
|
+
when 'list'
|
|
63
|
+
Trollop::options do
|
|
64
|
+
banner "list - List the files to be included in the package.\n\n" \
|
|
65
|
+
"Options:\n"
|
|
66
|
+
opt :config,
|
|
67
|
+
'The config file to use',
|
|
68
|
+
type: :string,
|
|
69
|
+
default: Rubypack::RubypackFile::DEFAULT_FILENAME
|
|
70
|
+
opt :verbose,
|
|
71
|
+
'Verbose output for debugging.'
|
|
72
|
+
end
|
|
73
|
+
else
|
|
74
|
+
Trollop::die "unknown subcommand"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
success = case cmd
|
|
78
|
+
when 'build'
|
|
79
|
+
builder = Rubypack::Builder.new(cmd_opts)
|
|
80
|
+
builder.build!
|
|
81
|
+
when 'deploy'
|
|
82
|
+
deployer = Rubypack::Deployer.new(cmd_opts)
|
|
83
|
+
deployer.deploy!
|
|
84
|
+
when 'list'
|
|
85
|
+
listing = Rubypack::Listing.new(cmd_opts)
|
|
86
|
+
listing.list!
|
|
87
|
+
end
|
|
88
|
+
exit(success ? 0 : 1)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
3
|
+
module Rubypack
|
|
4
|
+
class Builder
|
|
5
|
+
def initialize(options)
|
|
6
|
+
@options = options
|
|
7
|
+
@output = if options[:verbose]
|
|
8
|
+
VerboseOutput.new
|
|
9
|
+
elsif options[:quiet]
|
|
10
|
+
QuietOutput.new
|
|
11
|
+
else
|
|
12
|
+
DefaultOutput.new
|
|
13
|
+
end
|
|
14
|
+
@overwrite = !options[:no_overwrite]
|
|
15
|
+
@output_directory = options[:output_directory]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def build!
|
|
19
|
+
pack = read_rubypack_file
|
|
20
|
+
return false unless pack
|
|
21
|
+
|
|
22
|
+
download_success = download_gems(pack)
|
|
23
|
+
return false unless download_success
|
|
24
|
+
|
|
25
|
+
files = generate_list_of_files(pack)
|
|
26
|
+
return false unless files
|
|
27
|
+
|
|
28
|
+
Dir.mktmpdir do |output_directory|
|
|
29
|
+
copy_files(pack, files, output_directory)
|
|
30
|
+
create_package(pack, output_directory)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
true
|
|
34
|
+
rescue => exception
|
|
35
|
+
@output.error(exception.message)
|
|
36
|
+
verbose(exception.backtrace.join("\n"))
|
|
37
|
+
false
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def read_rubypack_file
|
|
43
|
+
@output.step("Reading #{@options[:config]} file...") do
|
|
44
|
+
RubypackFile.new(filename: @options[:config], output: @output)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def download_gems(pack)
|
|
49
|
+
@output.step('Downloading gems...') do
|
|
50
|
+
bundler = BundlerController.new(path: pack.path)
|
|
51
|
+
bundler.package do |out|
|
|
52
|
+
while line = out.gets do
|
|
53
|
+
@output.verbose(' >', line)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def generate_list_of_files(pack)
|
|
60
|
+
@output.step('Generating list of files...') do
|
|
61
|
+
pack.include(@options[:config])
|
|
62
|
+
pack.include('Gemfile.lock')
|
|
63
|
+
pack.include('vendor/cache/*')
|
|
64
|
+
all_files = pack.list_files
|
|
65
|
+
@output.status(' Files count:', all_files.count)
|
|
66
|
+
all_files
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def copy_files(pack, files, output_directory)
|
|
71
|
+
@output.step('Creating copy of files...') do
|
|
72
|
+
@output.verbose(' Temporal path:', output_directory)
|
|
73
|
+
FileUtils.mkdir_p(output_directory)
|
|
74
|
+
files.each do |file|
|
|
75
|
+
new_file = File.join(output_directory, file)
|
|
76
|
+
directory = File.dirname(new_file)
|
|
77
|
+
FileUtils.mkdir_p(directory) unless Dir.exists?(directory)
|
|
78
|
+
@output.verbose(' =', file)
|
|
79
|
+
FileUtils.copy_entry(File.join(pack.path, file), new_file)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def create_package(pack, output_directory)
|
|
85
|
+
@output.step('Creating package...') do
|
|
86
|
+
compressor = Compressor.new(
|
|
87
|
+
format: @options[:compressor],
|
|
88
|
+
output: @output)
|
|
89
|
+
compressor.compress!(
|
|
90
|
+
path: output_directory,
|
|
91
|
+
output_filename: File.join(@output_directory, pack.output_filename),
|
|
92
|
+
overwrite: @overwrite)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
|
|
2
|
+
module Rubypack
|
|
3
|
+
class BundlerController
|
|
4
|
+
def initialize(path:)
|
|
5
|
+
@path = path
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def package
|
|
9
|
+
begin
|
|
10
|
+
old_pwd = Dir.pwd
|
|
11
|
+
Dir.chdir(@path)
|
|
12
|
+
IO.popen(['bundle', 'package', '--all-platforms', '--all', err: [:child, :out]]) do |out|
|
|
13
|
+
yield(out)
|
|
14
|
+
end
|
|
15
|
+
fail("bundle package failed: #{$?.exitstatus}") unless $?.exitstatus == 0
|
|
16
|
+
true
|
|
17
|
+
rescue => error
|
|
18
|
+
fail("Error executing bundle package: #{error.message}")
|
|
19
|
+
ensure
|
|
20
|
+
Dir.chdir(old_pwd)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def install
|
|
25
|
+
begin
|
|
26
|
+
old_pwd = Dir.pwd
|
|
27
|
+
Dir.chdir(@path)
|
|
28
|
+
IO.popen(['bundle', 'install', '--local', '--deployment', err: [:child, :out]]) do |out|
|
|
29
|
+
yield(out)
|
|
30
|
+
end
|
|
31
|
+
fail("bundle package failed: #{$?.exitstatus}") unless $?.exitstatus == 0
|
|
32
|
+
true
|
|
33
|
+
rescue => error
|
|
34
|
+
fail("Error executing bundle package: #{error.message}")
|
|
35
|
+
ensure
|
|
36
|
+
Dir.chdir(old_pwd)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require_relative 'compressors/all'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
|
|
4
|
+
module Rubypack
|
|
5
|
+
class Compressor
|
|
6
|
+
|
|
7
|
+
def initialize(format:, output:)
|
|
8
|
+
@format = format
|
|
9
|
+
@output = output
|
|
10
|
+
|
|
11
|
+
@compressor = case format
|
|
12
|
+
when 'tgz'
|
|
13
|
+
Compressors::TGZ.new
|
|
14
|
+
when 'zip'
|
|
15
|
+
Compressors::ZIP.new
|
|
16
|
+
else
|
|
17
|
+
fail("Unknown compressor: #{format}")
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def compress!(path:, output_filename:, overwrite:)
|
|
22
|
+
fail("File already exists: #{output_filename}") if !overwrite && File.exists?(output_filename)
|
|
23
|
+
fail("Directory not found: #{path}") unless File.directory?(path)
|
|
24
|
+
output_directory = File.dirname(output_filename)
|
|
25
|
+
fail("Directory not found: #{output_directory}") unless File.directory?(output_directory)
|
|
26
|
+
|
|
27
|
+
begin
|
|
28
|
+
filename = File.expand_path(output_filename + @compressor.extension)
|
|
29
|
+
old_pwd = Dir.pwd
|
|
30
|
+
Dir.chdir(path)
|
|
31
|
+
@compressor.compress(filename: filename) do |out|
|
|
32
|
+
while line = out.gets do
|
|
33
|
+
@output.verbose(' >', line)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
ensure
|
|
37
|
+
Dir.chdir(old_pwd)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
@output.status(' File created: ', filename)
|
|
41
|
+
rescue => exception
|
|
42
|
+
@output.error(exception.message)
|
|
43
|
+
fail('Compression canceled')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def decompress!(filename:, directory:)
|
|
47
|
+
fail("File not found: #{filename}") unless File.exists?(filename)
|
|
48
|
+
fail("Directory already exists: #{directory}") if File.directory?(directory)
|
|
49
|
+
|
|
50
|
+
FileUtils.mkdir_p(directory)
|
|
51
|
+
|
|
52
|
+
begin
|
|
53
|
+
full_filename = File.expand_path(filename)
|
|
54
|
+
old_pwd = Dir.pwd
|
|
55
|
+
Dir.chdir(directory)
|
|
56
|
+
@compressor.decompress(filename: full_filename) do |out|
|
|
57
|
+
while line = out.gets do
|
|
58
|
+
@output.verbose(' >', line)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
ensure
|
|
62
|
+
Dir.chdir(old_pwd)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
@output.status(' Directory created: ', directory)
|
|
66
|
+
rescue => exception
|
|
67
|
+
@output.error(exception.message)
|
|
68
|
+
fail('Decompression canceled')
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
module Rubypack
|
|
3
|
+
module Compressors
|
|
4
|
+
class TGZ
|
|
5
|
+
def compress(filename:)
|
|
6
|
+
IO.popen(['tar', '-zcvf', filename, './', err: [:child, :out]]) do |out|
|
|
7
|
+
yield(out)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def decompress(filename:)
|
|
12
|
+
IO.popen(['tar', '-zxvf', filename, err: [:child, :out]]) do |out|
|
|
13
|
+
yield(out)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def extension
|
|
18
|
+
'.tgz.rpack'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
module Rubypack
|
|
3
|
+
module Compressors
|
|
4
|
+
class ZIP
|
|
5
|
+
def compress(filename:)
|
|
6
|
+
IO.popen(['zip', '-r', filename, './', err: [:child, :out]]) do |out|
|
|
7
|
+
yield(out)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def decompress(filename:)
|
|
12
|
+
IO.popen(['unzip', filename, err: [:child, :out]]) do |out|
|
|
13
|
+
yield(out)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def extension
|
|
18
|
+
'.zip.rpack'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
3
|
+
module Rubypack
|
|
4
|
+
class Deployer
|
|
5
|
+
def initialize(options)
|
|
6
|
+
@options = options
|
|
7
|
+
@output = if options[:verbose]
|
|
8
|
+
VerboseOutput.new
|
|
9
|
+
elsif options[:quiet]
|
|
10
|
+
QuietOutput.new
|
|
11
|
+
else
|
|
12
|
+
DefaultOutput.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
@filename = options[:filename]
|
|
16
|
+
@directory = options[:directory]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def deploy!
|
|
20
|
+
success = unpack_file
|
|
21
|
+
return unless success
|
|
22
|
+
|
|
23
|
+
success = install_gems
|
|
24
|
+
return false unless success
|
|
25
|
+
|
|
26
|
+
true
|
|
27
|
+
rescue => exception
|
|
28
|
+
@output.error(exception.message)
|
|
29
|
+
verbose(exception.backtrace.join("\n"))
|
|
30
|
+
false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def unpack_file
|
|
36
|
+
@output.step('Unpacking file...') do
|
|
37
|
+
if @options[:compressor]
|
|
38
|
+
format = @options[:compressor]
|
|
39
|
+
elsif @filename =~ /\.([a-z]+)\.rpack$/
|
|
40
|
+
format = $1
|
|
41
|
+
else
|
|
42
|
+
@output.error("Unknown package format")
|
|
43
|
+
return false
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
compressor = Compressor.new(
|
|
47
|
+
format: format,
|
|
48
|
+
output: @output)
|
|
49
|
+
compressor.decompress!(
|
|
50
|
+
filename: @filename,
|
|
51
|
+
directory: @directory)
|
|
52
|
+
|
|
53
|
+
true
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def install_gems
|
|
58
|
+
@output.step('Installing gems...') do
|
|
59
|
+
bundler = BundlerController.new(path: @directory)
|
|
60
|
+
bundler.install do |out|
|
|
61
|
+
while line = out.gets do
|
|
62
|
+
@output.verbose(' >', line)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
3
|
+
module Rubypack
|
|
4
|
+
class Listing
|
|
5
|
+
def initialize(options)
|
|
6
|
+
@options = options
|
|
7
|
+
@output = VerboseOutput.new
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def list!
|
|
11
|
+
pack = RubypackFile.new(filename: @options[:config], output: @output)
|
|
12
|
+
pack.include(@options[:config])
|
|
13
|
+
pack.include('vendor/cache/*')
|
|
14
|
+
files = pack.list_files
|
|
15
|
+
@output.status(' Files count:', files.count)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
|
|
2
|
+
module Rubypack
|
|
3
|
+
class RubypackFile
|
|
4
|
+
DEFAULT_FILENAME = '.rubypack'
|
|
5
|
+
|
|
6
|
+
attr_accessor :path
|
|
7
|
+
|
|
8
|
+
def initialize(filename:, output:)
|
|
9
|
+
fail("File not found: #{filename}") unless File.exists?(filename)
|
|
10
|
+
@filename = File.basename(filename)
|
|
11
|
+
@path = File.dirname(filename)
|
|
12
|
+
@output = output
|
|
13
|
+
read!
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def read!
|
|
17
|
+
instance_exec { eval(File.read(File.join(@path, @filename))) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def name(name)
|
|
21
|
+
@output.status(' Name:', name)
|
|
22
|
+
@name = name
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def version(version)
|
|
26
|
+
@output.status(' Version:', version)
|
|
27
|
+
@version = version
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def output_filename
|
|
31
|
+
"#{@name}-#{@version}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def run(command)
|
|
35
|
+
@command = command
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def include(*args)
|
|
39
|
+
@rules = [] unless defined?(@rules)
|
|
40
|
+
args.each { |entry| @rules << { action: :include, filter: entry } }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def exclude(*args)
|
|
44
|
+
@rules = [] unless defined?(@rules)
|
|
45
|
+
args.each { |entry| @rules << { action: :exclude, filter: entry } }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def format_rule(rule, files)
|
|
49
|
+
@output.status(" Action: #{rule[:action]}, Filter: #{rule[:filter]}")
|
|
50
|
+
icon = (rule[:action] == :include) ? ' +' : ' -'
|
|
51
|
+
files.each { |file| @output.verbose(icon, file) }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def list_files
|
|
55
|
+
old_pwd = Dir.pwd
|
|
56
|
+
Dir.chdir(@path)
|
|
57
|
+
|
|
58
|
+
# If not rules were defined, include all by default
|
|
59
|
+
unless defined?(@rules)
|
|
60
|
+
files = Dir['**/**']
|
|
61
|
+
format_rule({ action: :include, filter: '**/**' }, files)
|
|
62
|
+
return ffiles
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Determinate if the package must start with all files or with none
|
|
66
|
+
action = @rules.first[:action]
|
|
67
|
+
if action == :include
|
|
68
|
+
files = []
|
|
69
|
+
elsif action == :exclude
|
|
70
|
+
files = Dir['**/**']
|
|
71
|
+
format_rule({ action: :include, filter: '**/**' }, files)
|
|
72
|
+
else
|
|
73
|
+
fail("Action not implemented: #{action}")
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Include/exclude based on the rules
|
|
77
|
+
@rules.each do |rule|
|
|
78
|
+
if rule[:action] == :include
|
|
79
|
+
filtered_files = Dir[rule[:filter]]
|
|
80
|
+
files |= filtered_files
|
|
81
|
+
format_rule(rule, filtered_files)
|
|
82
|
+
elsif rule[:action] == :exclude
|
|
83
|
+
filtered_files = Dir[rule[:filter]]
|
|
84
|
+
files -= filtered_files
|
|
85
|
+
format_rule(rule, filtered_files)
|
|
86
|
+
else
|
|
87
|
+
fail("Action not implemented: #{rule[:action]}")
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Remove directories
|
|
92
|
+
files.reject! { |file| File.directory?(file) }
|
|
93
|
+
|
|
94
|
+
# Sort the file names
|
|
95
|
+
files.sort
|
|
96
|
+
ensure
|
|
97
|
+
Dir.chdir(old_pwd)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
|
|
2
|
+
module Rubypack
|
|
3
|
+
# Class used to supress all message to the stdout/stderr.
|
|
4
|
+
class QuietOutput
|
|
5
|
+
def step(action)
|
|
6
|
+
status(action)
|
|
7
|
+
result = yield
|
|
8
|
+
status(' [ OK ]')
|
|
9
|
+
result
|
|
10
|
+
rescue => exception
|
|
11
|
+
error(' [ FAIL ]', exception.message)
|
|
12
|
+
verbose(exception.backtrace.join("\n"))
|
|
13
|
+
nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def status(*messages)
|
|
17
|
+
# nothing to do
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def verbose(*messages)
|
|
21
|
+
# nothing to do
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def error(*messages)
|
|
25
|
+
# nothing to do
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Class used to display all the normal messages to stdout and stderr.
|
|
30
|
+
class DefaultOutput < QuietOutput
|
|
31
|
+
def status(*messages)
|
|
32
|
+
$stdout.puts(messages.join(' '))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def error(*messages)
|
|
36
|
+
$stderr.puts(messages.join(' '))
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Class used to display all the messages to stdout and stderr including the debug information
|
|
41
|
+
class VerboseOutput < DefaultOutput
|
|
42
|
+
def verbose(*messages)
|
|
43
|
+
$stdout.puts(messages.join(' '))
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/rubypack/version.rb
CHANGED
data/lib/rubypack.rb
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
require
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
require 'rubypack/version'
|
|
2
|
+
require_relative 'rubypack/shell_output'
|
|
3
|
+
require_relative 'rubypack/rubypack_file'
|
|
4
|
+
require_relative 'rubypack/builder'
|
|
5
|
+
require_relative 'rubypack/deployer'
|
|
6
|
+
require_relative 'rubypack/listing'
|
|
7
|
+
require_relative 'rubypack/compressor'
|
|
8
|
+
require_relative 'rubypack/bundler_controller'
|
data/rubypack.gemspec
CHANGED
|
@@ -4,23 +4,26 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
4
4
|
require 'rubypack/version'
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name =
|
|
7
|
+
spec.name = 'rubypack'
|
|
8
8
|
spec.version = Rubypack::VERSION
|
|
9
|
-
spec.authors = [
|
|
10
|
-
spec.email = [
|
|
9
|
+
spec.authors = ['Jorge del Rio']
|
|
10
|
+
spec.email = ['jorge.delrio@kueski.com']
|
|
11
11
|
|
|
12
|
-
spec.summary =
|
|
13
|
-
spec.description =
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
spec.summary = 'Gem to build and deploy packages of your application'
|
|
13
|
+
spec.description = 'This gem provides some utilities to build a package of your application' +
|
|
14
|
+
' with aims to provide a runnable standalone application that can be shared' +
|
|
15
|
+
' or deployed in production systems.'
|
|
16
|
+
spec.homepage = 'https://github.com/newint33h/rubypack.git'
|
|
17
|
+
spec.license = 'MIT'
|
|
16
18
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
17
19
|
f.match(%r{^(test|spec|features)/})
|
|
18
20
|
end
|
|
19
|
-
spec.bindir =
|
|
20
|
-
spec.executables = spec.files.grep(%r{^
|
|
21
|
-
spec.require_paths = [
|
|
21
|
+
spec.bindir = 'bin'
|
|
22
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
23
|
+
spec.require_paths = ['lib']
|
|
22
24
|
|
|
23
|
-
spec.add_development_dependency
|
|
24
|
-
spec.add_development_dependency
|
|
25
|
-
spec.add_development_dependency
|
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.14'
|
|
26
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
28
|
+
spec.add_development_dependency 'trollop', '~> 2.1'
|
|
26
29
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubypack
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jorge del Rio
|
|
8
8
|
autorequire:
|
|
9
|
-
bindir:
|
|
9
|
+
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-05-
|
|
11
|
+
date: 2017-05-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -52,12 +52,27 @@ dependencies:
|
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '3.0'
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: trollop
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '2.1'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '2.1'
|
|
69
|
+
description: This gem provides some utilities to build a package of your application
|
|
70
|
+
with aims to provide a runnable standalone application that can be shared or deployed
|
|
71
|
+
in production systems.
|
|
58
72
|
email:
|
|
59
73
|
- jorge.delrio@kueski.com
|
|
60
|
-
executables:
|
|
74
|
+
executables:
|
|
75
|
+
- rubypack
|
|
61
76
|
extensions: []
|
|
62
77
|
extra_rdoc_files: []
|
|
63
78
|
files:
|
|
@@ -68,9 +83,18 @@ files:
|
|
|
68
83
|
- Gemfile
|
|
69
84
|
- README.md
|
|
70
85
|
- Rakefile
|
|
71
|
-
- bin/
|
|
72
|
-
- bin/setup
|
|
86
|
+
- bin/rubypack
|
|
73
87
|
- lib/rubypack.rb
|
|
88
|
+
- lib/rubypack/builder.rb
|
|
89
|
+
- lib/rubypack/bundler_controller.rb
|
|
90
|
+
- lib/rubypack/compressor.rb
|
|
91
|
+
- lib/rubypack/compressors/all.rb
|
|
92
|
+
- lib/rubypack/compressors/tgz_compressor.rb
|
|
93
|
+
- lib/rubypack/compressors/zip_compressor.rb
|
|
94
|
+
- lib/rubypack/deployer.rb
|
|
95
|
+
- lib/rubypack/listing.rb
|
|
96
|
+
- lib/rubypack/rubypack_file.rb
|
|
97
|
+
- lib/rubypack/shell_output.rb
|
|
74
98
|
- lib/rubypack/version.rb
|
|
75
99
|
- rubypack.gemspec
|
|
76
100
|
homepage: https://github.com/newint33h/rubypack.git
|
|
@@ -96,5 +120,5 @@ rubyforge_project:
|
|
|
96
120
|
rubygems_version: 2.5.1
|
|
97
121
|
signing_key:
|
|
98
122
|
specification_version: 4
|
|
99
|
-
summary: Gem to build and
|
|
123
|
+
summary: Gem to build and deploy packages of your application
|
|
100
124
|
test_files: []
|
data/bin/console
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
require "bundler/setup"
|
|
4
|
-
require "rubypack"
|
|
5
|
-
|
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
-
|
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
-
# require "pry"
|
|
11
|
-
# Pry.start
|
|
12
|
-
|
|
13
|
-
require "irb"
|
|
14
|
-
IRB.start(__FILE__)
|