stable-cli-rails 0.8.2 → 0.8.3
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 +4 -20
- data/lib/stable/commands/destroy.rb +8 -0
- data/lib/stable/commands/upgrade_ruby.rb +163 -0
- data/lib/stable/services/caddy_manager.rb +8 -2
- data/lib/stable/services/setup_runner.rb +4 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: adfc3784b0a153d9a5368139267d77c0cfa8a32b71d72e8da43ae5a454220f6a
|
|
4
|
+
data.tar.gz: 861823110de96d0e4d1c8297f13ff2f9630a25649d201f921aaa64f43849888c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9651b1cd3c7127223a5587f31e70175fdf2be8e9ccd8c3e17347b73a1364b9404eda928d7e314513bf5a416b8acf90c31a14eb2d6e7ec719d6f7576887dd933d
|
|
7
|
+
data.tar.gz: 9ab4288661598a9349301e1fa1f96007b0eafdc78eb66886e26f9b555ecf871d55f07fdb9b2ce529d59aff25ee287e655e68a3a5bce001d38c6621eae6c73736
|
data/lib/stable/cli.rb
CHANGED
|
@@ -13,6 +13,8 @@ module Stable
|
|
|
13
13
|
class CLI < Thor
|
|
14
14
|
def initialize(*)
|
|
15
15
|
super
|
|
16
|
+
return if ENV['STABLE_TEST_MODE']
|
|
17
|
+
|
|
16
18
|
Stable::Bootstrap.run!
|
|
17
19
|
Services::SetupRunner.ensure_dependencies!
|
|
18
20
|
end
|
|
@@ -128,27 +130,9 @@ module Stable
|
|
|
128
130
|
Commands::Doctor.new.call
|
|
129
131
|
end
|
|
130
132
|
|
|
131
|
-
desc 'upgrade-ruby NAME VERSION', '
|
|
133
|
+
desc 'upgrade-ruby NAME VERSION', 'Change Ruby version for an app (upgrade, downgrade, or switch)'
|
|
132
134
|
def upgrade_ruby(name, version)
|
|
133
|
-
|
|
134
|
-
unless app
|
|
135
|
-
puts "No app named #{name}"
|
|
136
|
-
return
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
if Stable::Services::Ruby.rvm_available?
|
|
140
|
-
system("bash -lc 'rvm install #{version}'")
|
|
141
|
-
elsif Stable::Services::Ruby.rbenv_available?
|
|
142
|
-
system("rbenv install #{version}")
|
|
143
|
-
else
|
|
144
|
-
puts 'No Ruby version manager found'
|
|
145
|
-
return
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
File.write(File.join(app[:path], '.ruby-version'), version)
|
|
149
|
-
Services::AppRegistry.update(name, ruby: version)
|
|
150
|
-
|
|
151
|
-
puts "#{name} now uses Ruby #{version}"
|
|
135
|
+
Commands::UpgradeRuby.new(name, version).call
|
|
152
136
|
end
|
|
153
137
|
|
|
154
138
|
private
|
|
@@ -65,6 +65,9 @@ module Stable
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
def cleanup_rvm_gemset(app)
|
|
68
|
+
# Skip RVM operations in test mode
|
|
69
|
+
return if ENV['STABLE_TEST_MODE']
|
|
70
|
+
|
|
68
71
|
# Only clean up RVM gemsets on Unix-like systems (macOS/Linux)
|
|
69
72
|
# Windows uses different Ruby version managers
|
|
70
73
|
return unless Stable::Utils::Platform.unix?
|
|
@@ -85,6 +88,11 @@ module Stable
|
|
|
85
88
|
end
|
|
86
89
|
|
|
87
90
|
def delete_project_directory(path)
|
|
91
|
+
if ENV['STABLE_TEST_MODE']
|
|
92
|
+
puts ' Deleting project directory...'
|
|
93
|
+
return
|
|
94
|
+
end
|
|
95
|
+
|
|
88
96
|
if File.exist?(path)
|
|
89
97
|
puts ' Deleting project directory...'
|
|
90
98
|
FileUtils.rm_rf(path)
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'shellwords'
|
|
4
|
+
|
|
5
|
+
module Stable
|
|
6
|
+
module Commands
|
|
7
|
+
# Command for upgrading/downgrading Ruby versions for applications
|
|
8
|
+
class UpgradeRuby
|
|
9
|
+
def initialize(name, version)
|
|
10
|
+
@name = name
|
|
11
|
+
@version = version
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call
|
|
15
|
+
app = Services::AppRegistry.find(@name)
|
|
16
|
+
unless app
|
|
17
|
+
puts "No app named #{@name}"
|
|
18
|
+
return
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
current_version = app[:ruby] || RUBY_VERSION
|
|
22
|
+
|
|
23
|
+
puts "#{action(current_version, @version)} #{@name} from Ruby #{current_version} to #{@version}..."
|
|
24
|
+
puts ''
|
|
25
|
+
|
|
26
|
+
# Install the target Ruby version if needed
|
|
27
|
+
platform = Stable::Utils::Platform.current
|
|
28
|
+
|
|
29
|
+
if platform == :windows
|
|
30
|
+
puts '⚠️ Windows detected - Ruby version managers work differently on Windows'
|
|
31
|
+
puts " Please manually install Ruby #{@version} using RubyInstaller or your preferred method"
|
|
32
|
+
puts ' Recommended: https://rubyinstaller.org/'
|
|
33
|
+
puts ' Then update your PATH to use the new Ruby version'
|
|
34
|
+
puts ''
|
|
35
|
+
puts "After installing Ruby #{@version}, update the app configuration manually:"
|
|
36
|
+
puts " - Edit .ruby-version file to contain: #{@version}"
|
|
37
|
+
puts ' - Run: bundle install (in the app directory)'
|
|
38
|
+
return
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
if Stable::Services::Ruby.rvm_available?
|
|
42
|
+
puts "Ensuring Ruby #{@version} is available..."
|
|
43
|
+
system("bash -lc 'rvm install #{@version}'") unless ENV['STABLE_TEST_MODE']
|
|
44
|
+
elsif Stable::Services::Ruby.rbenv_available?
|
|
45
|
+
puts "Ensuring Ruby #{@version} is available..."
|
|
46
|
+
system("rbenv install #{@version}") unless ENV['STABLE_TEST_MODE']
|
|
47
|
+
else
|
|
48
|
+
puts '❌ No supported Ruby version manager found'
|
|
49
|
+
puts ' On macOS/Linux, install RVM (https://rvm.io/) or rbenv (https://github.com/rbenv/rbenv)'
|
|
50
|
+
puts ' On Windows, use RubyInstaller (https://rubyinstaller.org/)'
|
|
51
|
+
return
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Clean, simple approach: Remove current Ruby environment and install new one fresh
|
|
55
|
+
puts "🔄 Upgrading #{@name} from Ruby #{current_version} to #{@version}..."
|
|
56
|
+
|
|
57
|
+
# 1. Remove current Ruby version/gemset (like destroy command)
|
|
58
|
+
cleanup_rvm_gemset(app)
|
|
59
|
+
|
|
60
|
+
# 2. Install new Ruby version fresh (like app creator)
|
|
61
|
+
setup_new_ruby_version(app, @version)
|
|
62
|
+
|
|
63
|
+
puts ''
|
|
64
|
+
puts "✅ #{@name} #{past_tense_action(action(current_version, @version))} to Ruby #{@version}!"
|
|
65
|
+
puts " Old gemset cleared, fresh #{@version}@#{@name} gemset created with gems"
|
|
66
|
+
puts ''
|
|
67
|
+
puts "Start with: stable start #{@name}"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def cleanup_rvm_gemset(app)
|
|
73
|
+
# Skip RVM operations in test mode
|
|
74
|
+
return if ENV['STABLE_TEST_MODE']
|
|
75
|
+
|
|
76
|
+
# Only clean up RVM gemsets on Unix-like systems (macOS/Linux)
|
|
77
|
+
# Windows uses different Ruby version managers
|
|
78
|
+
return unless Stable::Utils::Platform.unix?
|
|
79
|
+
|
|
80
|
+
ruby_version = app[:ruby]
|
|
81
|
+
# Handle different ruby version formats (e.g., "3.4.7", "ruby-3.4.7")
|
|
82
|
+
clean_ruby_version = ruby_version.to_s.sub(/^ruby-/, '')
|
|
83
|
+
gemset_name = "#{clean_ruby_version}@#{@name}"
|
|
84
|
+
|
|
85
|
+
puts " Cleaning up RVM gemset #{gemset_name}..."
|
|
86
|
+
begin
|
|
87
|
+
# Use system to run RVM command to delete the gemset
|
|
88
|
+
system("bash -lc 'source ~/.rvm/scripts/rvm && rvm gemset delete #{gemset_name} --force' 2>/dev/null || true")
|
|
89
|
+
puts " ✅ RVM gemset #{gemset_name} cleaned up"
|
|
90
|
+
rescue StandardError => e
|
|
91
|
+
puts " ⚠️ Could not clean up RVM gemset #{gemset_name}: #{e.message}"
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def setup_new_ruby_version(app, new_version)
|
|
96
|
+
# Follow app_creator.rb pattern exactly
|
|
97
|
+
unless ENV['STABLE_TEST_MODE']
|
|
98
|
+
# Ensure Ruby version & RVM (like app_creator.rb)
|
|
99
|
+
Stable::Services::Ruby.ensure_version(new_version)
|
|
100
|
+
Stable::Services::Ruby.ensure_rvm!
|
|
101
|
+
|
|
102
|
+
# Create gemset (like app_creator.rb)
|
|
103
|
+
Stable::System::Shell.run("bash -lc 'source #{Stable::Services::Ruby.rvm_script} && rvm #{new_version} do rvm gemset create #{@name} || true'")
|
|
104
|
+
|
|
105
|
+
rvm_cmd = Stable::Services::Ruby.rvm_prefix(new_version, @name)
|
|
106
|
+
|
|
107
|
+
# Install Bundler (like app_creator.rb)
|
|
108
|
+
Stable::System::Shell.run("bash -lc '#{rvm_cmd} gem install bundler --no-document'")
|
|
109
|
+
|
|
110
|
+
# Run bundle install (like app_creator.rb)
|
|
111
|
+
Stable::System::Shell.run(rvm_run('bundle install --jobs=4 --retry=3', chdir: app[:path]))
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Update app configuration (like app_creator.rb)
|
|
115
|
+
unless ENV['STABLE_TEST_MODE']
|
|
116
|
+
Dir.chdir(app[:path]) do
|
|
117
|
+
File.write('.ruby-version', "#{new_version}\n")
|
|
118
|
+
File.write('.ruby-gemset', "#{@name}\n")
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Update registry
|
|
123
|
+
Services::AppRegistry.update(@name, ruby: new_version)
|
|
124
|
+
puts " ✅ New Ruby #{new_version} environment set up with gems"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def rvm_run(cmd, chdir: nil)
|
|
128
|
+
cd = chdir ? "cd #{chdir} && " : ''
|
|
129
|
+
"bash -lc '#{cd}source #{Dir.home}/.rvm/scripts/rvm && rvm #{@version}@#{@name} do #{cmd}'"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def action(current_version, new_version)
|
|
133
|
+
current_parts = current_version.split('.').map(&:to_i)
|
|
134
|
+
new_parts = new_version.split('.').map(&:to_i)
|
|
135
|
+
|
|
136
|
+
if new_parts[0] > current_parts[0] ||
|
|
137
|
+
(new_parts[0] == current_parts[0] && new_parts[1] > current_parts[1]) ||
|
|
138
|
+
(new_parts[0] == current_parts[0] && new_parts[1] == current_parts[1] && new_parts[2] > current_parts[2])
|
|
139
|
+
'Upgrading'
|
|
140
|
+
elsif new_parts[0] < current_parts[0] ||
|
|
141
|
+
(new_parts[0] == current_parts[0] && new_parts[1] < current_parts[1]) ||
|
|
142
|
+
(new_parts[0] == current_parts[0] && new_parts[1] == current_parts[1] && new_parts[2] < current_parts[2])
|
|
143
|
+
'Downgrading'
|
|
144
|
+
else
|
|
145
|
+
'Switching'
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def past_tense_action(action)
|
|
150
|
+
case action
|
|
151
|
+
when 'Upgrading'
|
|
152
|
+
'upgraded'
|
|
153
|
+
when 'Downgrading'
|
|
154
|
+
'downgraded'
|
|
155
|
+
when 'Switching'
|
|
156
|
+
'switched'
|
|
157
|
+
else
|
|
158
|
+
'updated'
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
@@ -16,7 +16,7 @@ module Stable
|
|
|
16
16
|
content = remove_domain_block(content, domain)
|
|
17
17
|
|
|
18
18
|
atomic_write(caddyfile, content)
|
|
19
|
-
system("caddy fmt --overwrite #{caddyfile}")
|
|
19
|
+
system("caddy fmt --overwrite #{caddyfile}") unless ENV['STABLE_TEST_MODE']
|
|
20
20
|
|
|
21
21
|
reload_if_running
|
|
22
22
|
end
|
|
@@ -38,12 +38,14 @@ module Stable
|
|
|
38
38
|
content << build_block(domain, port, skip_ssl: skip_ssl)
|
|
39
39
|
|
|
40
40
|
atomic_write(caddyfile, content)
|
|
41
|
-
system("caddy fmt --overwrite #{caddyfile}")
|
|
41
|
+
system("caddy fmt --overwrite #{caddyfile}") unless ENV['STABLE_TEST_MODE']
|
|
42
42
|
|
|
43
43
|
ensure_running!
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def reload
|
|
47
|
+
return if ENV['STABLE_TEST_MODE']
|
|
48
|
+
|
|
47
49
|
if system('which caddy > /dev/null')
|
|
48
50
|
pid = Process.spawn("caddy reload --config #{caddyfile}")
|
|
49
51
|
Process.detach(pid.to_i)
|
|
@@ -53,6 +55,8 @@ module Stable
|
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
def ensure_running!
|
|
58
|
+
return if ENV['STABLE_TEST_MODE']
|
|
59
|
+
|
|
56
60
|
if running?
|
|
57
61
|
reload
|
|
58
62
|
else
|
|
@@ -81,6 +85,8 @@ module Stable
|
|
|
81
85
|
|
|
82
86
|
return if valid_pem?(cert_path) && valid_pem?(key_path)
|
|
83
87
|
|
|
88
|
+
return if ENV['STABLE_TEST_MODE'] # Skip cert generation in tests
|
|
89
|
+
|
|
84
90
|
raise 'mkcert not installed' unless system('which mkcert > /dev/null')
|
|
85
91
|
|
|
86
92
|
System::Shell.run(
|
|
@@ -11,6 +11,8 @@ module Stable
|
|
|
11
11
|
ensure_apps_registry
|
|
12
12
|
ensure_caddyfile
|
|
13
13
|
# start or ensure caddy is running like original CLI
|
|
14
|
+
return if ENV['STABLE_TEST_MODE']
|
|
15
|
+
|
|
14
16
|
Stable::Services::CaddyManager.ensure_running!
|
|
15
17
|
puts "Caddy home initialized at #{Stable::Paths.root}"
|
|
16
18
|
self.class.ensure_dependencies!
|
|
@@ -44,6 +46,8 @@ module Stable
|
|
|
44
46
|
end
|
|
45
47
|
|
|
46
48
|
def ensure_dependencies!
|
|
49
|
+
return if ENV['STABLE_TEST_MODE']
|
|
50
|
+
|
|
47
51
|
platform = Stable::Utils::Platform.current
|
|
48
52
|
|
|
49
53
|
unless Stable::Utils::PackageManager.available?
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stable-cli-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Danny Simfukwe
|
|
@@ -46,6 +46,7 @@ files:
|
|
|
46
46
|
- lib/stable/commands/setup.rb
|
|
47
47
|
- lib/stable/commands/start.rb
|
|
48
48
|
- lib/stable/commands/stop.rb
|
|
49
|
+
- lib/stable/commands/upgrade_ruby.rb
|
|
49
50
|
- lib/stable/config/paths.rb
|
|
50
51
|
- lib/stable/db_manager.rb
|
|
51
52
|
- lib/stable/paths.rb
|
|
@@ -92,5 +93,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
92
93
|
requirements: []
|
|
93
94
|
rubygems_version: 3.6.7
|
|
94
95
|
specification_version: 4
|
|
95
|
-
summary: CLI tool to manage local Rails apps with automatic Caddy and
|
|
96
|
+
summary: Zero-config CLI tool to manage local Rails apps with automatic Caddy and
|
|
97
|
+
HTTPS setup
|
|
96
98
|
test_files: []
|