appbundler 0.6.0 → 0.7.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 +16 -16
- data/.rspec +2 -2
- data/.travis.yml +16 -12
- data/Gemfile +4 -4
- data/LICENSE.txt +202 -202
- data/README.md +70 -70
- data/Rakefile +1 -1
- data/appbundler.gemspec +27 -27
- data/bin/appbundler +13 -13
- data/lib/appbundler.rb +4 -4
- data/lib/appbundler/app.rb +194 -192
- data/lib/appbundler/cli.rb +113 -113
- data/lib/appbundler/version.rb +3 -3
- data/spec/appbundler/app_spec.rb +421 -421
- data/spec/fixtures/appbundler-example-app/.bundle/config +2 -2
- data/spec/fixtures/appbundler-example-app/Gemfile +2 -2
- data/spec/fixtures/appbundler-example-app/Gemfile.lock.unix +135 -135
- data/spec/fixtures/appbundler-example-app/Gemfile.lock.windows +172 -172
- data/spec/fixtures/appbundler-example-app/README.md +3 -3
- data/spec/fixtures/appbundler-example-app/appbundler-example-app.gemspec +22 -22
- data/spec/fixtures/appbundler-example-app/bin/app-binary-1 +2 -2
- data/spec/fixtures/appbundler-example-app/bin/app-binary-2 +2 -2
- data/spec/fixtures/appbundler-example-app/lib/example_app.rb +3 -3
- data/spec/spec_helper.rb +9 -9
- metadata +3 -3
data/lib/appbundler/cli.rb
CHANGED
@@ -1,113 +1,113 @@
|
|
1
|
-
require 'appbundler/version'
|
2
|
-
require 'appbundler/app'
|
3
|
-
require 'mixlib/cli'
|
4
|
-
|
5
|
-
module Appbundler
|
6
|
-
class CLI
|
7
|
-
include Mixlib::CLI
|
8
|
-
|
9
|
-
banner(<<-BANNER)
|
10
|
-
Usage: appbundler APPLICATION_DIR BINSTUB_DIR
|
11
|
-
|
12
|
-
APPLICATION_DIR is the root directory to a working copy of your app
|
13
|
-
BINSTUB_DIR is the directory where you want generated executables to be written
|
14
|
-
|
15
|
-
Your bundled application must already be gem installed. Generated binstubs
|
16
|
-
will point to the gem, not your working copy.
|
17
|
-
BANNER
|
18
|
-
|
19
|
-
option :version,
|
20
|
-
:short => '-v',
|
21
|
-
:long => '--version',
|
22
|
-
:description => 'Show appbundler version',
|
23
|
-
:boolean => true,
|
24
|
-
:proc => lambda {|v| $stdout.puts("Appbundler Version: #{::Appbundler::VERSION}")},
|
25
|
-
:exit => 0
|
26
|
-
|
27
|
-
option :help,
|
28
|
-
:short => "-h",
|
29
|
-
:long => "--help",
|
30
|
-
:description => "Show this message",
|
31
|
-
:on => :tail,
|
32
|
-
:boolean => true,
|
33
|
-
:show_options => true,
|
34
|
-
:exit => 0
|
35
|
-
|
36
|
-
def self.run(argv)
|
37
|
-
cli = new(argv)
|
38
|
-
cli.handle_options
|
39
|
-
cli.validate!
|
40
|
-
cli.run
|
41
|
-
end
|
42
|
-
|
43
|
-
attr_reader :argv
|
44
|
-
|
45
|
-
attr_reader :app_path
|
46
|
-
attr_reader :bin_path
|
47
|
-
|
48
|
-
def initialize(argv)
|
49
|
-
@argv = argv
|
50
|
-
super()
|
51
|
-
end
|
52
|
-
|
53
|
-
def handle_options
|
54
|
-
parse_options(@argv)
|
55
|
-
end
|
56
|
-
|
57
|
-
def validate!
|
58
|
-
if cli_arguments.size != 2
|
59
|
-
usage_and_exit!
|
60
|
-
else
|
61
|
-
@app_path = File.expand_path(cli_arguments[0])
|
62
|
-
@bin_path = File.expand_path(cli_arguments[1])
|
63
|
-
verify_app_path
|
64
|
-
verify_bin_path
|
65
|
-
verify_gem_installed
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def verify_app_path
|
70
|
-
if !File.directory?(app_path)
|
71
|
-
err("APPLICATION_DIR `#{app_path}' is not a directory or doesn't exist")
|
72
|
-
usage_and_exit!
|
73
|
-
elsif !File.exist?(File.join(app_path, "Gemfile.lock"))
|
74
|
-
err("APPLICATION_DIR does not contain required Gemfile.lock")
|
75
|
-
usage_and_exit!
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def verify_bin_path
|
80
|
-
if !File.directory?(bin_path)
|
81
|
-
err("BINSTUB_DIR `#{bin_path}' is not a directory or doesn't exist")
|
82
|
-
usage_and_exit!
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def verify_gem_installed
|
87
|
-
app = App.new(app_path, bin_path)
|
88
|
-
app.app_gemspec
|
89
|
-
rescue Gem::LoadError
|
90
|
-
err("Unable to find #{app.app_spec.name} #{app.app_spec.version} installed as a gem")
|
91
|
-
err("You must install the top-level app as a gem before calling app-bundler")
|
92
|
-
usage_and_exit!
|
93
|
-
end
|
94
|
-
|
95
|
-
def run
|
96
|
-
app = App.new(app_path, bin_path)
|
97
|
-
created_stubs = app.write_executable_stubs
|
98
|
-
created_stubs.each do |real_executable_path, stub_path|
|
99
|
-
$stdout.puts "Generated binstub #{stub_path} => #{real_executable_path}"
|
100
|
-
end
|
101
|
-
app.copy_bundler_env
|
102
|
-
end
|
103
|
-
|
104
|
-
def err(message)
|
105
|
-
$stderr.print("#{message}\n")
|
106
|
-
end
|
107
|
-
|
108
|
-
def usage_and_exit!
|
109
|
-
err(banner)
|
110
|
-
exit 1
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
1
|
+
require 'appbundler/version'
|
2
|
+
require 'appbundler/app'
|
3
|
+
require 'mixlib/cli'
|
4
|
+
|
5
|
+
module Appbundler
|
6
|
+
class CLI
|
7
|
+
include Mixlib::CLI
|
8
|
+
|
9
|
+
banner(<<-BANNER)
|
10
|
+
Usage: appbundler APPLICATION_DIR BINSTUB_DIR
|
11
|
+
|
12
|
+
APPLICATION_DIR is the root directory to a working copy of your app
|
13
|
+
BINSTUB_DIR is the directory where you want generated executables to be written
|
14
|
+
|
15
|
+
Your bundled application must already be gem installed. Generated binstubs
|
16
|
+
will point to the gem, not your working copy.
|
17
|
+
BANNER
|
18
|
+
|
19
|
+
option :version,
|
20
|
+
:short => '-v',
|
21
|
+
:long => '--version',
|
22
|
+
:description => 'Show appbundler version',
|
23
|
+
:boolean => true,
|
24
|
+
:proc => lambda {|v| $stdout.puts("Appbundler Version: #{::Appbundler::VERSION}")},
|
25
|
+
:exit => 0
|
26
|
+
|
27
|
+
option :help,
|
28
|
+
:short => "-h",
|
29
|
+
:long => "--help",
|
30
|
+
:description => "Show this message",
|
31
|
+
:on => :tail,
|
32
|
+
:boolean => true,
|
33
|
+
:show_options => true,
|
34
|
+
:exit => 0
|
35
|
+
|
36
|
+
def self.run(argv)
|
37
|
+
cli = new(argv)
|
38
|
+
cli.handle_options
|
39
|
+
cli.validate!
|
40
|
+
cli.run
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :argv
|
44
|
+
|
45
|
+
attr_reader :app_path
|
46
|
+
attr_reader :bin_path
|
47
|
+
|
48
|
+
def initialize(argv)
|
49
|
+
@argv = argv
|
50
|
+
super()
|
51
|
+
end
|
52
|
+
|
53
|
+
def handle_options
|
54
|
+
parse_options(@argv)
|
55
|
+
end
|
56
|
+
|
57
|
+
def validate!
|
58
|
+
if cli_arguments.size != 2
|
59
|
+
usage_and_exit!
|
60
|
+
else
|
61
|
+
@app_path = File.expand_path(cli_arguments[0])
|
62
|
+
@bin_path = File.expand_path(cli_arguments[1])
|
63
|
+
verify_app_path
|
64
|
+
verify_bin_path
|
65
|
+
verify_gem_installed
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def verify_app_path
|
70
|
+
if !File.directory?(app_path)
|
71
|
+
err("APPLICATION_DIR `#{app_path}' is not a directory or doesn't exist")
|
72
|
+
usage_and_exit!
|
73
|
+
elsif !File.exist?(File.join(app_path, "Gemfile.lock"))
|
74
|
+
err("APPLICATION_DIR does not contain required Gemfile.lock")
|
75
|
+
usage_and_exit!
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def verify_bin_path
|
80
|
+
if !File.directory?(bin_path)
|
81
|
+
err("BINSTUB_DIR `#{bin_path}' is not a directory or doesn't exist")
|
82
|
+
usage_and_exit!
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def verify_gem_installed
|
87
|
+
app = App.new(app_path, bin_path)
|
88
|
+
app.app_gemspec
|
89
|
+
rescue Gem::LoadError
|
90
|
+
err("Unable to find #{app.app_spec.name} #{app.app_spec.version} installed as a gem")
|
91
|
+
err("You must install the top-level app as a gem before calling app-bundler")
|
92
|
+
usage_and_exit!
|
93
|
+
end
|
94
|
+
|
95
|
+
def run
|
96
|
+
app = App.new(app_path, bin_path)
|
97
|
+
created_stubs = app.write_executable_stubs
|
98
|
+
created_stubs.each do |real_executable_path, stub_path|
|
99
|
+
$stdout.puts "Generated binstub #{stub_path} => #{real_executable_path}"
|
100
|
+
end
|
101
|
+
app.copy_bundler_env
|
102
|
+
end
|
103
|
+
|
104
|
+
def err(message)
|
105
|
+
$stderr.print("#{message}\n")
|
106
|
+
end
|
107
|
+
|
108
|
+
def usage_and_exit!
|
109
|
+
err(banner)
|
110
|
+
exit 1
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
data/lib/appbundler/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Appbundler
|
2
|
-
VERSION = "0.
|
3
|
-
end
|
1
|
+
module Appbundler
|
2
|
+
VERSION = "0.7.0"
|
3
|
+
end
|
data/spec/appbundler/app_spec.rb
CHANGED
@@ -1,421 +1,421 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'tmpdir'
|
3
|
-
require 'fileutils'
|
4
|
-
require 'mixlib/shellout'
|
5
|
-
require 'appbundler/app'
|
6
|
-
|
7
|
-
describe Appbundler do
|
8
|
-
|
9
|
-
def all_specs
|
10
|
-
@all_specs ||= []
|
11
|
-
end
|
12
|
-
|
13
|
-
def double_spec(name, version, dep_names)
|
14
|
-
deps = dep_names.map {|n| double("Bundler::Dependency #{n}", :name => n.to_s) }
|
15
|
-
spec = double("Bundler::LazySpecification '#{name}'", :name => name.to_s, :version => version, :dependencies => deps)
|
16
|
-
all_specs << spec
|
17
|
-
spec
|
18
|
-
end
|
19
|
-
|
20
|
-
def shellout!(cmd)
|
21
|
-
s = Mixlib::ShellOut.new(cmd, :env => {"RUBYOPT" => nil, "BUNDLE_GEMFILE" => nil, "APPBUNDLER_ALLOW_RVM" => "true"})
|
22
|
-
s.run_command
|
23
|
-
s.error!
|
24
|
-
s
|
25
|
-
end
|
26
|
-
|
27
|
-
def target_bindir
|
28
|
-
File.expand_path("../../test-tmp/bin", __FILE__)
|
29
|
-
end
|
30
|
-
|
31
|
-
context "given an app with multiple levels of dependencies" do
|
32
|
-
|
33
|
-
let!(:second_level_dep_a_a) do
|
34
|
-
double_spec(:second_level_dep_a_a, "2.1.0", [])
|
35
|
-
end
|
36
|
-
|
37
|
-
let!(:second_level_dep_shared) do
|
38
|
-
double_spec(:second_level_dep_shared, "2.3.0", [])
|
39
|
-
end
|
40
|
-
|
41
|
-
let!(:second_level_dep_b_a) do
|
42
|
-
double_spec(:second_level_dep_b_a, "2.2.0", [])
|
43
|
-
end
|
44
|
-
|
45
|
-
let!(:first_level_dep_a) do
|
46
|
-
double_spec(:first_level_dep_a, "1.1.0", [:second_level_dep_a_a, :second_level_dep_shared])
|
47
|
-
end
|
48
|
-
|
49
|
-
let!(:first_level_dep_b) do
|
50
|
-
double_spec(:first_level_dep_b, "1.2.0", [:second_level_dep_b_a, :second_level_dep_shared])
|
51
|
-
end
|
52
|
-
|
53
|
-
let!(:app_spec) do
|
54
|
-
double_spec(:app, "1.0.0", [:first_level_dep_a, :first_level_dep_b])
|
55
|
-
end
|
56
|
-
|
57
|
-
let(:bin_path) { File.join(target_bindir, "foo") }
|
58
|
-
|
59
|
-
let(:app_root) { "/opt/app/embedded/apps/app" }
|
60
|
-
|
61
|
-
let(:app) do
|
62
|
-
Appbundler::App.new(app_root, target_bindir)
|
63
|
-
end
|
64
|
-
|
65
|
-
before do
|
66
|
-
allow(app).to receive(:gemfile_lock_specs).and_return(all_specs)
|
67
|
-
end
|
68
|
-
|
69
|
-
it "finds the running ruby interpreter" do
|
70
|
-
expect(app.ruby).to eq(Gem.ruby)
|
71
|
-
end
|
72
|
-
|
73
|
-
it "finds all runtime dependencies of the app" do
|
74
|
-
# we want to find the minimum set of gems that we need to activate to run
|
75
|
-
# the application. To do this, we look at the app's runtime deps and
|
76
|
-
# recursively search through the list of gemspecs that we got from the
|
77
|
-
# Gemfile.lock, collecting all the runtime deps. This should get us the
|
78
|
-
# smallest possible "activate.rb" file that can launch the application
|
79
|
-
# with locked gem versions.
|
80
|
-
expect(app.runtime_dep_specs).to include(first_level_dep_a)
|
81
|
-
expect(app.runtime_dep_specs).to include(first_level_dep_b)
|
82
|
-
expect(app.runtime_dep_specs).to include(second_level_dep_a_a)
|
83
|
-
expect(app.runtime_dep_specs).to include(second_level_dep_b_a)
|
84
|
-
expect(app.runtime_dep_specs).to include(second_level_dep_shared)
|
85
|
-
expect(app.runtime_dep_specs.select {|s| s == second_level_dep_shared}.size).to eq(1)
|
86
|
-
end
|
87
|
-
|
88
|
-
it "generates gem activation code for the app" do
|
89
|
-
# this is code with a bunch of gem "foo", "= X.Y.Z" statements. The top
|
90
|
-
# level application is _not_ included in this, it's added to the load
|
91
|
-
# path instead.
|
92
|
-
expect(app.runtime_activate).to include(%q{gem "first_level_dep_a", "= 1.1.0"})
|
93
|
-
expect(app.runtime_activate).to include(%q{gem "second_level_dep_a_a", "= 2.1.0"})
|
94
|
-
expect(app.runtime_activate).to include(%q{gem "second_level_dep_shared", "= 2.3.0"})
|
95
|
-
expect(app.runtime_activate).to include(%q{gem "first_level_dep_b", "= 1.2.0"})
|
96
|
-
expect(app.runtime_activate).to include(%q{gem "second_level_dep_b_a", "= 2.2.0"})
|
97
|
-
expect(app.runtime_activate).to_not include(%q{gem "app"})
|
98
|
-
end
|
99
|
-
|
100
|
-
it "locks the main app's gem via rubygems, and loads the proper binary" do
|
101
|
-
expected_loading_code = <<-CODE
|
102
|
-
gem "app", "= 1.0.0"
|
103
|
-
|
104
|
-
spec = Gem::Specification.find_by_name("app", "= 1.0.0")
|
105
|
-
bin_file = spec.bin_file("foo")
|
106
|
-
|
107
|
-
Kernel.load(bin_file)
|
108
|
-
CODE
|
109
|
-
expect(app.load_statement_for(bin_path)).to eq(expected_loading_code)
|
110
|
-
end
|
111
|
-
|
112
|
-
it "generates code to override GEM_HOME and GEM_PATH (e.g., rvm)" do
|
113
|
-
expected = %Q{ENV["GEM_HOME"] = ENV["GEM_PATH"] = nil unless ENV["APPBUNDLER_ALLOW_RVM"] == "true"}
|
114
|
-
expect(app.env_sanitizer).to eq(expected)
|
115
|
-
expect(app.runtime_activate).to include(expected)
|
116
|
-
end
|
117
|
-
|
118
|
-
context "on windows" do
|
119
|
-
|
120
|
-
let(:target_bindir) { "C:/opscode/chef/bin" }
|
121
|
-
|
122
|
-
before do
|
123
|
-
allow(app).to receive(:ruby).and_return("C:/opscode/chef/embedded/bin/ruby.exe")
|
124
|
-
end
|
125
|
-
|
126
|
-
it "computes the relative path to ruby" do
|
127
|
-
expect(app.ruby_relative_path).to eq("../embedded/bin/ruby.exe")
|
128
|
-
end
|
129
|
-
|
130
|
-
it "generates batchfile stub code" do
|
131
|
-
expected_batch_code=<<-E
|
132
|
-
@ECHO OFF
|
133
|
-
"%~dp0\\..\\embedded\\bin\\ruby.exe" "%~dpn0" %*
|
134
|
-
E
|
135
|
-
expect(app.batchfile_stub).to eq(expected_batch_code)
|
136
|
-
end
|
137
|
-
|
138
|
-
end
|
139
|
-
|
140
|
-
end
|
141
|
-
|
142
|
-
context "when created with the example application" do
|
143
|
-
FIXTURES_PATH = File.expand_path("../../fixtures/", __FILE__).freeze
|
144
|
-
|
145
|
-
APP_ROOT = File.join(FIXTURES_PATH, "appbundler-example-app").freeze
|
146
|
-
|
147
|
-
let(:app_root) { APP_ROOT }
|
148
|
-
|
149
|
-
let(:app) do
|
150
|
-
Appbundler::App.new(APP_ROOT, target_bindir)
|
151
|
-
end
|
152
|
-
|
153
|
-
before(:all) do
|
154
|
-
Dir.chdir(APP_ROOT) do
|
155
|
-
if windows?
|
156
|
-
FileUtils.cp("Gemfile.lock.windows", "Gemfile.lock")
|
157
|
-
else
|
158
|
-
FileUtils.cp("Gemfile.lock.unix", "Gemfile.lock")
|
159
|
-
end
|
160
|
-
shellout!("bundle install")
|
161
|
-
shellout!("gem build appbundler-example-app.gemspec")
|
162
|
-
shellout!("gem install appbundler-example-app-1.0.0.gem")
|
163
|
-
Gem.clear_paths
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
before do
|
168
|
-
FileUtils.rm_rf(target_bindir) if File.exist?(target_bindir)
|
169
|
-
FileUtils.mkdir_p(target_bindir)
|
170
|
-
end
|
171
|
-
|
172
|
-
after(:all) do
|
173
|
-
shellout!("gem uninstall appbundler-example-app -a -q -x")
|
174
|
-
FileUtils.rm_rf(target_bindir) if File.exist?(target_bindir)
|
175
|
-
FileUtils.rm(File.join(APP_ROOT, "Gemfile.lock"))
|
176
|
-
end
|
177
|
-
|
178
|
-
it "initializes ok" do
|
179
|
-
app
|
180
|
-
end
|
181
|
-
|
182
|
-
it "names the app using the directory basename" do
|
183
|
-
expect(app.name).to eq("appbundler-example-app")
|
184
|
-
end
|
185
|
-
|
186
|
-
it "lists the app's dependencies" do
|
187
|
-
# only runtime deps
|
188
|
-
expect(app.app_dependency_names).to eq(["chef"])
|
189
|
-
end
|
190
|
-
|
191
|
-
it "generates runtime activation code for the app" do
|
192
|
-
expected_gem_activates= if windows?
|
193
|
-
<<-E
|
194
|
-
ENV["GEM_HOME"] = ENV["GEM_PATH"] = nil unless ENV["APPBUNDLER_ALLOW_RVM"] == "true"
|
195
|
-
gem "chef", "= 12.4.1"
|
196
|
-
gem "chef-config", "= 12.4.1"
|
197
|
-
gem "mixlib-config", "= 2.2.1"
|
198
|
-
gem "mixlib-shellout", "= 2.2.0"
|
199
|
-
gem "win32-process", "= 0.7.5"
|
200
|
-
gem "ffi", "= 1.9.10"
|
201
|
-
gem "chef-zero", "= 4.3.0"
|
202
|
-
gem "ffi-yajl", "= 2.2.2"
|
203
|
-
gem "libyajl2", "= 1.2.0"
|
204
|
-
gem "hashie", "= 2.1.2"
|
205
|
-
gem "mixlib-log", "= 1.6.0"
|
206
|
-
gem "rack", "= 1.6.4"
|
207
|
-
gem "uuidtools", "= 2.1.5"
|
208
|
-
gem "diff-lcs", "= 1.2.5"
|
209
|
-
gem "erubis", "= 2.7.0"
|
210
|
-
gem "highline", "= 1.7.3"
|
211
|
-
gem "mixlib-authentication", "= 1.3.0"
|
212
|
-
gem "mixlib-cli", "= 1.5.0"
|
213
|
-
gem "net-ssh", "= 2.9.2"
|
214
|
-
gem "net-ssh-multi", "= 1.2.1"
|
215
|
-
gem "net-ssh-gateway", "= 1.2.0"
|
216
|
-
gem "ohai", "= 8.5.1"
|
217
|
-
gem "ipaddress", "= 0.8.0"
|
218
|
-
gem "mime-types", "= 2.6.1"
|
219
|
-
gem "rake", "= 10.1.1"
|
220
|
-
gem "systemu", "= 2.6.5"
|
221
|
-
gem "wmi-lite", "= 1.0.0"
|
222
|
-
gem "plist", "= 3.1.0"
|
223
|
-
gem "pry", "= 0.9.12.6"
|
224
|
-
gem "coderay", "= 1.1.0"
|
225
|
-
gem "method_source", "= 0.8.2"
|
226
|
-
gem "slop", "= 3.4.7"
|
227
|
-
gem "win32console", "= 1.3.2"
|
228
|
-
gem "rspec-core", "= 3.3.2"
|
229
|
-
gem "rspec-support", "= 3.3.0"
|
230
|
-
gem "rspec-expectations", "= 3.3.1"
|
231
|
-
gem "rspec-mocks", "= 3.3.2"
|
232
|
-
gem "rspec_junit_formatter", "= 0.2.3"
|
233
|
-
gem "builder", "= 3.2.2"
|
234
|
-
gem "serverspec", "= 2.23.1"
|
235
|
-
gem "multi_json", "= 1.11.2"
|
236
|
-
gem "rspec", "= 3.3.0"
|
237
|
-
gem "rspec-its", "= 1.2.0"
|
238
|
-
gem "specinfra", "= 2.43.3"
|
239
|
-
gem "net-scp", "= 1.2.1"
|
240
|
-
gem "net-telnet", "= 0.1.1"
|
241
|
-
gem "sfl", "= 2.2"
|
242
|
-
gem "syslog-logger", "= 1.6.8"
|
243
|
-
gem "win32-api", "= 1.5.3"
|
244
|
-
gem "win32-dir", "= 0.5.0"
|
245
|
-
gem "win32-event", "= 0.6.1"
|
246
|
-
gem "win32-ipc", "= 0.6.6"
|
247
|
-
gem "win32-eventlog", "= 0.6.3"
|
248
|
-
gem "win32-mmap", "= 0.4.1"
|
249
|
-
gem "win32-mutex", "= 0.4.2"
|
250
|
-
gem "win32-service", "= 0.8.6"
|
251
|
-
gem "windows-api", "= 0.4.4"
|
252
|
-
gem "windows-pr", "= 1.2.4"
|
253
|
-
E
|
254
|
-
else
|
255
|
-
<<-E
|
256
|
-
ENV["GEM_HOME"] = ENV["GEM_PATH"] = nil unless ENV["APPBUNDLER_ALLOW_RVM"] == "true"
|
257
|
-
gem "chef", "= 12.4.1"
|
258
|
-
gem "chef-config", "= 12.4.1"
|
259
|
-
gem "mixlib-config", "= 2.2.1"
|
260
|
-
gem "mixlib-shellout", "= 2.2.0"
|
261
|
-
gem "chef-zero", "= 4.3.0"
|
262
|
-
gem "ffi-yajl", "= 2.2.2"
|
263
|
-
gem "libyajl2", "= 1.2.0"
|
264
|
-
gem "hashie", "= 2.1.2"
|
265
|
-
gem "mixlib-log", "= 1.6.0"
|
266
|
-
gem "rack", "= 1.6.4"
|
267
|
-
gem "uuidtools", "= 2.1.5"
|
268
|
-
gem "diff-lcs", "= 1.2.5"
|
269
|
-
gem "erubis", "= 2.7.0"
|
270
|
-
gem "highline", "= 1.7.3"
|
271
|
-
gem "mixlib-authentication", "= 1.3.0"
|
272
|
-
gem "mixlib-cli", "= 1.5.0"
|
273
|
-
gem "net-ssh", "= 2.9.2"
|
274
|
-
gem "net-ssh-multi", "= 1.2.1"
|
275
|
-
gem "net-ssh-gateway", "= 1.2.0"
|
276
|
-
gem "ohai", "= 8.5.1"
|
277
|
-
gem "ffi", "= 1.9.10"
|
278
|
-
gem "ipaddress", "= 0.8.0"
|
279
|
-
gem "mime-types", "= 2.6.1"
|
280
|
-
gem "rake", "= 10.1.1"
|
281
|
-
gem "systemu", "= 2.6.5"
|
282
|
-
gem "wmi-lite", "= 1.0.0"
|
283
|
-
gem "plist", "= 3.1.0"
|
284
|
-
gem "pry", "= 0.9.12.6"
|
285
|
-
gem "coderay", "= 1.1.0"
|
286
|
-
gem "method_source", "= 0.8.2"
|
287
|
-
gem "slop", "= 3.4.7"
|
288
|
-
gem "rspec-core", "= 3.3.2"
|
289
|
-
gem "rspec-support", "= 3.3.0"
|
290
|
-
gem "rspec-expectations", "= 3.3.1"
|
291
|
-
gem "rspec-mocks", "= 3.3.2"
|
292
|
-
gem "rspec_junit_formatter", "= 0.2.3"
|
293
|
-
gem "builder", "= 3.2.2"
|
294
|
-
gem "serverspec", "= 2.23.1"
|
295
|
-
gem "multi_json", "= 1.11.2"
|
296
|
-
gem "rspec", "= 3.3.0"
|
297
|
-
gem "rspec-its", "= 1.2.0"
|
298
|
-
gem "specinfra", "= 2.43.3"
|
299
|
-
gem "net-scp", "= 1.2.1"
|
300
|
-
gem "net-telnet", "= 0.1.1"
|
301
|
-
gem "sfl", "= 2.2"
|
302
|
-
gem "syslog-logger", "= 1.6.8"
|
303
|
-
E
|
304
|
-
end
|
305
|
-
expect(app.runtime_activate).to include(expected_gem_activates)
|
306
|
-
end
|
307
|
-
|
308
|
-
it "lists the app's executables" do
|
309
|
-
spec = Gem::Specification.find_by_name("appbundler-example-app", "= 1.0.0")
|
310
|
-
expected_executables = %w[app-binary-1 app-binary-2].map do |basename|
|
311
|
-
File.join(spec.gem_dir, "/bin", basename)
|
312
|
-
end
|
313
|
-
expect(app.executables).to match_array(expected_executables)
|
314
|
-
end
|
315
|
-
|
316
|
-
it "generates an executable 'stub' for an executable in the app" do
|
317
|
-
app_binary_1_path = app.executables.grep(/app\-binary\-1/).first
|
318
|
-
executable_content = app.binstub(app_binary_1_path)
|
319
|
-
|
320
|
-
shebang = executable_content.lines.first
|
321
|
-
expect(shebang).to match(/^\#\!/)
|
322
|
-
expect(shebang).to include(Gem.ruby)
|
323
|
-
|
324
|
-
expect(executable_content).to include(app.runtime_activate)
|
325
|
-
|
326
|
-
load_binary = executable_content.lines.to_a.last
|
327
|
-
|
328
|
-
expected_load_path = %Q[Kernel.load(bin_file)\n]
|
329
|
-
|
330
|
-
expect(load_binary).to eq(expected_load_path)
|
331
|
-
end
|
332
|
-
|
333
|
-
it "generates executable stubs for all executables in the app" do
|
334
|
-
app.write_executable_stubs
|
335
|
-
binary_1 = File.join(target_bindir, "app-binary-1")
|
336
|
-
binary_2 = File.join(target_bindir, "app-binary-2")
|
337
|
-
expect(File.exist?(binary_1)).to be(true)
|
338
|
-
expect(File.exist?(binary_2)).to be(true)
|
339
|
-
expect(File.executable?(binary_1) || File.exists?(binary_1 + ".bat")).to be(true)
|
340
|
-
expect(File.executable?(binary_1) || File.exists?(binary_1 + ".bat")).to be(true)
|
341
|
-
expect(shellout!(binary_1).stdout.strip).to eq("binary 1 ran")
|
342
|
-
expect(shellout!(binary_2).stdout.strip).to eq("binary 2 ran")
|
343
|
-
end
|
344
|
-
|
345
|
-
it "copies over Gemfile.lock to the gem directory" do
|
346
|
-
spec = Gem::Specification.find_by_name("appbundler-example-app", "= 1.0.0")
|
347
|
-
gem_path = spec.gem_dir
|
348
|
-
app.copy_bundler_env
|
349
|
-
expect(File.exists?(File.join(gem_path, 'Gemfile.lock'))).to be(true)
|
350
|
-
end
|
351
|
-
|
352
|
-
it "copies over .bundler to the gem directory" do
|
353
|
-
spec = Gem::Specification.find_by_name("appbundler-example-app", "= 1.0.0")
|
354
|
-
gem_path = spec.gem_dir
|
355
|
-
app.copy_bundler_env
|
356
|
-
expect(File.directory?(File.join(gem_path, '.bundle'))).to be(true)
|
357
|
-
expect(File.exists?(File.join(gem_path, '.bundle/config'))).to be(true)
|
358
|
-
end
|
359
|
-
context "and the executable is symlinked to a different directory", :not_supported_on_windows do
|
360
|
-
|
361
|
-
let(:symlinks_root_dir) do
|
362
|
-
Dir.mktmpdir
|
363
|
-
end
|
364
|
-
|
365
|
-
let(:symlinks_bin_dir) do
|
366
|
-
d = File.join(symlinks_root_dir, "bin")
|
367
|
-
FileUtils.mkdir(d)
|
368
|
-
d
|
369
|
-
end
|
370
|
-
|
371
|
-
let(:binary_symlinked_path) { File.join(symlinks_bin_dir, "app-binary-1") }
|
372
|
-
|
373
|
-
let(:binary_orignal_path) { File.join(target_bindir, "app-binary-1") }
|
374
|
-
|
375
|
-
before do
|
376
|
-
app.write_executable_stubs
|
377
|
-
FileUtils.ln_s(binary_orignal_path, binary_symlinked_path)
|
378
|
-
end
|
379
|
-
|
380
|
-
after do
|
381
|
-
FileUtils.rm_rf(symlinks_root_dir)
|
382
|
-
end
|
383
|
-
|
384
|
-
it "correctly runs the executable via the symlinked executable" do
|
385
|
-
expect(shellout!(binary_symlinked_path).stdout).to eq("binary 1 ran\n")
|
386
|
-
end
|
387
|
-
|
388
|
-
end
|
389
|
-
|
390
|
-
context "on windows" do
|
391
|
-
|
392
|
-
let(:expected_ruby_relpath) do
|
393
|
-
app.ruby_relative_path.gsub('/', '\\')
|
394
|
-
end
|
395
|
-
|
396
|
-
let(:expected_batch_code) do
|
397
|
-
<<-E
|
398
|
-
@ECHO OFF
|
399
|
-
"%~dp0\\#{expected_ruby_relpath}" "%~dpn0" %*
|
400
|
-
E
|
401
|
-
end
|
402
|
-
|
403
|
-
before do
|
404
|
-
stub_const("RUBY_PLATFORM", "mingw")
|
405
|
-
end
|
406
|
-
|
407
|
-
it "creates a batchfile wrapper for each executable" do
|
408
|
-
app.write_executable_stubs
|
409
|
-
binary_1 = File.join(target_bindir, "app-binary-1.bat")
|
410
|
-
binary_2 = File.join(target_bindir, "app-binary-2.bat")
|
411
|
-
expect(File.exist?(binary_1)).to be(true)
|
412
|
-
expect(File.exist?(binary_2)).to be(true)
|
413
|
-
expect(IO.read(binary_1)).to eq(expected_batch_code)
|
414
|
-
expect(IO.read(binary_2)).to eq(expected_batch_code)
|
415
|
-
end
|
416
|
-
|
417
|
-
end
|
418
|
-
|
419
|
-
end
|
420
|
-
|
421
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tmpdir'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'mixlib/shellout'
|
5
|
+
require 'appbundler/app'
|
6
|
+
|
7
|
+
describe Appbundler do
|
8
|
+
|
9
|
+
def all_specs
|
10
|
+
@all_specs ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def double_spec(name, version, dep_names)
|
14
|
+
deps = dep_names.map {|n| double("Bundler::Dependency #{n}", :name => n.to_s) }
|
15
|
+
spec = double("Bundler::LazySpecification '#{name}'", :name => name.to_s, :version => version, :dependencies => deps)
|
16
|
+
all_specs << spec
|
17
|
+
spec
|
18
|
+
end
|
19
|
+
|
20
|
+
def shellout!(cmd)
|
21
|
+
s = Mixlib::ShellOut.new(cmd, :env => {"RUBYOPT" => nil, "BUNDLE_GEMFILE" => nil, "APPBUNDLER_ALLOW_RVM" => "true"})
|
22
|
+
s.run_command
|
23
|
+
s.error!
|
24
|
+
s
|
25
|
+
end
|
26
|
+
|
27
|
+
def target_bindir
|
28
|
+
File.expand_path("../../test-tmp/bin", __FILE__)
|
29
|
+
end
|
30
|
+
|
31
|
+
context "given an app with multiple levels of dependencies" do
|
32
|
+
|
33
|
+
let!(:second_level_dep_a_a) do
|
34
|
+
double_spec(:second_level_dep_a_a, "2.1.0", [])
|
35
|
+
end
|
36
|
+
|
37
|
+
let!(:second_level_dep_shared) do
|
38
|
+
double_spec(:second_level_dep_shared, "2.3.0", [])
|
39
|
+
end
|
40
|
+
|
41
|
+
let!(:second_level_dep_b_a) do
|
42
|
+
double_spec(:second_level_dep_b_a, "2.2.0", [])
|
43
|
+
end
|
44
|
+
|
45
|
+
let!(:first_level_dep_a) do
|
46
|
+
double_spec(:first_level_dep_a, "1.1.0", [:second_level_dep_a_a, :second_level_dep_shared])
|
47
|
+
end
|
48
|
+
|
49
|
+
let!(:first_level_dep_b) do
|
50
|
+
double_spec(:first_level_dep_b, "1.2.0", [:second_level_dep_b_a, :second_level_dep_shared])
|
51
|
+
end
|
52
|
+
|
53
|
+
let!(:app_spec) do
|
54
|
+
double_spec(:app, "1.0.0", [:first_level_dep_a, :first_level_dep_b])
|
55
|
+
end
|
56
|
+
|
57
|
+
let(:bin_path) { File.join(target_bindir, "foo") }
|
58
|
+
|
59
|
+
let(:app_root) { "/opt/app/embedded/apps/app" }
|
60
|
+
|
61
|
+
let(:app) do
|
62
|
+
Appbundler::App.new(app_root, target_bindir)
|
63
|
+
end
|
64
|
+
|
65
|
+
before do
|
66
|
+
allow(app).to receive(:gemfile_lock_specs).and_return(all_specs)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "finds the running ruby interpreter" do
|
70
|
+
expect(app.ruby).to eq(Gem.ruby)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "finds all runtime dependencies of the app" do
|
74
|
+
# we want to find the minimum set of gems that we need to activate to run
|
75
|
+
# the application. To do this, we look at the app's runtime deps and
|
76
|
+
# recursively search through the list of gemspecs that we got from the
|
77
|
+
# Gemfile.lock, collecting all the runtime deps. This should get us the
|
78
|
+
# smallest possible "activate.rb" file that can launch the application
|
79
|
+
# with locked gem versions.
|
80
|
+
expect(app.runtime_dep_specs).to include(first_level_dep_a)
|
81
|
+
expect(app.runtime_dep_specs).to include(first_level_dep_b)
|
82
|
+
expect(app.runtime_dep_specs).to include(second_level_dep_a_a)
|
83
|
+
expect(app.runtime_dep_specs).to include(second_level_dep_b_a)
|
84
|
+
expect(app.runtime_dep_specs).to include(second_level_dep_shared)
|
85
|
+
expect(app.runtime_dep_specs.select {|s| s == second_level_dep_shared}.size).to eq(1)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "generates gem activation code for the app" do
|
89
|
+
# this is code with a bunch of gem "foo", "= X.Y.Z" statements. The top
|
90
|
+
# level application is _not_ included in this, it's added to the load
|
91
|
+
# path instead.
|
92
|
+
expect(app.runtime_activate).to include(%q{gem "first_level_dep_a", "= 1.1.0"})
|
93
|
+
expect(app.runtime_activate).to include(%q{gem "second_level_dep_a_a", "= 2.1.0"})
|
94
|
+
expect(app.runtime_activate).to include(%q{gem "second_level_dep_shared", "= 2.3.0"})
|
95
|
+
expect(app.runtime_activate).to include(%q{gem "first_level_dep_b", "= 1.2.0"})
|
96
|
+
expect(app.runtime_activate).to include(%q{gem "second_level_dep_b_a", "= 2.2.0"})
|
97
|
+
expect(app.runtime_activate).to_not include(%q{gem "app"})
|
98
|
+
end
|
99
|
+
|
100
|
+
it "locks the main app's gem via rubygems, and loads the proper binary" do
|
101
|
+
expected_loading_code = <<-CODE
|
102
|
+
gem "app", "= 1.0.0"
|
103
|
+
|
104
|
+
spec = Gem::Specification.find_by_name("app", "= 1.0.0")
|
105
|
+
bin_file = spec.bin_file("foo")
|
106
|
+
|
107
|
+
Kernel.load(bin_file)
|
108
|
+
CODE
|
109
|
+
expect(app.load_statement_for(bin_path)).to eq(expected_loading_code)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "generates code to override GEM_HOME and GEM_PATH (e.g., rvm)" do
|
113
|
+
expected = %Q{ENV["GEM_HOME"] = ENV["GEM_PATH"] = nil unless ENV["APPBUNDLER_ALLOW_RVM"] == "true"}
|
114
|
+
expect(app.env_sanitizer).to eq(expected)
|
115
|
+
expect(app.runtime_activate).to include(expected)
|
116
|
+
end
|
117
|
+
|
118
|
+
context "on windows" do
|
119
|
+
|
120
|
+
let(:target_bindir) { "C:/opscode/chef/bin" }
|
121
|
+
|
122
|
+
before do
|
123
|
+
allow(app).to receive(:ruby).and_return("C:/opscode/chef/embedded/bin/ruby.exe")
|
124
|
+
end
|
125
|
+
|
126
|
+
it "computes the relative path to ruby" do
|
127
|
+
expect(app.ruby_relative_path).to eq("../embedded/bin/ruby.exe")
|
128
|
+
end
|
129
|
+
|
130
|
+
it "generates batchfile stub code" do
|
131
|
+
expected_batch_code=<<-E
|
132
|
+
@ECHO OFF
|
133
|
+
"%~dp0\\..\\embedded\\bin\\ruby.exe" "%~dpn0" %*
|
134
|
+
E
|
135
|
+
expect(app.batchfile_stub).to eq(expected_batch_code)
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
context "when created with the example application" do
|
143
|
+
FIXTURES_PATH = File.expand_path("../../fixtures/", __FILE__).freeze
|
144
|
+
|
145
|
+
APP_ROOT = File.join(FIXTURES_PATH, "appbundler-example-app").freeze
|
146
|
+
|
147
|
+
let(:app_root) { APP_ROOT }
|
148
|
+
|
149
|
+
let(:app) do
|
150
|
+
Appbundler::App.new(APP_ROOT, target_bindir)
|
151
|
+
end
|
152
|
+
|
153
|
+
before(:all) do
|
154
|
+
Dir.chdir(APP_ROOT) do
|
155
|
+
if windows?
|
156
|
+
FileUtils.cp("Gemfile.lock.windows", "Gemfile.lock")
|
157
|
+
else
|
158
|
+
FileUtils.cp("Gemfile.lock.unix", "Gemfile.lock")
|
159
|
+
end
|
160
|
+
shellout!("bundle install")
|
161
|
+
shellout!("gem build appbundler-example-app.gemspec")
|
162
|
+
shellout!("gem install appbundler-example-app-1.0.0.gem")
|
163
|
+
Gem.clear_paths
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
before do
|
168
|
+
FileUtils.rm_rf(target_bindir) if File.exist?(target_bindir)
|
169
|
+
FileUtils.mkdir_p(target_bindir)
|
170
|
+
end
|
171
|
+
|
172
|
+
after(:all) do
|
173
|
+
shellout!("gem uninstall appbundler-example-app -a -q -x")
|
174
|
+
FileUtils.rm_rf(target_bindir) if File.exist?(target_bindir)
|
175
|
+
FileUtils.rm(File.join(APP_ROOT, "Gemfile.lock"))
|
176
|
+
end
|
177
|
+
|
178
|
+
it "initializes ok" do
|
179
|
+
app
|
180
|
+
end
|
181
|
+
|
182
|
+
it "names the app using the directory basename" do
|
183
|
+
expect(app.name).to eq("appbundler-example-app")
|
184
|
+
end
|
185
|
+
|
186
|
+
it "lists the app's dependencies" do
|
187
|
+
# only runtime deps
|
188
|
+
expect(app.app_dependency_names).to eq(["chef"])
|
189
|
+
end
|
190
|
+
|
191
|
+
it "generates runtime activation code for the app" do
|
192
|
+
expected_gem_activates= if windows?
|
193
|
+
<<-E
|
194
|
+
ENV["GEM_HOME"] = ENV["GEM_PATH"] = nil unless ENV["APPBUNDLER_ALLOW_RVM"] == "true"
|
195
|
+
gem "chef", "= 12.4.1"
|
196
|
+
gem "chef-config", "= 12.4.1"
|
197
|
+
gem "mixlib-config", "= 2.2.1"
|
198
|
+
gem "mixlib-shellout", "= 2.2.0"
|
199
|
+
gem "win32-process", "= 0.7.5"
|
200
|
+
gem "ffi", "= 1.9.10"
|
201
|
+
gem "chef-zero", "= 4.3.0"
|
202
|
+
gem "ffi-yajl", "= 2.2.2"
|
203
|
+
gem "libyajl2", "= 1.2.0"
|
204
|
+
gem "hashie", "= 2.1.2"
|
205
|
+
gem "mixlib-log", "= 1.6.0"
|
206
|
+
gem "rack", "= 1.6.4"
|
207
|
+
gem "uuidtools", "= 2.1.5"
|
208
|
+
gem "diff-lcs", "= 1.2.5"
|
209
|
+
gem "erubis", "= 2.7.0"
|
210
|
+
gem "highline", "= 1.7.3"
|
211
|
+
gem "mixlib-authentication", "= 1.3.0"
|
212
|
+
gem "mixlib-cli", "= 1.5.0"
|
213
|
+
gem "net-ssh", "= 2.9.2"
|
214
|
+
gem "net-ssh-multi", "= 1.2.1"
|
215
|
+
gem "net-ssh-gateway", "= 1.2.0"
|
216
|
+
gem "ohai", "= 8.5.1"
|
217
|
+
gem "ipaddress", "= 0.8.0"
|
218
|
+
gem "mime-types", "= 2.6.1"
|
219
|
+
gem "rake", "= 10.1.1"
|
220
|
+
gem "systemu", "= 2.6.5"
|
221
|
+
gem "wmi-lite", "= 1.0.0"
|
222
|
+
gem "plist", "= 3.1.0"
|
223
|
+
gem "pry", "= 0.9.12.6"
|
224
|
+
gem "coderay", "= 1.1.0"
|
225
|
+
gem "method_source", "= 0.8.2"
|
226
|
+
gem "slop", "= 3.4.7"
|
227
|
+
gem "win32console", "= 1.3.2"
|
228
|
+
gem "rspec-core", "= 3.3.2"
|
229
|
+
gem "rspec-support", "= 3.3.0"
|
230
|
+
gem "rspec-expectations", "= 3.3.1"
|
231
|
+
gem "rspec-mocks", "= 3.3.2"
|
232
|
+
gem "rspec_junit_formatter", "= 0.2.3"
|
233
|
+
gem "builder", "= 3.2.2"
|
234
|
+
gem "serverspec", "= 2.23.1"
|
235
|
+
gem "multi_json", "= 1.11.2"
|
236
|
+
gem "rspec", "= 3.3.0"
|
237
|
+
gem "rspec-its", "= 1.2.0"
|
238
|
+
gem "specinfra", "= 2.43.3"
|
239
|
+
gem "net-scp", "= 1.2.1"
|
240
|
+
gem "net-telnet", "= 0.1.1"
|
241
|
+
gem "sfl", "= 2.2"
|
242
|
+
gem "syslog-logger", "= 1.6.8"
|
243
|
+
gem "win32-api", "= 1.5.3"
|
244
|
+
gem "win32-dir", "= 0.5.0"
|
245
|
+
gem "win32-event", "= 0.6.1"
|
246
|
+
gem "win32-ipc", "= 0.6.6"
|
247
|
+
gem "win32-eventlog", "= 0.6.3"
|
248
|
+
gem "win32-mmap", "= 0.4.1"
|
249
|
+
gem "win32-mutex", "= 0.4.2"
|
250
|
+
gem "win32-service", "= 0.8.6"
|
251
|
+
gem "windows-api", "= 0.4.4"
|
252
|
+
gem "windows-pr", "= 1.2.4"
|
253
|
+
E
|
254
|
+
else
|
255
|
+
<<-E
|
256
|
+
ENV["GEM_HOME"] = ENV["GEM_PATH"] = nil unless ENV["APPBUNDLER_ALLOW_RVM"] == "true"
|
257
|
+
gem "chef", "= 12.4.1"
|
258
|
+
gem "chef-config", "= 12.4.1"
|
259
|
+
gem "mixlib-config", "= 2.2.1"
|
260
|
+
gem "mixlib-shellout", "= 2.2.0"
|
261
|
+
gem "chef-zero", "= 4.3.0"
|
262
|
+
gem "ffi-yajl", "= 2.2.2"
|
263
|
+
gem "libyajl2", "= 1.2.0"
|
264
|
+
gem "hashie", "= 2.1.2"
|
265
|
+
gem "mixlib-log", "= 1.6.0"
|
266
|
+
gem "rack", "= 1.6.4"
|
267
|
+
gem "uuidtools", "= 2.1.5"
|
268
|
+
gem "diff-lcs", "= 1.2.5"
|
269
|
+
gem "erubis", "= 2.7.0"
|
270
|
+
gem "highline", "= 1.7.3"
|
271
|
+
gem "mixlib-authentication", "= 1.3.0"
|
272
|
+
gem "mixlib-cli", "= 1.5.0"
|
273
|
+
gem "net-ssh", "= 2.9.2"
|
274
|
+
gem "net-ssh-multi", "= 1.2.1"
|
275
|
+
gem "net-ssh-gateway", "= 1.2.0"
|
276
|
+
gem "ohai", "= 8.5.1"
|
277
|
+
gem "ffi", "= 1.9.10"
|
278
|
+
gem "ipaddress", "= 0.8.0"
|
279
|
+
gem "mime-types", "= 2.6.1"
|
280
|
+
gem "rake", "= 10.1.1"
|
281
|
+
gem "systemu", "= 2.6.5"
|
282
|
+
gem "wmi-lite", "= 1.0.0"
|
283
|
+
gem "plist", "= 3.1.0"
|
284
|
+
gem "pry", "= 0.9.12.6"
|
285
|
+
gem "coderay", "= 1.1.0"
|
286
|
+
gem "method_source", "= 0.8.2"
|
287
|
+
gem "slop", "= 3.4.7"
|
288
|
+
gem "rspec-core", "= 3.3.2"
|
289
|
+
gem "rspec-support", "= 3.3.0"
|
290
|
+
gem "rspec-expectations", "= 3.3.1"
|
291
|
+
gem "rspec-mocks", "= 3.3.2"
|
292
|
+
gem "rspec_junit_formatter", "= 0.2.3"
|
293
|
+
gem "builder", "= 3.2.2"
|
294
|
+
gem "serverspec", "= 2.23.1"
|
295
|
+
gem "multi_json", "= 1.11.2"
|
296
|
+
gem "rspec", "= 3.3.0"
|
297
|
+
gem "rspec-its", "= 1.2.0"
|
298
|
+
gem "specinfra", "= 2.43.3"
|
299
|
+
gem "net-scp", "= 1.2.1"
|
300
|
+
gem "net-telnet", "= 0.1.1"
|
301
|
+
gem "sfl", "= 2.2"
|
302
|
+
gem "syslog-logger", "= 1.6.8"
|
303
|
+
E
|
304
|
+
end
|
305
|
+
expect(app.runtime_activate).to include(expected_gem_activates)
|
306
|
+
end
|
307
|
+
|
308
|
+
it "lists the app's executables" do
|
309
|
+
spec = Gem::Specification.find_by_name("appbundler-example-app", "= 1.0.0")
|
310
|
+
expected_executables = %w[app-binary-1 app-binary-2].map do |basename|
|
311
|
+
File.join(spec.gem_dir, "/bin", basename)
|
312
|
+
end
|
313
|
+
expect(app.executables).to match_array(expected_executables)
|
314
|
+
end
|
315
|
+
|
316
|
+
it "generates an executable 'stub' for an executable in the app" do
|
317
|
+
app_binary_1_path = app.executables.grep(/app\-binary\-1/).first
|
318
|
+
executable_content = app.binstub(app_binary_1_path)
|
319
|
+
|
320
|
+
shebang = executable_content.lines.first
|
321
|
+
expect(shebang).to match(/^\#\!/)
|
322
|
+
expect(shebang).to include(Gem.ruby)
|
323
|
+
|
324
|
+
expect(executable_content).to include(app.runtime_activate)
|
325
|
+
|
326
|
+
load_binary = executable_content.lines.to_a.last
|
327
|
+
|
328
|
+
expected_load_path = %Q[Kernel.load(bin_file)\n]
|
329
|
+
|
330
|
+
expect(load_binary).to eq(expected_load_path)
|
331
|
+
end
|
332
|
+
|
333
|
+
it "generates executable stubs for all executables in the app" do
|
334
|
+
app.write_executable_stubs
|
335
|
+
binary_1 = File.join(target_bindir, "app-binary-1")
|
336
|
+
binary_2 = File.join(target_bindir, "app-binary-2")
|
337
|
+
expect(File.exist?(binary_1)).to be(true)
|
338
|
+
expect(File.exist?(binary_2)).to be(true)
|
339
|
+
expect(File.executable?(binary_1) || File.exists?(binary_1 + ".bat")).to be(true)
|
340
|
+
expect(File.executable?(binary_1) || File.exists?(binary_1 + ".bat")).to be(true)
|
341
|
+
expect(shellout!(binary_1).stdout.strip).to eq("binary 1 ran")
|
342
|
+
expect(shellout!(binary_2).stdout.strip).to eq("binary 2 ran")
|
343
|
+
end
|
344
|
+
|
345
|
+
it "copies over Gemfile.lock to the gem directory" do
|
346
|
+
spec = Gem::Specification.find_by_name("appbundler-example-app", "= 1.0.0")
|
347
|
+
gem_path = spec.gem_dir
|
348
|
+
app.copy_bundler_env
|
349
|
+
expect(File.exists?(File.join(gem_path, 'Gemfile.lock'))).to be(true)
|
350
|
+
end
|
351
|
+
|
352
|
+
it "copies over .bundler to the gem directory" do
|
353
|
+
spec = Gem::Specification.find_by_name("appbundler-example-app", "= 1.0.0")
|
354
|
+
gem_path = spec.gem_dir
|
355
|
+
app.copy_bundler_env
|
356
|
+
expect(File.directory?(File.join(gem_path, '.bundle'))).to be(true)
|
357
|
+
expect(File.exists?(File.join(gem_path, '.bundle/config'))).to be(true)
|
358
|
+
end
|
359
|
+
context "and the executable is symlinked to a different directory", :not_supported_on_windows do
|
360
|
+
|
361
|
+
let(:symlinks_root_dir) do
|
362
|
+
Dir.mktmpdir
|
363
|
+
end
|
364
|
+
|
365
|
+
let(:symlinks_bin_dir) do
|
366
|
+
d = File.join(symlinks_root_dir, "bin")
|
367
|
+
FileUtils.mkdir(d)
|
368
|
+
d
|
369
|
+
end
|
370
|
+
|
371
|
+
let(:binary_symlinked_path) { File.join(symlinks_bin_dir, "app-binary-1") }
|
372
|
+
|
373
|
+
let(:binary_orignal_path) { File.join(target_bindir, "app-binary-1") }
|
374
|
+
|
375
|
+
before do
|
376
|
+
app.write_executable_stubs
|
377
|
+
FileUtils.ln_s(binary_orignal_path, binary_symlinked_path)
|
378
|
+
end
|
379
|
+
|
380
|
+
after do
|
381
|
+
FileUtils.rm_rf(symlinks_root_dir)
|
382
|
+
end
|
383
|
+
|
384
|
+
it "correctly runs the executable via the symlinked executable" do
|
385
|
+
expect(shellout!(binary_symlinked_path).stdout).to eq("binary 1 ran\n")
|
386
|
+
end
|
387
|
+
|
388
|
+
end
|
389
|
+
|
390
|
+
context "on windows" do
|
391
|
+
|
392
|
+
let(:expected_ruby_relpath) do
|
393
|
+
app.ruby_relative_path.gsub('/', '\\')
|
394
|
+
end
|
395
|
+
|
396
|
+
let(:expected_batch_code) do
|
397
|
+
<<-E
|
398
|
+
@ECHO OFF
|
399
|
+
"%~dp0\\#{expected_ruby_relpath}" "%~dpn0" %*
|
400
|
+
E
|
401
|
+
end
|
402
|
+
|
403
|
+
before do
|
404
|
+
stub_const("RUBY_PLATFORM", "mingw")
|
405
|
+
end
|
406
|
+
|
407
|
+
it "creates a batchfile wrapper for each executable" do
|
408
|
+
app.write_executable_stubs
|
409
|
+
binary_1 = File.join(target_bindir, "app-binary-1.bat")
|
410
|
+
binary_2 = File.join(target_bindir, "app-binary-2.bat")
|
411
|
+
expect(File.exist?(binary_1)).to be(true)
|
412
|
+
expect(File.exist?(binary_2)).to be(true)
|
413
|
+
expect(IO.read(binary_1)).to eq(expected_batch_code)
|
414
|
+
expect(IO.read(binary_2)).to eq(expected_batch_code)
|
415
|
+
end
|
416
|
+
|
417
|
+
end
|
418
|
+
|
419
|
+
end
|
420
|
+
|
421
|
+
end
|