codeclimate/codeclimate

View on GitHub
lib/cc/cli/version_checker.rb

Summary

Maintainability
A
35 mins
Test Coverage
A
100%
require "cc/cli/global_config"
require "cc/cli/global_cache"

module CC
  module CLI
    class VersionChecker
      include CC::CLI::Output

      VERSION_CHECK_TIMEOUT = 60 * 60 # 1 Hour in seconds
      DEFAULT_VERSIONS_URL = "https://versions.codeclimate.com".freeze

      def check
        return unless global_config.check_version? && version_check_is_due?

        print_new_version_message if outdated?

        global_config.save
      rescue => error
        CLI.logger.debug(error)
      end

      private

      def version_check_is_due?
        Time.now > global_cache.last_version_check + VERSION_CHECK_TIMEOUT
      end

      def outdated?
        api_response["outdated"]
      end

      def latest_version
        api_response["latest"]
      end

      def print_new_version_message
        warn "A new version (v#{latest_version}) is available. Upgrade instructions are available at: https://github.com/codeclimate/codeclimate#packages"
      end

      def api_response
        @api_response ||=
          begin
            cache! JSON.parse(api_response_body)
          rescue JSON::ParserError => error
            CLI.logger.debug(error)
            {
              "outdated" => false,
            }
          end
      end

      def api_response_body
        if http_response.is_a? Net::HTTPSuccess
          http_response.body
        else
          raise Net::HTTPFatalError.new("HTTP Error", http_response)
        end
      rescue Net::HTTPFatalError => error
        CLI.logger.debug(error)
        ""
      end

      def http_response
        @http_response ||=
          begin
            uri = URI.parse(ENV.fetch("CODECLIMATE_VERSIONS_URL", DEFAULT_VERSIONS_URL))
            uri.query = { version: version, uid: global_config.uuid }.to_query

            http = Net::HTTP.new(uri.host, uri.port)
            http.open_timeout = 5
            http.read_timeout = 5
            http.ssl_timeout = 5
            http.use_ssl = uri.scheme == "https"

            http.get(uri, "User-Agent" => user_agent)
          end
      end

      def cache!(data)
        global_cache.latest_version = data["latest"]
        global_cache.outdated = data["outdated"] == true
        global_cache.last_version_check = Time.now
        data
      end

      def version
        @version ||= Version.new.version
      end

      def user_agent
        "Code Climate CLI #{version}"
      end

      def global_config
        @global_config ||= GlobalConfig.new
      end

      def global_cache
        @global_cache ||= GlobalCache.new
      end

      def terminal
        @terminal ||= HighLine.new(nil, $stderr)
      end
    end
  end
end