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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a7c350e5e5b2858a8a8ceb9e35eb9772c0e3416accf9f8e3546ba072ae59833
4
- data.tar.gz: ed890e3547579a9361c473a8b884166a87d4454f1b89874e53510138f38e43f9
3
+ metadata.gz: adfc3784b0a153d9a5368139267d77c0cfa8a32b71d72e8da43ae5a454220f6a
4
+ data.tar.gz: 861823110de96d0e4d1c8297f13ff2f9630a25649d201f921aaa64f43849888c
5
5
  SHA512:
6
- metadata.gz: 9f86445108712b6eb9cb99a14f5da5df53e14d11d646d3ccc9525dc23efec767ae2a6a2f6cb68c0ac032f75928992dfb0913580900ebae6d2426660051f5191b
7
- data.tar.gz: 2965495aa69ea21c4c19c7020222a90ee84214d05530a1b6175e9ce6689dda13d94a508cb708c9d2c2447f8b484b6afe127e7ae19c08efcf5dfefea247757d03
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', 'Upgrade Ruby for an app'
133
+ desc 'upgrade-ruby NAME VERSION', 'Change Ruby version for an app (upgrade, downgrade, or switch)'
132
134
  def upgrade_ruby(name, version)
133
- app = Services::AppRegistry.find(name)
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.2
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 HTTPS setup
96
+ summary: Zero-config CLI tool to manage local Rails apps with automatic Caddy and
97
+ HTTPS setup
96
98
  test_files: []