stable-cli-rails 0.8.2 → 0.8.4

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: ea91d16ba356305a67c3627e75bfe16f2d780c0523d5420485accf4b4b70a2ca
4
+ data.tar.gz: c7344e77e0294a139d14e588fb28706b9c2e22cb5b1b00ae0aaa8e05d182b74a
5
5
  SHA512:
6
- metadata.gz: 9f86445108712b6eb9cb99a14f5da5df53e14d11d646d3ccc9525dc23efec767ae2a6a2f6cb68c0ac032f75928992dfb0913580900ebae6d2426660051f5191b
7
- data.tar.gz: 2965495aa69ea21c4c19c7020222a90ee84214d05530a1b6175e9ce6689dda13d94a508cb708c9d2c2447f8b484b6afe127e7ae19c08efcf5dfefea247757d03
6
+ metadata.gz: ab9bfc8f6f5c5588ad6f9b8819ea4b504653ebe40e885e0796c51082e33b8a4e02189aca720dbed0edb971e558c6f4e23d2d405189ab53301eef6283fe3d4280
7
+ data.tar.gz: 8de8596f02772e8a98538ec45b52648869dde114bc65cf5958abff944a5c4c52389c278d1c821589952d0ef347974f22a7c0f9bb25f90ef7159370bfb10130ec
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,14 @@ 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)
135
+ Commands::UpgradeRuby.new(name, version).call
136
+ end
150
137
 
151
- puts "#{name} now uses Ruby #{version}"
138
+ desc 'open APP', 'Open a running app in the browser'
139
+ def open(app_name)
140
+ Stable::Commands::Open.new(app_name).call
152
141
  end
153
142
 
154
143
  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,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Stable
4
+ module Commands
5
+ # Open command - opens a Rails application in a browser
6
+ class Open
7
+ def initialize(app_name)
8
+ @app_name = app_name
9
+ end
10
+
11
+ def call
12
+ app = Services::AppRegistry.find(@app_name)
13
+ abort "App '#{@app_name}' not found" unless app
14
+
15
+ abort "App '#{@app_name}' is not running" unless app[:pid] && process_alive?(app[:pid])
16
+ url = build_url(app)
17
+ open_browser(url)
18
+ puts "✔ Opened #{url}"
19
+ end
20
+
21
+ private
22
+
23
+ def build_url(app)
24
+ scheme = app[:skip_ssl] ? 'http' : 'https'
25
+ if app[:domain]
26
+ "#{scheme}://#{app[:domain]}"
27
+ else
28
+ "#{scheme}://127.0.0.1:#{app[:port]}"
29
+ end
30
+ end
31
+
32
+ def open_browser(url)
33
+ cmd =
34
+ case RbConfig::CONFIG['host_os']
35
+ when /darwin/
36
+ "open #{url}"
37
+ when /linux/
38
+ "xdg-open #{url}"
39
+ when /mswin|mingw/
40
+ "start #{url}"
41
+ else
42
+ abort 'Unsupported OS'
43
+ end
44
+
45
+ system(cmd) || abort('Failed to open browser')
46
+ end
47
+
48
+ def process_alive?(pid)
49
+ Process.kill(0, pid)
50
+ true
51
+ rescue Errno::ESRCH
52
+ false
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,161 @@
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
+ # 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
58
+ cleanup_rvm_gemset(app)
59
+
60
+ # 2. Install new Ruby version
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
+ unless ENV['STABLE_TEST_MODE']
97
+ Stable::Services::Ruby.ensure_version(new_version)
98
+ Stable::Services::Ruby.ensure_rvm!
99
+
100
+ # Create gemset
101
+ Stable::System::Shell.run("bash -lc 'source #{Stable::Services::Ruby.rvm_script} && rvm #{new_version} do rvm gemset create #{@name} || true'")
102
+
103
+ rvm_cmd = Stable::Services::Ruby.rvm_prefix(new_version, @name)
104
+
105
+ # Install Bundler
106
+ Stable::System::Shell.run("bash -lc '#{rvm_cmd} gem install bundler --no-document'")
107
+
108
+ # Run bundle install
109
+ Stable::System::Shell.run(rvm_run('bundle install --jobs=4 --retry=3', chdir: app[:path]))
110
+ end
111
+
112
+ # Update app configuration
113
+ unless ENV['STABLE_TEST_MODE']
114
+ Dir.chdir(app[:path]) do
115
+ File.write('.ruby-version', "#{new_version}\n")
116
+ File.write('.ruby-gemset', "#{@name}\n")
117
+ end
118
+ end
119
+
120
+ # Update registry
121
+ Services::AppRegistry.update(@name, ruby: new_version)
122
+ puts " ✅ New Ruby #{new_version} environment set up with gems"
123
+ end
124
+
125
+ def rvm_run(cmd, chdir: nil)
126
+ cd = chdir ? "cd #{chdir} && " : ''
127
+ "bash -lc '#{cd}source #{Dir.home}/.rvm/scripts/rvm && rvm #{@version}@#{@name} do #{cmd}'"
128
+ end
129
+
130
+ def action(current_version, new_version)
131
+ current_parts = current_version.split('.').map(&:to_i)
132
+ new_parts = new_version.split('.').map(&:to_i)
133
+
134
+ if new_parts[0] > current_parts[0] ||
135
+ (new_parts[0] == current_parts[0] && new_parts[1] > current_parts[1]) ||
136
+ (new_parts[0] == current_parts[0] && new_parts[1] == current_parts[1] && new_parts[2] > current_parts[2])
137
+ 'Upgrading'
138
+ elsif new_parts[0] < current_parts[0] ||
139
+ (new_parts[0] == current_parts[0] && new_parts[1] < current_parts[1]) ||
140
+ (new_parts[0] == current_parts[0] && new_parts[1] == current_parts[1] && new_parts[2] < current_parts[2])
141
+ 'Downgrading'
142
+ else
143
+ 'Switching'
144
+ end
145
+ end
146
+
147
+ def past_tense_action(action)
148
+ case action
149
+ when 'Upgrading'
150
+ 'upgraded'
151
+ when 'Downgrading'
152
+ 'downgraded'
153
+ when 'Switching'
154
+ 'switched'
155
+ else
156
+ 'updated'
157
+ end
158
+ end
159
+ end
160
+ end
161
+ 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.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Simfukwe
@@ -41,11 +41,13 @@ files:
41
41
  - lib/stable/commands/doctor.rb
42
42
  - lib/stable/commands/list.rb
43
43
  - lib/stable/commands/new.rb
44
+ - lib/stable/commands/open.rb
44
45
  - lib/stable/commands/remove.rb
45
46
  - lib/stable/commands/restart.rb
46
47
  - lib/stable/commands/setup.rb
47
48
  - lib/stable/commands/start.rb
48
49
  - lib/stable/commands/stop.rb
50
+ - lib/stable/commands/upgrade_ruby.rb
49
51
  - lib/stable/config/paths.rb
50
52
  - lib/stable/db_manager.rb
51
53
  - lib/stable/paths.rb
@@ -90,7 +92,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
92
  - !ruby/object:Gem::Version
91
93
  version: '0'
92
94
  requirements: []
93
- rubygems_version: 3.6.7
95
+ rubygems_version: 3.6.9
94
96
  specification_version: 4
95
- summary: CLI tool to manage local Rails apps with automatic Caddy and HTTPS setup
97
+ summary: Zero-config CLI tool to manage local Rails apps with automatic Caddy and
98
+ HTTPS setup
96
99
  test_files: []