# frozen_string_literal: true require 'json' require 'etc' module Diffend module Voting # Module responsible for handling both local and remote gem versions module Versions # Module responsible for fetching safe/malicious votes # for current or current/new versions of gems module Remote # API version API_VERSION = '0.1' # Platform type ruby PLATFORM_TYPE = 0 private_constant :API_VERSION, :PLATFORM_TYPE class << self # @param command [String] either install or update # @param definition [Bundler::Definition] definition for your source # @param config [OpenStruct] diffend config def call(command, config, definition) payload = payload(command, config.project_id, definition) response = Diffend::Request.call( build_request_object(command, config, payload) ) JSON.parse(response.body) rescue StandardError => e Diffend::HandleErrors::Report.call( exception: e, payload: payload || {}, config: config, message: :unhandled_exception, report: true ) end # @param command [String] either install or update # @param config [OpenStruct] diffend config # @param payload [Hash] # # @return [Diffend::RequestObject] def build_request_object(command, config, payload) Diffend::RequestObject.new( config: config, url: commands_url(command, config.project_id), payload: payload, request_method: :post ) end # Build diffend, host, packages, and platform specific information # # @param command [String] either install or update # @param project_id [String] diffend project_id # @param definition [Bundler::Definition] definition for your source # # @return [Hash] payload for diffend endpoint def payload(command, project_id, definition) { 'diffend' => build_diffend(project_id), 'host' => build_host, 'packages' => Local.call(command, definition), 'platform' => build_platform }.freeze end # Build diffend information # # @param project_id [String, nil] diffend project_id # # @return [Hash] def build_diffend(project_id) { 'api_version' => API_VERSION, 'environment' => build_diffend_environment, 'project_id' => project_id, 'type' => PLATFORM_TYPE, 'version' => Diffend::VERSION }.freeze end # Build diffend environment information # # @return [String] def build_diffend_environment ENV['DIFFEND_ENV'] || 'development' end # Build platform information # # @return [Hash] def build_platform { 'bundler' => { 'version' => Bundler::VERSION }, 'environment' => build_platform_environment, 'ruby' => build_platform_ruby, 'rubygems' => { 'specification_version' => Gem::Specification::CURRENT_SPECIFICATION_VERSION, 'version' => Gem::VERSION } }.freeze end # Build platform ruby information # # @return [Hash] def build_platform_ruby if defined?(JRUBY_VERSION) revision = JRUBY_REVISION.to_s version = JRUBY_VERSION else revision = RUBY_REVISION.to_s version = RUBY_ENGINE_VERSION end { 'engine' => RUBY_ENGINE, 'patchlevel' => RUBY_PATCHLEVEL, 'release_date' => RUBY_RELEASE_DATE, 'revision' => revision, 'version' => version } end # Build platform environment information # # @return [String] def build_platform_environment ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development' end # Build host information # # @return [Hash] def build_host uname = Etc.uname { 'command' => build_host_command, 'ips' => build_host_ips, 'name' => uname[:nodename], 'system' => { 'machine' => uname[:machine], 'name' => uname[:sysname], 'release' => uname[:release], 'version' => uname[:version] }, 'tags' => build_host_tags, 'user' => Etc.getpwuid(Process.uid).name, 'pid' => Process.pid }.freeze end # Build host command information # # @return [Hash] def build_host_command { 'name' => $PROGRAM_NAME.split('/').last.strip, 'options' => ARGV.join(' ') } end # Build host ips, except localhost and loopback # # @return [Array] def build_host_ips Socket.ip_address_list.map do |ip| next if ip.ipv4_loopback? || ip.ipv6_loopback? || ip.ipv6_linklocal? ip.ip_address end.compact end # Build host tags # # @return [Array] def build_host_tags tags = [] if ENV.key?('GITHUB_ACTIONS') tags << 'ci' tags << 'ci-github' end if ENV.key?('CIRCLECI') tags << 'ci' tags << 'ci-circle' end tags end # Provides diffend command endpoint url # # @param command [String] either install or update # @param project_id [String] diffend project_id # # @return [String] diffend endpoint def commands_url(command, project_id) return ENV['DIFFEND_COMMAND_URL'] if ENV.key?('DIFFEND_COMMAND_URL') "https://my.diffend.io/api/projects/#{project_id}/bundle/#{command}" end end end end end end