Module: Strata::CLI::Utils::VersionChecker

Defined in:
lib/strata/cli/utils/version_checker.rb

Constant Summary collapse

GEM_NAME =
"strata-cli"
RUBYGEMS_API_URL =
"https://rubygems.org/api/v1/gems/#{GEM_NAME}.json".freeze
CACHE_FILE =
File.join(ENV.fetch("TMPDIR", "/tmp"), "strata-cli-version-check-cache")
CACHE_DURATION =

24 hours in seconds

86_400

Class Method Summary collapse

Class Method Details

.cache_valid?Boolean

Returns:

  • (Boolean)


103
104
105
106
107
108
# File 'lib/strata/cli/utils/version_checker.rb', line 103

def cache_valid?
  return false unless File.exist?(CACHE_FILE)

  cache_time = File.mtime(CACHE_FILE)
  (Time.now - cache_time) < CACHE_DURATION
end

.check_and_notify(current_version) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/strata/cli/utils/version_checker.rb', line 21

def check_and_notify(current_version)
  return if skip_check?

  latest_version = fetch_latest_version
  return unless latest_version

  display_update_message(latest_version) if newer_version_available?(current_version, latest_version)

  update_cache
rescue
  # Silently fail - version checking should never break the CLI
  # In development, you might want to log this: warn "Version check failed: #{e.message}"
  nil
end

.check_and_notify_if_needed(current_version, args) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/strata/cli/utils/version_checker.rb', line 114

def check_and_notify_if_needed(current_version, args)
  # Skip version check for version and help commands
  command = args.first
  return if args.empty? || %w[version help].include?(command)

  # Early return if we should skip (avoids any work when cache is valid)
  return if skip_check?

  begin
    # Run synchronously with timeout to ensure it completes before process exits
    Timeout.timeout(3) do
      check_and_notify(current_version)
    end
  rescue Timeout::Error
    # If it takes too long, silently fail
    nil
  rescue
    # Silently fail - version checking should never break the CLI
    nil
  end
end

.display_update_message(version) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
# File 'lib/strata/cli/utils/version_checker.rb', line 83

def display_update_message(version)
  require_relative "../helpers/color_helper"
  colors = ColorHelper

  message = "💡 Tip: A new version of #{GEM_NAME} (#{version}) is available. " \
            "Update with: #{colors.info("gem update strata-cli")}"

  # Use Thor's say method for consistent output
  shell = Thor::Shell::Color.new
  shell.say "\n#{colors.warning(message)}\n"
end

.fetch_latest_versionObject



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/strata/cli/utils/version_checker.rb', line 58

def fetch_latest_version
  uri = URI(RUBYGEMS_API_URL)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
  http.open_timeout = 2 # 2 second timeout
  http.read_timeout = 2

  response = http.get(uri.path)
  parse_version_response(response)
rescue
  # Silently fail - version checking should never break the CLI
  # This includes SSL errors, network errors, timeouts, etc.
  nil
end

.newer_version_available?(current, latest) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/strata/cli/utils/version_checker.rb', line 36

def newer_version_available?(current, latest)
  return false unless current && latest

  # Simple version comparison (assumes semantic versioning)
  # Convert non-numeric parts (like "beta") to 0 for comparison
  current_parts = current.split(".").map(&:to_i)
  latest_parts = latest.split(".").map(&:to_i)

  # Pad with zeros if needed
  max_length = [current_parts.length, latest_parts.length].max
  current_parts += [0] * (max_length - current_parts.length)
  latest_parts += [0] * (max_length - latest_parts.length)

  # Compare arrays element by element
  latest_parts.zip(current_parts).each do |latest_part, current_part|
    return true if latest_part > current_part
    return false if latest_part < current_part
  end

  false # Versions are equal
end

.parse_version_response(response) ⇒ Object



74
75
76
77
78
79
80
81
# File 'lib/strata/cli/utils/version_checker.rb', line 74

def parse_version_response(response)
  return nil unless response.is_a?(Net::HTTPSuccess)

  data = JSON.parse(response.body)
  data["version"]
rescue JSON::ParserError
  nil
end

.skip_check?Boolean

Returns:

  • (Boolean)


95
96
97
98
99
100
101
# File 'lib/strata/cli/utils/version_checker.rb', line 95

def skip_check?
  return true if ENV["STRATA_SKIP_VERSION_CHECK"] == "true"
  return false unless cache_valid?

  # Check was done recently, skip
  true
end

.update_cacheObject



110
111
112
# File 'lib/strata/cli/utils/version_checker.rb', line 110

def update_cache
  FileUtils.touch(CACHE_FILE)
end