diffend 0.2.27 → 0.2.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diffend
4
+ # Module responsible for building local context
5
+ module LocalContext
6
+ # Module responsible for building platform information from local context
7
+ module Platform
8
+ class << self
9
+ # Build platform information
10
+ #
11
+ # @return [Hash]
12
+ def call
13
+ {
14
+ 'bundler' => {
15
+ 'version' => Bundler::VERSION
16
+ },
17
+ 'environment' => environment,
18
+ 'ruby' => ruby_information,
19
+ 'rubygems' => {
20
+ 'specification_version' => Gem::Specification::CURRENT_SPECIFICATION_VERSION,
21
+ 'version' => Gem::VERSION
22
+ }
23
+ }.freeze
24
+ end
25
+
26
+ private
27
+
28
+ # Build platform ruby information
29
+ #
30
+ # @return [Hash]
31
+ def ruby_information
32
+ if defined?(JRUBY_VERSION)
33
+ revision = JRUBY_REVISION.to_s
34
+ version = JRUBY_VERSION
35
+ else
36
+ revision = RUBY_REVISION.to_s
37
+ version = RUBY_ENGINE_VERSION
38
+ end
39
+
40
+ {
41
+ 'engine' => RUBY_ENGINE,
42
+ 'patchlevel' => RUBY_PATCHLEVEL,
43
+ 'release_date' => RUBY_RELEASE_DATE,
44
+ 'revision' => revision,
45
+ 'version' => version
46
+ }
47
+ end
48
+
49
+ # Build platform environment information
50
+ #
51
+ # @return [String]
52
+ def environment
53
+ ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diffend
4
+ # Diffend logging
5
+ class Logger
6
+ # Low-level information, mostly for developers.
7
+ DEBUG = 0
8
+ # Generic (useful) information about system operation.
9
+ INFO = 1
10
+ # A warning.
11
+ WARN = 2
12
+ # A handleable error condition.
13
+ ERROR = 3
14
+ # An unhandleable error that results in a program crash.
15
+ FATAL = 4
16
+ # An unknown message that should always be logged.
17
+ UNKNOWN = 5
18
+
19
+ # @param level [Integer] logging severity threshold
20
+ def initialize(level = INFO)
21
+ @level = level
22
+ end
23
+
24
+ # @param message [String]
25
+ def debug(message)
26
+ log(DEBUG, message)
27
+ end
28
+
29
+ # @param message [String]
30
+ def info(message)
31
+ log(INFO, message)
32
+ end
33
+
34
+ # @param message [String]
35
+ def warn(message)
36
+ log(WARN, message)
37
+ end
38
+
39
+ # @param message [String]
40
+ def error(message)
41
+ log(ERROR, message)
42
+ end
43
+
44
+ # @param message [String]
45
+ def fatal(message)
46
+ log(FATAL, message)
47
+ end
48
+
49
+ private
50
+
51
+ # @param severity [Integer]
52
+ # @param message [String]
53
+ def log(severity, message)
54
+ return if severity < @level
55
+
56
+ case severity
57
+ when INFO
58
+ Bundler.ui.confirm(message)
59
+ when WARN
60
+ Bundler.ui.warn(message)
61
+ when ERROR, FATAL
62
+ Bundler.ui.error(message)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -1,28 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  %w[
4
- build_bundler_definition
4
+ version
5
+ logger
5
6
  errors
6
- config/fetcher
7
- config/file_finder
8
- config/validator
7
+ build_bundler_definition
9
8
  commands
9
+ config
10
+ configs/fetcher
11
+ configs/file_finder
12
+ configs/validator
10
13
  handle_errors/messages
11
14
  handle_errors/build_exception_payload
12
15
  handle_errors/display_to_stdout
13
16
  handle_errors/report
14
17
  request_object
15
18
  request
16
- voting
19
+ local_context/diffend
20
+ local_context/host
21
+ local_context/packages
22
+ local_context/platform
23
+ local_context
24
+ request_verdict
25
+ execute
17
26
  track
18
27
  ].each { |file| require "diffend/#{file}" }
19
28
 
20
- %w[
21
- versions/local
22
- versions/remote
23
- ].each { |file| require "diffend/voting/#{file}" }
29
+ config = Diffend::Config.new(
30
+ command: Diffend::Commands::EXEC,
31
+ severity: Diffend::Logger::FATAL
32
+ )
33
+
34
+ return if %w[development test].include?(config.env)
24
35
 
25
36
  Thread.new do
26
- track = Diffend::Track.new
37
+ track = Diffend::Track.new(config)
27
38
  track.start
28
39
  end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ %w[
4
+ bundler
5
+ ].each(&method(:require))
6
+
7
+ %w[
8
+ version
9
+ logger
10
+ latest_version
11
+ errors
12
+ build_bundler_definition
13
+ commands
14
+ config
15
+ configs/fetcher
16
+ configs/file_finder
17
+ configs/validator
18
+ handle_errors/messages
19
+ handle_errors/build_exception_payload
20
+ handle_errors/display_to_stdout
21
+ handle_errors/report
22
+ request_object
23
+ request
24
+ local_context/diffend
25
+ local_context/host
26
+ local_context/packages
27
+ local_context/platform
28
+ local_context
29
+ request_verdict
30
+ execute
31
+ track
32
+ ].each { |file| require "diffend/#{file}" }
33
+
34
+ module Diffend
35
+ module Plugin
36
+ class << self
37
+ # Registers the plugin and add before install all hook
38
+ def register
39
+ ::Bundler::Plugin.add_hook('before-install-all') do |_|
40
+ execute
41
+ end
42
+ end
43
+
44
+ # Execute diffend plugin
45
+ def execute
46
+ return unless enabled?
47
+
48
+ config = Diffend::Config.new(severity: Diffend::Logger::INFO)
49
+
50
+ Diffend::LatestVersion.call(config)
51
+
52
+ Diffend::Execute.call(config)
53
+ rescue Diffend::Errors::HandledException
54
+ return if config.ignore_errors?
55
+
56
+ exit 255
57
+ rescue StandardError => e
58
+ Diffend::HandleErrors::Report.call(
59
+ exception: e,
60
+ config: config,
61
+ message: :unhandled_exception,
62
+ report: true,
63
+ raise_exception: false
64
+ )
65
+
66
+ return if config.ignore_errors?
67
+
68
+ exit 255
69
+ end
70
+
71
+ # Checks if plugin is enabled
72
+ #
73
+ # @return [Boolean] true if enabled, false otherwise
74
+ def enabled?
75
+ ::Bundler
76
+ .default_gemfile
77
+ .read
78
+ .split("\n")
79
+ .reject(&:empty?)
80
+ .map(&:strip)
81
+ .select { |line| line.start_with?('plugin') }
82
+ .any? { |line| line.include?('diffend') }
83
+ end
84
+ end
85
+ end
86
+ end
@@ -67,7 +67,7 @@ module Diffend
67
67
  rescue Diffend::Errors::RequestServerError => e
68
68
  retry_count += 1
69
69
 
70
- retry if handle_retry(SERVER_ERROR_MESSAGE, retry_count)
70
+ retry if handle_retry(request_object.config, SERVER_ERROR_MESSAGE, retry_count)
71
71
 
72
72
  Diffend::HandleErrors::Report.call(
73
73
  exception: e,
@@ -78,7 +78,7 @@ module Diffend
78
78
  rescue *CONNECTION_EXCEPTIONS => e
79
79
  retry_count += 1
80
80
 
81
- retry if handle_retry(CONNECTION_MESSAGE, retry_count)
81
+ retry if handle_retry(request_object.config, CONNECTION_MESSAGE, retry_count)
82
82
 
83
83
  Diffend::HandleErrors::Report.call(
84
84
  exception: e,
@@ -89,7 +89,7 @@ module Diffend
89
89
  rescue *TIMEOUT_EXCEPTIONS => e
90
90
  retry_count += 1
91
91
 
92
- retry if handle_retry(TIMEOUT_MESSAGE, retry_count)
92
+ retry if handle_retry(request_object.config, TIMEOUT_MESSAGE, retry_count)
93
93
 
94
94
  Diffend::HandleErrors::Report.call(
95
95
  exception: e,
@@ -101,12 +101,13 @@ module Diffend
101
101
 
102
102
  # Handle retry
103
103
  #
104
+ # @param config [Diffend::Config]
104
105
  # @param message [String] message we want to display
105
106
  # @param retry_count [Integer]
106
- def handle_retry(message, retry_count)
107
+ def handle_retry(config, message, retry_count)
107
108
  return false if retry_count == RETRIES
108
109
 
109
- Bundler.ui.error(message)
110
+ config.logger.warn(message)
110
111
  sleep(exponential_backoff(retry_count))
111
112
 
112
113
  retry_count < RETRIES
@@ -123,8 +124,8 @@ module Diffend
123
124
  uri.port,
124
125
  use_ssl: uri.scheme == 'https',
125
126
  verify_mode: OpenSSL::SSL::VERIFY_NONE,
126
- open_timeout: 5,
127
- read_timeout: 5
127
+ open_timeout: 15,
128
+ read_timeout: 15
128
129
  ) { |http| yield(http, uri) }
129
130
  end
130
131
 
@@ -132,7 +133,7 @@ module Diffend
132
133
  #
133
134
  # @param uri [URI::HTTPS]
134
135
  # @param request_method [Symbol]
135
- # @param config [OpenStruct] Diffend config
136
+ # @param config [Diffend::Config]
136
137
  # @param payload [Hash] with versions to check
137
138
  #
138
139
  # @return [Net::HTTP::Post, Net::HTTP::Put]
@@ -160,9 +161,8 @@ module Diffend
160
161
  # Assigns basic authorization if provided in the config
161
162
  #
162
163
  # @param request [Net::HTTP::Post] prepared http post
163
- # @param config [OpenStruct] Diffend config
164
+ # @param config [Diffend::Config]
164
165
  def assign_auth(request, config)
165
- return unless config
166
166
  return unless config.shareable_id
167
167
  return unless config.shareable_key
168
168
 
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Diffend
6
+ # Module responsible for fetching diffend verdict on local context
7
+ module RequestVerdict
8
+ class << self
9
+ # @param config [Diffend::Config]
10
+ # @param definition [Bundler::Definition] definition for your source
11
+ def call(config, definition)
12
+ payload = Diffend::LocalContext.call(config, definition)
13
+
14
+ response = Diffend::Request.call(
15
+ build_request_object(config, payload)
16
+ )
17
+
18
+ JSON.parse(response.body)
19
+ rescue Bundler::GemNotFound, Bundler::VersionConflict
20
+ raise ::Diffend::Errors::DependenciesResolveException
21
+ rescue StandardError => e
22
+ Diffend::HandleErrors::Report.call(
23
+ exception: e,
24
+ payload: payload || {},
25
+ config: config,
26
+ message: :unhandled_exception,
27
+ report: true
28
+ )
29
+ end
30
+
31
+ # @param config [Diffend::Config]
32
+ # @param payload [Hash]
33
+ #
34
+ # @return [Diffend::RequestObject]
35
+ def build_request_object(config, payload)
36
+ Diffend::RequestObject.new(
37
+ config: config,
38
+ url: config.commands_url,
39
+ payload: payload,
40
+ request_method: :post
41
+ )
42
+ end
43
+ end
44
+ end
45
+ end
@@ -9,14 +9,16 @@ module Diffend
9
9
  RETRY_SLEEP = 15
10
10
 
11
11
  # Initialize tracking
12
- def initialize
12
+ #
13
+ # @param config [Diffend::Config]
14
+ def initialize(config)
13
15
  @mutex = Mutex.new
14
- @config = fetch_config
16
+ @config = config
15
17
  end
16
18
 
17
19
  # Start tracking
18
20
  def start
19
- response = exec_request
21
+ response = Diffend::Execute.call(@config)
20
22
 
21
23
  perform(response['id'])
22
24
  rescue Diffend::Errors::HandledException
@@ -40,27 +42,12 @@ module Diffend
40
42
  # @param request_id [String]
41
43
  def perform(request_id)
42
44
  loop do
43
- @mutex.synchronize do
44
- track_request(request_id)
45
- end
45
+ @mutex.synchronize { track_request(request_id) }
46
46
 
47
47
  sleep(TRACK_SLEEP)
48
48
  end
49
49
  end
50
50
 
51
- # Perform an exec request
52
- def exec_request
53
- Diffend::Voting.call(
54
- Diffend::Commands::EXEC,
55
- @config,
56
- Diffend::BuildBundlerDefinition.call(
57
- Diffend::Commands::EXEC,
58
- Bundler.default_gemfile,
59
- Bundler.default_lockfile
60
- )
61
- )
62
- end
63
-
64
51
  # Perform a track request
65
52
  #
66
53
  # @param request_id [String]
@@ -76,29 +63,10 @@ module Diffend
76
63
  def build_request_object(request_id)
77
64
  Diffend::RequestObject.new(
78
65
  config: @config,
79
- url: track_url(@config.project_id, request_id),
66
+ url: @config.track_url(request_id),
80
67
  payload: { id: request_id }.freeze,
81
68
  request_method: :put
82
69
  ).freeze
83
70
  end
84
-
85
- # Fetch diffend config file
86
- #
87
- # @return [OpenStruct, nil] configuration object
88
- #
89
- # @raise [Errors::MissingConfigurationFile] when no config file
90
- def fetch_config
91
- Config::Fetcher.call(
92
- File.expand_path('..', Bundler.bin_path)
93
- )
94
- end
95
-
96
- # @param project_id [String] diffend project_id
97
- # @param request_id [String]
98
- #
99
- # @return [String]
100
- def track_url(project_id, request_id)
101
- "https://my.diffend.io/api/projects/#{project_id}/bundle/#{request_id}/track"
102
- end
103
71
  end
104
72
  end