Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ Style/StringLiteralsInInterpolation:

Style/RedundantReturn:
Enabled: false

Style/StderrPuts:
Enabled: false
6 changes: 6 additions & 0 deletions lib/psdk/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions lib/psdk/cli/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
60 changes: 60 additions & 0 deletions lib/psdk/helpers/version_update.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# 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
$stderr.puts "Failed to update: #{e.message}"
exit(1)
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 Gem::Version.new(remote_version) > Gem::Version.new(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
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...'
result = system('gem install psdk-cli')
raise 'gem install psdk-cli failed' unless result

puts 'Update complete.'
exit
end
end
end
end
88 changes: 88 additions & 0 deletions spec/psdk/helpers/version_update_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# 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
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
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

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
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
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($stderr).to receive(:puts).with(
'Failed to update: Could not find psdk-cli in remote gems'
)
Psdk::Cli::VersionUpdate.check_and_update
end
end
end
end
# rubocop:enable Metrics/BlockLength