stable-cli-rails 0.6.7 → 0.6.8
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/lib/stable/cli.rb +111 -42
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 55e25d45106e712c1d3e9d23754150d9519e34b38d4464652c4c0a21539a0597
|
|
4
|
+
data.tar.gz: a2bb082ffeb11bf916903f7a15cc0da89a5136c33d53b3139038d7d294591f2d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 954bb6bd50281fe5a47ed03e2cead5a2c614f7786d17cdc4831c50ab798e0a6fac59dc1b98b76f3d35524be574396813444bbf3d4f60099e7e81b44846658ef4
|
|
7
|
+
data.tar.gz: 275d760d16ce88fb018f3aad059330fd05c63911aa19352b67780bd8d8680d64918583ece7e48e2eb452329c468fff3eaac5a7fdee92341425ff792421646c0b
|
data/lib/stable/cli.rb
CHANGED
|
@@ -14,6 +14,7 @@ module Stable
|
|
|
14
14
|
super
|
|
15
15
|
Stable::Bootstrap.run!
|
|
16
16
|
ensure_dependencies!
|
|
17
|
+
dedupe_registry!
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def self.exit_on_failure?
|
|
@@ -29,24 +30,40 @@ module Stable
|
|
|
29
30
|
port ||= next_free_port
|
|
30
31
|
app_path = File.expand_path(name)
|
|
31
32
|
|
|
33
|
+
# --- Add app to registry ---
|
|
34
|
+
domain = "#{name}.test"
|
|
35
|
+
apps = Registry.apps
|
|
36
|
+
|
|
37
|
+
app = {
|
|
38
|
+
name: name,
|
|
39
|
+
path: app_path,
|
|
40
|
+
domain: domain,
|
|
41
|
+
port: port,
|
|
42
|
+
ruby: ruby,
|
|
43
|
+
started_at: nil
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
apps.reject! { |a| a[:name] == name }
|
|
47
|
+
apps << app
|
|
48
|
+
|
|
32
49
|
abort "Folder already exists: #{app_path}" if File.exist?(app_path)
|
|
33
50
|
|
|
34
51
|
# --- Ensure RVM and Ruby ---
|
|
35
52
|
ensure_rvm!
|
|
36
53
|
puts "Using Ruby #{ruby} with RVM gemset #{name}..."
|
|
37
|
-
system("bash -lc 'rvm #{ruby}@#{name} --create do true'") or abort(
|
|
38
|
-
|
|
54
|
+
system("bash -lc 'rvm #{ruby}@#{name} --create do true'") or abort("Failed to create RVM gemset #{name}")
|
|
55
|
+
ruby_cmd = rvm_exec(app, ruby)
|
|
39
56
|
# --- Install Rails in gemset if needed ---
|
|
40
57
|
rails_version = rails || 'latest'
|
|
41
|
-
rails_check = system("bash -lc '
|
|
58
|
+
rails_check = system("bash -lc '#{ruby_cmd} gem list -i rails#{rails ? " -v #{rails}" : ''}'")
|
|
42
59
|
unless rails_check
|
|
43
60
|
puts "Installing Rails #{rails_version} in gemset..."
|
|
44
|
-
system("bash -lc '
|
|
61
|
+
system("bash -lc '#{ruby_cmd} gem install rails #{rails ? "-v #{rails}" : ''}'") or abort('Failed to install Rails')
|
|
45
62
|
end
|
|
46
63
|
|
|
47
64
|
# --- Create Rails app ---
|
|
48
65
|
puts "Creating Rails app #{name} (Ruby #{ruby})..."
|
|
49
|
-
system("bash -lc '
|
|
66
|
+
system("bash -lc '#{ruby_cmd} rails new #{app_path}'") or abort('Rails app creation failed')
|
|
50
67
|
|
|
51
68
|
# --- Add .ruby-version and .ruby-gemset ---
|
|
52
69
|
Dir.chdir(app_path) do
|
|
@@ -55,15 +72,9 @@ module Stable
|
|
|
55
72
|
|
|
56
73
|
# --- Install gems inside gemset ---
|
|
57
74
|
puts 'Running bundle install...'
|
|
58
|
-
system("bash -lc '
|
|
75
|
+
system("bash -lc '#{ruby_cmd} bundle install --jobs=4 --retry=3'") or abort('bundle install failed')
|
|
59
76
|
end
|
|
60
77
|
|
|
61
|
-
# --- Add app to registry ---
|
|
62
|
-
domain = "#{name}.test"
|
|
63
|
-
apps = Registry.apps
|
|
64
|
-
apps << { name: name, path: app_path, domain: domain, port: port, ruby: ruby }
|
|
65
|
-
Registry.save(apps)
|
|
66
|
-
|
|
67
78
|
# --- Host entry & certificate ---
|
|
68
79
|
add_host_entry(domain)
|
|
69
80
|
generate_cert(domain) unless options[:skip_ssl]
|
|
@@ -76,15 +87,20 @@ module Stable
|
|
|
76
87
|
log_file = File.join(app_path, 'log', 'stable.log')
|
|
77
88
|
FileUtils.mkdir_p(File.dirname(log_file))
|
|
78
89
|
|
|
90
|
+
abort "Port #{port} is already in use. Choose another port." if app_running?({ port: port })
|
|
91
|
+
|
|
79
92
|
pid = spawn(
|
|
80
93
|
'bash',
|
|
81
94
|
'-lc',
|
|
82
|
-
"cd #{app_path} &&
|
|
95
|
+
"cd #{app_path} && #{ruby_cmd} bundle exec rails s -p #{port} -b 127.0.0.1",
|
|
83
96
|
out: log_file,
|
|
84
97
|
err: log_file
|
|
85
98
|
)
|
|
86
99
|
Process.detach(pid)
|
|
87
100
|
|
|
101
|
+
app[:started_at] = Time.now.to_i
|
|
102
|
+
Registry.save(apps)
|
|
103
|
+
|
|
88
104
|
sleep 1.5
|
|
89
105
|
|
|
90
106
|
wait_for_port(port)
|
|
@@ -111,6 +127,8 @@ module Stable
|
|
|
111
127
|
return
|
|
112
128
|
end
|
|
113
129
|
|
|
130
|
+
puts "Detected gemset: #{File.read('.ruby-gemset').strip}" if File.exist?('.ruby-gemset')
|
|
131
|
+
|
|
114
132
|
apps = Registry.apps
|
|
115
133
|
name = File.basename(folder)
|
|
116
134
|
domain = "#{name}.test"
|
|
@@ -154,47 +172,54 @@ module Stable
|
|
|
154
172
|
desc 'start NAME', 'Start a Rails app with its correct Ruby version'
|
|
155
173
|
def start(name)
|
|
156
174
|
app = Registry.apps.find { |a| a[:name] == name }
|
|
157
|
-
unless app
|
|
158
|
-
puts "No app found with name #{name}"
|
|
159
|
-
return
|
|
160
|
-
end
|
|
175
|
+
return puts("No app found with name #{name}") unless app
|
|
161
176
|
|
|
162
177
|
port = app[:port] || next_free_port
|
|
163
178
|
ruby = app[:ruby]
|
|
179
|
+
path = app[:path]
|
|
164
180
|
|
|
165
|
-
|
|
181
|
+
if app_running?(app)
|
|
182
|
+
puts "#{name} is already running on https://#{app[:domain]} (port #{port})"
|
|
183
|
+
return
|
|
184
|
+
end
|
|
166
185
|
|
|
167
|
-
|
|
168
|
-
FileUtils.mkdir_p(File.dirname(log_file))
|
|
186
|
+
gemset = gemset_for(app)
|
|
169
187
|
|
|
170
|
-
|
|
171
|
-
if ruby
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
ensure_rbenv_ruby!(ruby)
|
|
177
|
-
"RBENV_VERSION=#{ruby}"
|
|
178
|
-
else
|
|
179
|
-
puts 'No Ruby version manager found (rvm or rbenv)'
|
|
180
|
-
return
|
|
181
|
-
end
|
|
188
|
+
rvm_cmd =
|
|
189
|
+
if ruby && gemset
|
|
190
|
+
system("bash -lc 'rvm #{ruby}@#{gemset} --create do true'")
|
|
191
|
+
"rvm #{ruby}@#{gemset} do"
|
|
192
|
+
elsif ruby
|
|
193
|
+
"rvm #{ruby} do"
|
|
182
194
|
end
|
|
183
195
|
|
|
196
|
+
puts "Starting #{name} on port #{port}..."
|
|
197
|
+
|
|
198
|
+
log_file = File.join(path, 'log', 'stable.log')
|
|
199
|
+
FileUtils.mkdir_p(File.dirname(log_file))
|
|
200
|
+
|
|
184
201
|
pid = spawn(
|
|
185
202
|
'bash',
|
|
186
203
|
'-lc',
|
|
187
|
-
|
|
204
|
+
<<~CMD,
|
|
205
|
+
cd "#{path}"
|
|
206
|
+
#{rvm_cmd} bundle exec rails s \
|
|
207
|
+
-p #{port} \
|
|
208
|
+
-b 127.0.0.1
|
|
209
|
+
CMD
|
|
188
210
|
out: log_file,
|
|
189
211
|
err: log_file
|
|
190
212
|
)
|
|
213
|
+
|
|
191
214
|
Process.detach(pid)
|
|
192
215
|
|
|
193
|
-
|
|
216
|
+
wait_for_port(port, timeout: 30)
|
|
217
|
+
|
|
218
|
+
app[:started_at] = Time.now.to_i
|
|
219
|
+
Registry.save(Registry.apps)
|
|
194
220
|
|
|
195
221
|
generate_cert(app[:domain])
|
|
196
222
|
update_caddyfile(app[:domain], port)
|
|
197
|
-
wait_for_port(port)
|
|
198
223
|
caddy_reload
|
|
199
224
|
|
|
200
225
|
puts "#{name} started on https://#{app[:domain]}"
|
|
@@ -254,8 +279,11 @@ module Stable
|
|
|
254
279
|
puts "mkcert: #{system('which mkcert > /dev/null') ? 'yes' : 'no'}"
|
|
255
280
|
|
|
256
281
|
Registry.apps.each do |app|
|
|
257
|
-
|
|
258
|
-
|
|
282
|
+
state = boot_state(app)
|
|
283
|
+
ruby = app[:ruby] || 'default'
|
|
284
|
+
port = app[:port]
|
|
285
|
+
|
|
286
|
+
puts "#{app[:name]} → Ruby #{ruby} | port #{port} | #{state}"
|
|
259
287
|
end
|
|
260
288
|
end
|
|
261
289
|
|
|
@@ -481,16 +509,17 @@ module Stable
|
|
|
481
509
|
end
|
|
482
510
|
end
|
|
483
511
|
|
|
484
|
-
def wait_for_port(port, timeout:
|
|
512
|
+
def wait_for_port(port, timeout: 10)
|
|
485
513
|
require 'socket'
|
|
486
|
-
|
|
514
|
+
start = Time.now
|
|
515
|
+
|
|
487
516
|
loop do
|
|
488
517
|
TCPSocket.new('127.0.0.1', port).close
|
|
489
|
-
|
|
518
|
+
return
|
|
490
519
|
rescue Errno::ECONNREFUSED
|
|
491
|
-
raise "
|
|
520
|
+
raise "Rails never bound port #{port}. Check log/stable.log" if Time.now - start > timeout
|
|
492
521
|
|
|
493
|
-
sleep 0.
|
|
522
|
+
sleep 0.5
|
|
494
523
|
end
|
|
495
524
|
end
|
|
496
525
|
|
|
@@ -550,5 +579,45 @@ module Stable
|
|
|
550
579
|
def ensure_rbenv_ruby!(version)
|
|
551
580
|
system("rbenv versions | grep -q #{version} || rbenv install #{version}")
|
|
552
581
|
end
|
|
582
|
+
|
|
583
|
+
def app_running?(app)
|
|
584
|
+
return false unless app && app[:port]
|
|
585
|
+
|
|
586
|
+
system("lsof -i tcp:#{app[:port]} -sTCP:LISTEN > /dev/null 2>&1")
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
def boot_state(app)
|
|
590
|
+
return 'stopped' unless app_running?(app)
|
|
591
|
+
|
|
592
|
+
if app[:started_at]
|
|
593
|
+
elapsed = Time.now.to_i - app[:started_at]
|
|
594
|
+
return "booting (#{elapsed}s)" if elapsed < 10
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
'running'
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
def dedupe_registry!
|
|
601
|
+
apps = Registry.apps
|
|
602
|
+
apps.uniq! { |a| a[:name] }
|
|
603
|
+
Registry.save(apps)
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
def gemset_for(app)
|
|
607
|
+
gemset_file = File.join(app[:path], '.ruby-gemset')
|
|
608
|
+
return File.read(gemset_file).strip if File.exist?(gemset_file)
|
|
609
|
+
|
|
610
|
+
nil
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
def rvm_exec(app, ruby)
|
|
614
|
+
gemset = gemset_for(app)
|
|
615
|
+
|
|
616
|
+
if gemset
|
|
617
|
+
"rvm #{ruby}@#{gemset} do"
|
|
618
|
+
else
|
|
619
|
+
"rvm #{ruby} do"
|
|
620
|
+
end
|
|
621
|
+
end
|
|
553
622
|
end
|
|
554
623
|
end
|