From d587f7419475941ce6d3d247699dd1b4c21fe71a Mon Sep 17 00:00:00 2001 From: Nuri Yuri Date: Sun, 23 Nov 2025 11:34:46 +0100 Subject: [PATCH 1/4] feat: Add `update` command to CLI for self-updating and adjust global configuration path. (Fix #6) --- lib/psdk/cli.rb | 6 +++ lib/psdk/cli/configuration.rb | 4 +- lib/psdk/helpers/version_update.rb | 53 ++++++++++++++++++++ spec/psdk/helpers/version_update_spec.rb | 63 ++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 lib/psdk/helpers/version_update.rb create mode 100644 spec/psdk/helpers/version_update_spec.rb diff --git a/lib/psdk/cli.rb b/lib/psdk/cli.rb index 946df13..f8fc1a3 100644 --- a/lib/psdk/cli.rb +++ b/lib/psdk/cli.rb @@ -20,6 +20,12 @@ def version Version.run(options[:no_psdk_version]) end + desc 'update', 'update the psdk-cli' + def update + require_relative 'helpers/version_update' + VersionUpdate.check_and_update + end + desc 'plugin', 'manage PSDK plugins' subcommand 'plugin', Plugin end diff --git a/lib/psdk/cli/configuration.rb b/lib/psdk/cli/configuration.rb index e5a876a..ae0064b 100644 --- a/lib/psdk/cli/configuration.rb +++ b/lib/psdk/cli/configuration.rb @@ -10,10 +10,10 @@ class Configuration PROJECT_CONFIGURATION_FILENAME = '.psdk-cli.yml' # Path where all the global configuration are stored - PATH = ENV.fetch('PSDK_CLI_DIR', Dir.home || ENV['USERPROFILE'] || '~') + PATH = File.join(ENV.fetch('PSDK_CLI_DIR', Dir.home || ENV['USERPROFILE'] || '~'), '.psdk-cli') # Filename of the global configuration - GLOBAL_CONFIGURATION_FILENAME = File.join(PATH, '.psdk-cli/config.yml') + GLOBAL_CONFIGURATION_FILENAME = File.join(PATH, 'config.yml') # Create a new configuration # @param hash [Hash] configuration hash diff --git a/lib/psdk/helpers/version_update.rb b/lib/psdk/helpers/version_update.rb new file mode 100644 index 0000000..92267aa --- /dev/null +++ b/lib/psdk/helpers/version_update.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require_relative '../cli/version' + +module Psdk + module Cli + # Module holding the logic to update the psdk-cli gem + module VersionUpdate + module_function + + # Check if the psdk-cli gem is up-to-date and update it if needed + def check_and_update + puts 'Checking for updates...' + local_version = Psdk::Cli::VERSION + remote_version = fetch_remote_version + + compare_and_update_versions(local_version, remote_version) + rescue StandardError => e + puts "Failed to check for updates: #{e.message}" + end + + # Compare local and remote versions and update if necessary + # @param local_version [String] The currently installed version + # @param remote_version [String] The latest version available + def compare_and_update_versions(local_version, remote_version) + if remote_version > local_version + puts "New version available: #{remote_version} (current: #{local_version})" + update_gem + else + puts 'psdk-cli is up-to-date.' + end + end + + # Fetch the latest version of psdk-cli from rubygems + # @return [String] + def fetch_remote_version + output = `gem search -r psdk-cli` + match = output.match(/psdk-cli \(([\d.]+)\)/) + return match[1] if match + + raise 'Could not find psdk-cli in remote gems' + end + + # Update the psdk-cli gem + def update_gem + puts 'Updating psdk-cli...' + system('gem install psdk-cli') + puts 'Update complete. Please restart the command.' + exit + end + end + end +end diff --git a/spec/psdk/helpers/version_update_spec.rb b/spec/psdk/helpers/version_update_spec.rb new file mode 100644 index 0000000..9fff786 --- /dev/null +++ b/spec/psdk/helpers/version_update_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'psdk/helpers/version_update' + +# rubocop:disable Metrics/BlockLength +RSpec.describe Psdk::Cli::VersionUpdate do + describe '.check_and_update' do + let(:local_version) { '1.0.0' } + let(:remote_version) { '1.0.1' } + let(:gem_search_output) { "psdk-cli (#{remote_version})\n" } + + before do + stub_const('Psdk::Cli::VERSION', local_version) + allow(Psdk::Cli::VersionUpdate).to receive(:`).with('gem search -r psdk-cli').and_return(gem_search_output) + allow(Psdk::Cli::VersionUpdate).to receive(:puts) + allow(Psdk::Cli::VersionUpdate).to receive(:system) + allow(Psdk::Cli::VersionUpdate).to receive(:exit) + end + + context 'when a new version is available' do + it 'updates the gem' do + expect(Psdk::Cli::VersionUpdate).to receive(:system).with('gem install psdk-cli') + Psdk::Cli::VersionUpdate.check_and_update + end + + it 'exits after update' do + expect(Psdk::Cli::VersionUpdate).to receive(:exit) + Psdk::Cli::VersionUpdate.check_and_update + end + end + + context 'when the local version is up-to-date' do + let(:remote_version) { '1.0.0' } + + it 'does not update the gem' do + expect(Psdk::Cli::VersionUpdate).not_to receive(:system) + Psdk::Cli::VersionUpdate.check_and_update + end + end + + context 'when the local version is newer than remote' do + let(:remote_version) { '0.9.9' } + + it 'does not update the gem' do + expect(Psdk::Cli::VersionUpdate).not_to receive(:system) + Psdk::Cli::VersionUpdate.check_and_update + end + end + + context 'when gem search fails to find the gem' do + let(:gem_search_output) { "No match found\n" } + + it 'rescues the error and prints a message' do + expect(Psdk::Cli::VersionUpdate).to receive(:puts).with( + 'Failed to check for updates: Could not find psdk-cli in remote gems' + ) + Psdk::Cli::VersionUpdate.check_and_update + end + end + end +end +# rubocop:enable Metrics/BlockLength From 1d6d540db1de8513ca6fb90aeebc124b317c64e5 Mon Sep 17 00:00:00 2001 From: Nuri Yuri Date: Sun, 23 Nov 2025 11:42:13 +0100 Subject: [PATCH 2/4] Add confirmation for update --- lib/psdk/helpers/version_update.rb | 4 ++++ spec/psdk/helpers/version_update_spec.rb | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/psdk/helpers/version_update.rb b/lib/psdk/helpers/version_update.rb index 92267aa..6a95c43 100644 --- a/lib/psdk/helpers/version_update.rb +++ b/lib/psdk/helpers/version_update.rb @@ -43,6 +43,10 @@ def fetch_remote_version # Update the psdk-cli gem def update_gem + print 'Do you want to update psdk-cli? [Y/n] ' + response = $stdin.gets.chomp + return unless response.empty? || response.casecmp('y').zero? + puts 'Updating psdk-cli...' system('gem install psdk-cli') puts 'Update complete. Please restart the command.' diff --git a/spec/psdk/helpers/version_update_spec.rb b/spec/psdk/helpers/version_update_spec.rb index 9fff786..9f05509 100644 --- a/spec/psdk/helpers/version_update_spec.rb +++ b/spec/psdk/helpers/version_update_spec.rb @@ -19,7 +19,12 @@ end context 'when a new version is available' do + before do + allow($stdin).to receive(:gets).and_return("y\n") + end + it 'updates the gem' do + expect(Psdk::Cli::VersionUpdate).to receive(:print).with('Do you want to update psdk-cli? [Y/n] ') expect(Psdk::Cli::VersionUpdate).to receive(:system).with('gem install psdk-cli') Psdk::Cli::VersionUpdate.check_and_update end @@ -28,6 +33,17 @@ expect(Psdk::Cli::VersionUpdate).to receive(:exit) Psdk::Cli::VersionUpdate.check_and_update end + + context 'when user declines update' do + before do + allow($stdin).to receive(:gets).and_return("n\n") + end + + it 'does not update the gem' do + expect(Psdk::Cli::VersionUpdate).not_to receive(:system) + Psdk::Cli::VersionUpdate.check_and_update + end + end end context 'when the local version is up-to-date' do From 2b4ab06db2bad2f32ee118f89616f51245f210ec Mon Sep 17 00:00:00 2001 From: Nuri Yuri Date: Tue, 25 Nov 2025 19:14:16 +0100 Subject: [PATCH 3/4] Apply review for error logging --- .rubocop.yml | 3 +++ lib/psdk/helpers/version_update.rb | 9 ++++++--- spec/psdk/helpers/version_update_spec.rb | 13 +++++++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index b55e282..c365e01 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -11,3 +11,6 @@ Style/StringLiteralsInInterpolation: Style/RedundantReturn: Enabled: false + +Style/StderrPuts: + Enabled: false diff --git a/lib/psdk/helpers/version_update.rb b/lib/psdk/helpers/version_update.rb index 6a95c43..bbe880f 100644 --- a/lib/psdk/helpers/version_update.rb +++ b/lib/psdk/helpers/version_update.rb @@ -16,7 +16,8 @@ def check_and_update compare_and_update_versions(local_version, remote_version) rescue StandardError => e - puts "Failed to check for updates: #{e.message}" + $stderr.puts "Failed to update: #{e.message}" + exit(1) end # Compare local and remote versions and update if necessary @@ -48,8 +49,10 @@ def update_gem return unless response.empty? || response.casecmp('y').zero? puts 'Updating psdk-cli...' - system('gem install psdk-cli') - puts 'Update complete. Please restart the command.' + result = system('gem install psdk-cli') + raise 'gem install psdk-cli failed' unless result + + puts 'Update complete.' exit end end diff --git a/spec/psdk/helpers/version_update_spec.rb b/spec/psdk/helpers/version_update_spec.rb index 9f05509..a473f17 100644 --- a/spec/psdk/helpers/version_update_spec.rb +++ b/spec/psdk/helpers/version_update_spec.rb @@ -21,6 +21,7 @@ context 'when a new version is available' do before do allow($stdin).to receive(:gets).and_return("y\n") + allow(Psdk::Cli::VersionUpdate).to receive(:system).and_return(true) end it 'updates the gem' do @@ -29,6 +30,14 @@ Psdk::Cli::VersionUpdate.check_and_update end + it 'logs an error and exits if update fails' do + expect(Psdk::Cli::VersionUpdate).to receive(:print).with('Do you want to update psdk-cli? [Y/n] ') + expect(Psdk::Cli::VersionUpdate).to receive(:system).with('gem install psdk-cli').and_return(false) + expect(Psdk::Cli::VersionUpdate).to receive(:exit).with(1) + expect($stderr).to receive(:puts).with('Failed to update: gem install psdk-cli failed') + Psdk::Cli::VersionUpdate.check_and_update + end + it 'exits after update' do expect(Psdk::Cli::VersionUpdate).to receive(:exit) Psdk::Cli::VersionUpdate.check_and_update @@ -68,8 +77,8 @@ let(:gem_search_output) { "No match found\n" } it 'rescues the error and prints a message' do - expect(Psdk::Cli::VersionUpdate).to receive(:puts).with( - 'Failed to check for updates: Could not find psdk-cli in remote gems' + expect($stderr).to receive(:puts).with( + 'Failed to update: Could not find psdk-cli in remote gems' ) Psdk::Cli::VersionUpdate.check_and_update end From 995a44e7d1e3f841f7ee3550a45fc22ed3e9a9fd Mon Sep 17 00:00:00 2001 From: Nuri Yuri Date: Thu, 27 Nov 2025 19:43:28 +0100 Subject: [PATCH 4/4] Use Gem::Version for comparing versions --- lib/psdk/helpers/version_update.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/psdk/helpers/version_update.rb b/lib/psdk/helpers/version_update.rb index bbe880f..0508c72 100644 --- a/lib/psdk/helpers/version_update.rb +++ b/lib/psdk/helpers/version_update.rb @@ -24,7 +24,7 @@ def check_and_update # @param local_version [String] The currently installed version # @param remote_version [String] The latest version available def compare_and_update_versions(local_version, remote_version) - if remote_version > local_version + if Gem::Version.new(remote_version) > Gem::Version.new(local_version) puts "New version available: #{remote_version} (current: #{local_version})" update_gem else