diffend 0.2.29 → 0.2.34

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diffend
4
+ # Module for all the components related to setting up the config
5
+ module Configs
6
+ # Class responsible for validating the config from .diffend.yml
7
+ module Validator
8
+ KNOWN_KEYS = {
9
+ project_id: [String],
10
+ shareable_id: [String],
11
+ shareable_key: [String],
12
+ build_path: [String],
13
+ env: [String],
14
+ command: [String],
15
+ ignore_errors?: [TrueClass, FalseClass],
16
+ development?: [TrueClass, FalseClass]
17
+ }.freeze
18
+
19
+ class << self
20
+ # @param config [Diffend::Config]
21
+ def call(config)
22
+ KNOWN_KEYS.each_key do |key|
23
+ if missing?(config, key)
24
+ missing_key_message(key)
25
+ .tap(&config.logger.method(:fatal))
26
+
27
+ raise Diffend::Errors::HandledException
28
+ end
29
+
30
+ if invalid?(config, key)
31
+ invalid_key_message(config, key)
32
+ .tap(&config.logger.method(:fatal))
33
+
34
+ raise Diffend::Errors::HandledException
35
+ end
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ # @param config [Diffend::Config]
42
+ # @param key [String]
43
+ #
44
+ # @return [Boolean] true if we are missing a key, false otherwise
45
+ def missing?(config, key)
46
+ value = config.public_send(key)
47
+
48
+ value.nil? || (value.respond_to?(:empty?) && value.empty?)
49
+ end
50
+
51
+ # @param config [Diffend::Config]
52
+ # @param key [String]
53
+ #
54
+ # @return [Boolean] true if we are missing a key, false otherwise
55
+ def invalid?(config, key)
56
+ !KNOWN_KEYS[key].include?(config.public_send(key).class)
57
+ end
58
+
59
+ # Missing key message
60
+ #
61
+ # @param key [String] missing key
62
+ #
63
+ # @return [String]
64
+ def missing_key_message(key)
65
+ <<~MSG
66
+ \nDiffend configuration is missing #{key} key.\n
67
+ MSG
68
+ end
69
+
70
+ # Invalid key message
71
+ #
72
+ # @param hash [Hash] config hash
73
+ # @param key [String] invalid key
74
+ #
75
+ # @return [String]
76
+ def invalid_key_message(hash, key)
77
+ <<~MSG
78
+ \nDiffend configuration value for #{key} is invalid.\n
79
+ It should be #{KNOWN_KEYS[key].join(' or ')} but is #{hash.public_send(key).class}.\n
80
+ MSG
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -5,10 +5,6 @@ module Diffend
5
5
  module Errors
6
6
  # Base error class from which all the errors should inherit
7
7
  BaseError = Class.new(StandardError)
8
- # Raised when we couldn't find a valid configuration file
9
- MissingConfigurationFile = Class.new(BaseError)
10
- # Raised when configuration file is empty
11
- EmptyConfigurationFile = Class.new(BaseError)
12
8
  # Raised when configuration file is malformed
13
9
  MalformedConfigurationFile = Class.new(BaseError)
14
10
  # Raised when project_id is missing in configuration file
@@ -23,5 +19,7 @@ module Diffend
23
19
  RequestServerError = Class.new(BaseError)
24
20
  # Raised when we had an exception that we know how to handle
25
21
  HandledException = Class.new(BaseError)
22
+ # Raised when we are unable to resolve dependencies
23
+ DependenciesResolveException = Class.new(BaseError)
26
24
  end
27
25
  end
@@ -1,28 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Diffend
4
- # Verifies voting verdicts for gems
5
- module Voting
4
+ # Executes a check for a given command
5
+ module Execute
6
6
  class << self
7
7
  # Build verdict
8
8
  #
9
- # @param command [String] either install or update
10
- # @param config [OpenStruct] diffend config
11
- # @param definition [Bundler::Definition] definition for your source
12
- def call(command, config, definition)
13
- Versions::Remote
14
- .call(command, config, definition)
15
- .tap { |response| build_message(command, config, response) }
9
+ # @param config [Diffend::Config]
10
+ def call(config)
11
+ Diffend::RequestVerdict
12
+ .call(config, build_definition(config.command))
13
+ .tap { |response| build_message(config, response) }
14
+ rescue Diffend::Errors::DependenciesResolveException
15
+ # We are unable to resolve dependencies, no message will be printed
16
16
  end
17
17
 
18
- # @param command [String] either install or update
19
- # @param config [OpenStruct] diffend config
18
+ # Build bundler definition
19
+ #
20
+ # @return [Bundler::Definition]
21
+ def build_definition(command)
22
+ Diffend::BuildBundlerDefinition.call(
23
+ command,
24
+ Bundler.default_gemfile,
25
+ Bundler.default_lockfile
26
+ )
27
+ end
28
+
29
+ # @param config [Diffend::Config]
20
30
  # @param response [Hash] response from diffend API
21
- def build_message(command, config, response)
31
+ def build_message(config, response)
22
32
  if response.key?('error')
23
- build_error(response)
33
+ build_error(config, response)
24
34
  elsif response.key?('action')
25
- build_verdict(command, config, response)
35
+ build_verdict(config, response)
26
36
  else
27
37
  Diffend::HandleErrors::Report.call(
28
38
  config: config,
@@ -36,25 +46,24 @@ module Diffend
36
46
  # @param response [Hash] response from diffend API
37
47
  def build_error(response)
38
48
  build_error_message(response)
39
- .tap(&Bundler.ui.method(:error))
49
+ .tap(&config.logger.method(:error))
40
50
 
41
51
  raise Diffend::Errors::HandledException
42
52
  end
43
53
 
44
- # @param command [String] either install or update
45
- # @param config [OpenStruct] diffend config
54
+ # @param config [Diffend::Config]
46
55
  # @param response [Hash] response from diffend API
47
- def build_verdict(command, config, response)
56
+ def build_verdict(config, response)
48
57
  case response['action']
49
58
  when 'allow'
50
- build_allow_message(command, response)
51
- .tap(&Bundler.ui.method(:confirm))
59
+ build_allow_message(config.command, response)
60
+ .tap(&config.logger.method(:info))
52
61
  when 'warn'
53
- build_warn_message(command, response)
54
- .tap(&Bundler.ui.method(:warn))
62
+ build_warn_message(config.command, response)
63
+ .tap(&config.logger.method(:warn))
55
64
  when 'deny'
56
- build_deny_message(command, response)
57
- .tap(&Bundler.ui.method(:error))
65
+ build_deny_message(config.command, response)
66
+ .tap(&config.logger.method(:error))
58
67
 
59
68
  exit 1
60
69
  else
@@ -77,7 +86,7 @@ module Diffend
77
86
  MSG
78
87
  end
79
88
 
80
- # @param command [String] either install or update
89
+ # @param command [String] command executed via bundler
81
90
  # @param response [Hash] response from diffend API
82
91
  #
83
92
  # @return [String]
@@ -89,7 +98,7 @@ module Diffend
89
98
  MSG
90
99
  end
91
100
 
92
- # @param command [String] either install or update
101
+ # @param command [String] command executed via bundler
93
102
  # @param response [Hash] response from diffend API
94
103
  #
95
104
  # @return [String]
@@ -101,7 +110,7 @@ module Diffend
101
110
  MSG
102
111
  end
103
112
 
104
- # @param command [String] either install or update
113
+ # @param command [String] command executed via bundler
105
114
  # @param response [Hash] response from diffend API
106
115
  #
107
116
  # @return [String]
@@ -114,7 +123,7 @@ module Diffend
114
123
  end
115
124
 
116
125
  # @param type [String] verdict type
117
- # @param command [String] either install or update
126
+ # @param command [String] command executed via bundler
118
127
  #
119
128
  # @return [String]
120
129
  def build_message_header(type, command)
@@ -7,10 +7,10 @@ module Diffend
7
7
  class << self
8
8
  # Execute request to Diffend
9
9
  #
10
+ # @param config [Diffend::Config]
11
+ # @param message [Symbol] message that we want to display
10
12
  # @param exception [Exception] expection that was raised
11
13
  # @param payload [Hash] with versions to check
12
- # @param config [OpenStruct] Diffend config
13
- # @param message [Symbol] message that we want to display
14
14
  # @param report [Boolean] if true we will report the issue to diffend
15
15
  # @param raise_exception [Boolean] if true we will raise an exception
16
16
  #
@@ -18,8 +18,11 @@ module Diffend
18
18
  def call(config:, message:, exception: nil, payload: {}, report: false, raise_exception: true)
19
19
  exception_payload = prepare_exception_payload(exception, payload)
20
20
 
21
- Bundler.ui.error(Diffend::HandleErrors::Messages::PAYLOAD_DUMP)
22
- Bundler.ui.error(Diffend::HandleErrors::Messages.const_get(message.to_s.upcase))
21
+ Diffend::HandleErrors::Messages::PAYLOAD_DUMP
22
+ .tap(&config.logger.method(:error))
23
+ Diffend::HandleErrors::Messages
24
+ .const_get(message.to_s.upcase)
25
+ .tap(&config.logger.method(:error))
23
26
 
24
27
  if report
25
28
  Diffend::Request.call(
@@ -30,14 +33,14 @@ module Diffend
30
33
  raise Diffend::Errors::HandledException if raise_exception
31
34
  end
32
35
 
33
- # @param config [OpenStruct] diffend config
36
+ # @param config [Diffend::Config]
34
37
  # @param payload [Hash]
35
38
  #
36
39
  # @return [Diffend::RequestObject]
37
40
  def build_request_object(config, payload)
38
41
  Diffend::RequestObject.new(
39
42
  config: config,
40
- url: errors_url(config.project_id),
43
+ url: config.errors_url,
41
44
  payload: payload,
42
45
  request_method: :post
43
46
  )
@@ -54,17 +57,6 @@ module Diffend
54
57
  .call(exception, payload)
55
58
  .tap(&Diffend::HandleErrors::DisplayToStdout.method(:call))
56
59
  end
57
-
58
- # Provides diffend errors endpoint url
59
- #
60
- # @param project_id [String] diffend project_id
61
- #
62
- # @return [String] diffend endpoint
63
- def errors_url(project_id)
64
- return ENV['DIFFEND_ERROR_URL'] if ENV.key?('DIFFEND_ERROR_URL')
65
-
66
- "https://my.diffend.io/api/projects/#{project_id}/errors"
67
- end
68
60
  end
69
61
  end
70
62
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diffend
4
+ # Verify if we are running latest version of the plugin
5
+ module LatestVersion
6
+ class << self
7
+ # Verify if we are running latest version of the plugin
8
+ #
9
+ # @param config [Diffend::Config]
10
+ def call(config)
11
+ return if config.development?
12
+ return if installed_version == Diffend::VERSION
13
+
14
+ print_message(config, installed_version)
15
+
16
+ exit 2
17
+ end
18
+
19
+ private
20
+
21
+ # @return [String] installed plugin version
22
+ def installed_version
23
+ ::Bundler::Plugin
24
+ .index
25
+ .plugin_path('diffend')
26
+ .basename
27
+ .to_s
28
+ .split('-')
29
+ .last
30
+ end
31
+
32
+ # @param config [Diffend::Config]
33
+ # @param version [Hash] installed version
34
+ def print_message(config, version)
35
+ build_message(version)
36
+ .tap(&config.logger.method(:error))
37
+ end
38
+
39
+ # @param version [Hash] installed version
40
+ #
41
+ # @return [String]
42
+ def build_message(version)
43
+ <<~MSG
44
+ \nYou are running an outdated version (#{version}) of the plugin, which will lead to issues.
45
+ \nPlease upgrade to the latest one (#{Diffend::VERSION}) by executing "rm -rf .bundle/plugin".\n
46
+ MSG
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diffend
4
+ # Module responsible for building local context
5
+ module LocalContext
6
+ class << self
7
+ # Build diffend, host, packages, and platform specific information
8
+ #
9
+ # @param config [Diffend::Config]
10
+ # @param definition [Bundler::Definition] definition for your source
11
+ #
12
+ # @return [Hash] payload for diffend endpoint
13
+ def call(config, definition)
14
+ {
15
+ 'diffend' => Diffend.call(config),
16
+ 'host' => Host.call,
17
+ 'packages' => Packages.call(config.command, definition),
18
+ 'platform' => Platform.call
19
+ }.freeze
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diffend
4
+ # Module responsible for building local context
5
+ module LocalContext
6
+ # Module responsible for building diffend information from local context
7
+ module Diffend
8
+ # API version
9
+ API_VERSION = '0.1'
10
+ # Platform type ruby
11
+ PLATFORM_TYPE = 0
12
+
13
+ private_constant :API_VERSION, :PLATFORM_TYPE
14
+
15
+ class << self
16
+ # Build diffend information
17
+ #
18
+ # @param config [Diffend::Config]
19
+ #
20
+ # @return [Hash]
21
+ def call(config)
22
+ {
23
+ 'api_version' => API_VERSION,
24
+ 'environment' => config.env,
25
+ 'project_id' => config.project_id,
26
+ 'type' => PLATFORM_TYPE,
27
+ 'version' => ::Diffend::VERSION
28
+ }.freeze
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'etc'
4
+
5
+ module Diffend
6
+ # Module responsible for building local context
7
+ module LocalContext
8
+ # Module responsible for building host information from local context
9
+ module Host
10
+ class << self
11
+ # Build host information
12
+ #
13
+ # @return [Hash]
14
+ def call
15
+ uname = Etc.uname
16
+
17
+ {
18
+ 'command' => command,
19
+ 'ips' => ips,
20
+ 'name' => uname[:nodename],
21
+ 'system' => {
22
+ 'machine' => uname[:machine],
23
+ 'name' => uname[:sysname],
24
+ 'release' => uname[:release],
25
+ 'version' => uname[:version]
26
+ },
27
+ 'tags' => tags,
28
+ 'user' => Etc.getpwuid(Process.uid).name,
29
+ 'pid' => Process.pid
30
+ }.freeze
31
+ end
32
+
33
+ private
34
+
35
+ # Build host command information
36
+ #
37
+ # @return [Hash]
38
+ def command
39
+ if File.exist?($PROGRAM_NAME)
40
+ if defined?(JRUBY_VERSION)
41
+ name = $PROGRAM_NAME.split('/').last.strip
42
+ command = "#{name} #{ARGV.join(' ')}"
43
+ else
44
+ array = `ps -p #{Process.pid} -o command=`.strip.split(' ')
45
+ array.shift if array.first.end_with?('bin/ruby')
46
+ name = array.shift.split('/').last.strip
47
+ command = "#{name} #{array.join(' ')}"
48
+ end
49
+
50
+ { 'name' => command, 'title' => '' }
51
+ else
52
+ { 'name' => ARGV.join(' '), 'title' => $PROGRAM_NAME }
53
+ end
54
+ end
55
+
56
+ # Build host ips, except localhost and loopback
57
+ #
58
+ # @return [Array<String>]
59
+ def ips
60
+ Socket.ip_address_list.map do |ip|
61
+ next if ip.ipv4_loopback? || ip.ipv6_loopback? || ip.ipv6_linklocal?
62
+
63
+ ip.ip_address
64
+ end.compact
65
+ end
66
+
67
+ # Build host tags
68
+ #
69
+ # @return [Array]
70
+ def tags
71
+ tags = []
72
+
73
+ if ENV.key?('GITHUB_ACTIONS')
74
+ tags << 'ci'
75
+ tags << 'ci-github'
76
+ end
77
+
78
+ if ENV.key?('CIRCLECI')
79
+ tags << 'ci'
80
+ tags << 'ci-circle'
81
+ end
82
+
83
+ tags
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end