diffend 0.2.19 → 0.2.23

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f18edf14b16e7f2ec3ce0c574ade976e78e3eac84f8395e45fc53595a8e3f91
4
- data.tar.gz: 292e755dac0d191787b77fb8556b5e2f90f9e040ee9e28486de90601b2c2a67c
3
+ metadata.gz: 5ce266f8f72de49360adc1e6e1f79c8bf5fa08727ffc990292877c015e1040ee
4
+ data.tar.gz: 1a71a4a519b1f2afb9bc993726c045b4db5b87833459ba8f7192c2a2f4232aa6
5
5
  SHA512:
6
- metadata.gz: 73326da64425debc8c27ad1dd216df34313a45795a2c6f555d0e5df067dfc17977ae9ee6e8307ab1df33af58a87ca23511ed3920eaa9c0bcec566fef602c30c3
7
- data.tar.gz: eabf666e6c1ef7a08afaadf519011edac2416f0a2fa13152a9112b898b94dde1f598f23866a9823220be308aa091d9dab6b6d03e95191f3d22ba43509d3933fa
6
+ metadata.gz: '08dd6da1d3984200d9ac07fd9fd1f9a0adf6b7746f86a77ab560b77b356dc6fad819513adea6fe2d714b1f06ed8cf5441d796681fd507b64247a2db3560d3138'
7
+ data.tar.gz: 2155bbba6da089606b38d36fcec4259054f6cac053bf56eefb303d6d3aa223ba4253ca771249a2543696c636e8c509aa75ceb3ab50f055dd18a2ba9715e5cb9f
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -9,6 +9,9 @@ jobs:
9
9
  matrix:
10
10
  ruby:
11
11
  - '2.7'
12
+ - '2.6'
13
+ - '2.5'
14
+ - 'jruby'
12
15
  include:
13
16
  - ruby: '2.7'
14
17
  coverage: 'true'
data/CHANGELOG.md CHANGED
@@ -1,6 +1,22 @@
1
1
  # Changelog
2
2
 
3
3
  ## [Unreleased][master]
4
+ - fix how we build gem platform ([#26](https://github.com/diffend-io/diffend-ruby/pull/26))
5
+ - test against jruby, ruby-2.5 and ruby-2.6 ([#25](https://github.com/diffend-io/diffend-ruby/pull/25))
6
+
7
+ ## [0.2.22] (2020-09-03)
8
+ - fix how we build host command
9
+
10
+ ## [0.2.21] (2020-09-03)
11
+ - bring back support for ruby 2.5.x
12
+
13
+ ## [0.2.20] (2020-09-03)
14
+ - expose host command ([#21](https://github.com/diffend-io/diffend-ruby/pull/21))
15
+ - expose host pid ([#20](https://github.com/diffend-io/diffend-ruby/pull/20))
16
+ - use `Bundler.feature_flag.default_cli_command` which is used as the default task if no command provided, instead of `Diffend::Commands::INSTALL` ([#19](https://github.com/diffend-io/diffend-ruby/pull/19))
17
+ - better error handling ([#18](https://github.com/diffend-io/diffend-ruby/pull/18))
18
+ - better detection of gem versions ([#17](https://github.com/diffend-io/diffend-ruby/pull/17))
19
+ - introduce `Diffend::BuildBundlerDefinition` ([#16](https://github.com/diffend-io/diffend-ruby/pull/16))
4
20
 
5
21
  ## [0.2.19] (2020-08-18)
6
22
 
@@ -22,7 +38,10 @@
22
38
 
23
39
  - initial release
24
40
 
25
- [master]: https://github.com/diffend-io/diffend-ruby/compare/v0.2.19...HEAD
41
+ [master]: https://github.com/diffend-io/diffend-ruby/compare/v0.2.22...HEAD
42
+ [0.2.22]: https://github.com/diffend-io/diffend-ruby/compare/v0.2.21...v0.2.22
43
+ [0.2.21]: https://github.com/diffend-io/diffend-ruby/compare/v0.2.20...v0.2.21
44
+ [0.2.20]: https://github.com/diffend-io/diffend-ruby/compare/v0.2.19...v0.2.20
26
45
  [0.2.19]: https://github.com/diffend-io/diffend-ruby/compare/v0.2.18...v0.2.19
27
46
  [0.2.18]: https://github.com/diffend-io/diffend-ruby/compare/v0.2.17...v0.2.18
28
47
  [0.2.17]: https://github.com/diffend-io/diffend-ruby/compare/v0.2.16...v0.2.17
data/Gemfile CHANGED
@@ -7,6 +7,7 @@ plugin 'diffend'
7
7
  gemspec
8
8
 
9
9
  group :development, :test do
10
- gem 'byebug'
10
+ gem 'byebug', platform: :ruby
11
+ gem 'pry', platform: :jruby
11
12
  gem 'rspec'
12
13
  end
data/Gemfile.lock CHANGED
@@ -1,13 +1,20 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- diffend (0.2.19)
4
+ diffend (0.2.23)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  byebug (11.1.3)
10
+ coderay (1.1.3)
10
11
  diff-lcs (1.4.4)
12
+ ffi (1.13.1-java)
13
+ method_source (1.0.0)
14
+ pry (0.13.1-java)
15
+ coderay (~> 1.1)
16
+ method_source (~> 1.0)
17
+ spoon (~> 0.0)
11
18
  rake (13.0.1)
12
19
  rspec (3.9.0)
13
20
  rspec-core (~> 3.9.0)
@@ -22,14 +29,18 @@ GEM
22
29
  diff-lcs (>= 1.2.0, < 2.0)
23
30
  rspec-support (~> 3.9.0)
24
31
  rspec-support (3.9.3)
32
+ spoon (0.0.6)
33
+ ffi
25
34
 
26
35
  PLATFORMS
36
+ java
27
37
  ruby
28
38
 
29
39
  DEPENDENCIES
30
40
  bundler
31
41
  byebug
32
42
  diffend!
43
+ pry
33
44
  rake
34
45
  rspec
35
46
 
data/lib/diffend.rb CHANGED
@@ -5,16 +5,21 @@
5
5
  ].each(&method(:require))
6
6
 
7
7
  %w[
8
+ build_bundler_definition
8
9
  errors
9
10
  config/fetcher
10
11
  config/file_finder
11
12
  config/validator
12
13
  commands
14
+ handle_errors/messages
15
+ handle_errors/build_exception_payload
16
+ handle_errors/display_to_stdout
17
+ handle_errors/report
18
+ request
13
19
  voting
14
20
  ].each { |file| require "diffend/#{file}" }
15
21
 
16
22
  %w[
17
- request
18
23
  versions/local
19
24
  versions/remote
20
25
  ].each { |file| require "diffend/voting/#{file}" }
@@ -22,7 +27,7 @@
22
27
  # Diffend main namespace
23
28
  module Diffend
24
29
  # Current plugin version
25
- VERSION = '0.2.19'
30
+ VERSION = '0.2.23'
26
31
  # Diffend homepage
27
32
  HOMEPAGE = 'https://diffend.io'
28
33
 
@@ -30,27 +35,28 @@ module Diffend
30
35
  # Registers the plugin and add before install all hook
31
36
  def register
32
37
  Bundler::Plugin.add_hook('before-install-all') do |_|
33
- Diffend::Voting.call(
34
- command,
35
- build_definition(command)
36
- )
38
+ execute
37
39
  end
38
40
  end
39
41
 
40
- # Build clean instance of bundler definition, as we don't want to pollute the main one
41
- #
42
- # @param command [String] bundler command that we are executing
43
- #
44
- # @return [Bundler::Definition]
45
- def build_definition(command)
46
- unlock = command == 'update' ? true : nil
42
+ # Execute diffend plugin
43
+ def execute
44
+ config = fetch_config
47
45
 
48
- Bundler.configure
49
-
50
- Bundler::Definition.build(
51
- Bundler.default_gemfile,
52
- Bundler.default_lockfile,
53
- unlock
46
+ Diffend::Voting.call(
47
+ command,
48
+ Diffend::BuildBundlerDefinition.call(
49
+ command,
50
+ Bundler.default_gemfile,
51
+ Bundler.default_lockfile
52
+ )
53
+ )
54
+ rescue StandardError => e
55
+ Diffend::HandleErrors::Report.call(
56
+ exception: e,
57
+ config: config,
58
+ message: :unhandled_exception,
59
+ report: true
54
60
  )
55
61
  end
56
62
 
@@ -58,7 +64,18 @@ module Diffend
58
64
  #
59
65
  # @return [String]
60
66
  def command
61
- ARGV.first || Diffend::Commands::INSTALL
67
+ ARGV.first || Bundler.feature_flag.default_cli_command.to_s
68
+ end
69
+
70
+ # Fetch diffend config file
71
+ #
72
+ # @return [OpenStruct, nil] configuration object
73
+ #
74
+ # @raise [Errors::MissingConfigurationFile] when no config file
75
+ def fetch_config
76
+ Config::Fetcher.call(
77
+ File.expand_path('..', Bundler.bin_path)
78
+ )
62
79
  end
63
80
  end
64
81
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diffend
4
+ # Builds bundler definition used within the plugin
5
+ module BuildBundlerDefinition
6
+ class << self
7
+ # Build clean instance of bundler definition, as we don't want to pollute the main one
8
+ #
9
+ # @param command [String] bundler command that we are executing
10
+ # @param gemfile [String] path to Gemfile
11
+ # @param lockfile [String] path to Gemfile.lock
12
+ #
13
+ # @return [Bundler::Definition]
14
+ def call(command, gemfile, lockfile)
15
+ unlock = command == 'update' ? true : nil
16
+
17
+ Bundler.configure
18
+ Bundler::Fetcher.disable_endpoint = nil
19
+
20
+ Bundler::Definition
21
+ .build(gemfile, lockfile, unlock)
22
+ .tap(&:validate_runtime!)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Diffend
6
+ module HandleErrors
7
+ # Module responsible for building exception payload
8
+ module BuildExceptionPayload
9
+ class << self
10
+ # Build exception payload
11
+ #
12
+ # @param exception [Exception] expection that was raised
13
+ # @param payload [Hash] with versions to check
14
+ #
15
+ # @return [Hash]
16
+ def call(exception, payload)
17
+ {
18
+ request_id: SecureRandom.uuid,
19
+ payload: payload,
20
+ exception: {
21
+ class: exception.class,
22
+ message: exception.message,
23
+ backtrace: exception.backtrace
24
+ }
25
+ }.freeze
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diffend
4
+ module HandleErrors
5
+ # Module responsible for displaying exception payload to stdout
6
+ module DisplayToStdout
7
+ class << self
8
+ # Display exception payload to stdout
9
+ #
10
+ # @param exception_payload [Hash]
11
+ def call(exception_payload)
12
+ puts exception_payload.to_json
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diffend
4
+ module HandleErrors
5
+ module Messages
6
+ PAYLOAD_DUMP = '^^^ Above is the dump of your request ^^^'
7
+ UNHANDLED_EXCEPTION = <<~MSG
8
+ \nSomething went really wrong. We recorded this incident in our system and will review it.\n
9
+ This is a bug, don't hesitate.\n
10
+ Create an issue at https://github.com/diffend-io/diffend-ruby/issues\n
11
+ MSG
12
+ REQUEST_ERROR = <<~MSG
13
+ \nWe were unable to process your request at this time. We recorded this incident in our system and will review it.\n
14
+ If you think that this is a bug, don't hesitate.\n
15
+ Create an issue at https://github.com/diffend-io/diffend-ruby/issues\n
16
+ MSG
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diffend
4
+ module HandleErrors
5
+ # Module responsible for reporting errors to diffend
6
+ module Report
7
+ class << self
8
+ # Execute request to Diffend
9
+ #
10
+ # @param exception [Exception] expection that was raised
11
+ # @param payload [Hash] with versions to check
12
+ # @param config [OpenStruct] Diffend config
13
+ # @param message [Symbol] message that we want to display
14
+ # @param report [Boolean] if true we will report the issue to diffend
15
+ #
16
+ # @return [Net::HTTPResponse] response from Diffend
17
+ def call(exception:, payload: {}, config:, message:, report: false)
18
+ exception_payload = prepare_exception_payload(exception, payload)
19
+
20
+ Bundler.ui.error(Diffend::HandleErrors::Messages::PAYLOAD_DUMP)
21
+ Bundler.ui.error(Diffend::HandleErrors::Messages.const_get(message.to_s.upcase))
22
+
23
+ if report
24
+ Diffend::Request.call(
25
+ config,
26
+ errors_url(config.project_id),
27
+ exception_payload
28
+ )
29
+ end
30
+
31
+ exit 1
32
+ end
33
+
34
+ # Prepare exception payload and display it to stdout
35
+ #
36
+ # @param exception [Exception] expection that was raised
37
+ # @param payload [Hash] with versions to check
38
+ #
39
+ # @return [Hash]
40
+ def prepare_exception_payload(exception, payload)
41
+ Diffend::HandleErrors::BuildExceptionPayload
42
+ .call(exception, payload)
43
+ .tap(&Diffend::HandleErrors::DisplayToStdout.method(:call))
44
+ end
45
+
46
+ # Provides diffend errors endpoint url
47
+ #
48
+ # @param project_id [String] diffend project_id
49
+ #
50
+ # @return [String] diffend endpoint
51
+ def errors_url(project_id)
52
+ return ENV['DIFFEND_ERROR_URL'] if ENV.key?('DIFFEND_ERROR_URL')
53
+
54
+ "https://my.diffend.io/api/projects/#{project_id}/errors"
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'openssl'
5
+ require 'json'
6
+
7
+ module Diffend
8
+ # Module responsible for doing request to Diffend
9
+ module Request
10
+ # Message displayed when connection issue occured and we will retry
11
+ CONNECTION_MESSAGE = 'We experienced a connection issue, retrying...'
12
+ # List of connection exceptions
13
+ CONNECTION_EXCEPTIONS = [
14
+ Errno::ECONNRESET,
15
+ Errno::ENETUNREACH,
16
+ Errno::EHOSTUNREACH,
17
+ Errno::ECONNREFUSED
18
+ ].freeze
19
+ # Message displayed when timeout occured and we will retry
20
+ TIMEOUT_MESSAGE = 'We experienced a connection issue, retrying...'
21
+ # List of timeout exceptions
22
+ TIMEOUT_EXCEPTIONS = [
23
+ Net::OpenTimeout,
24
+ Net::ReadTimeout
25
+ ].freeze
26
+ # Number of retries
27
+ RETRIES = 3
28
+ # Request headers
29
+ HEADERS = { 'Content-Type': 'application/json' }.freeze
30
+
31
+ private_constant :HEADERS
32
+
33
+ class << self
34
+ # Execute request
35
+ #
36
+ # @param config [OpenStruct] diffend config
37
+ # @param endpoint_url [String]
38
+ # @param payload [Hash]
39
+ #
40
+ # @return [Net::HTTPResponse] response from Diffend
41
+ def call(config, endpoint_url, payload)
42
+ retry_count ||= -1
43
+
44
+ build_http(endpoint_url) do |http, uri|
45
+ http.request(build_request(uri, config, payload))
46
+ end
47
+ rescue *CONNECTION_EXCEPTIONS => e
48
+ retry_count += 1
49
+
50
+ retry if handle_retry(CONNECTION_MESSAGE, retry_count)
51
+
52
+ Diffend::HandleErrors::Report.call(
53
+ exception: e,
54
+ payload: payload,
55
+ config: config,
56
+ message: :request_error
57
+ )
58
+ rescue *TIMEOUT_EXCEPTIONS => e
59
+ retry_count += 1
60
+
61
+ retry if handle_retry(TIMEOUT_MESSAGE, retry_count)
62
+
63
+ Diffend::HandleErrors::Report.call(
64
+ exception: e,
65
+ payload: payload,
66
+ config: config,
67
+ message: :request_error
68
+ )
69
+ end
70
+
71
+ # Handle retry
72
+ #
73
+ # @param message [String] message we want to display
74
+ # @param retry_count [Integer]
75
+ def handle_retry(message, retry_count)
76
+ return false if retry_count == RETRIES
77
+
78
+ Bundler.ui.error(message)
79
+ sleep(exponential_backoff(retry_count))
80
+
81
+ retry_count < RETRIES
82
+ end
83
+
84
+ # Builds http connection object
85
+ #
86
+ # @param url [String] command endpoint url
87
+ def build_http(url)
88
+ uri = URI(url)
89
+
90
+ Net::HTTP.start(
91
+ uri.host,
92
+ uri.port,
93
+ use_ssl: uri.scheme == 'https',
94
+ verify_mode: OpenSSL::SSL::VERIFY_NONE,
95
+ open_timeout: 5,
96
+ read_timeout: 5
97
+ ) { |http| yield(http, uri) }
98
+ end
99
+
100
+ # Build http post request and assigns headers and payload
101
+ #
102
+ # @param uri [URI::HTTPS]
103
+ # @param config [OpenStruct] Diffend config
104
+ # @param payload [Hash] with versions to check
105
+ #
106
+ # @return [Net::HTTP::Post]
107
+ def build_request(uri, config, payload)
108
+ Net::HTTP::Post
109
+ .new(uri.request_uri, HEADERS)
110
+ .tap { |request| assign_auth(request, config) }
111
+ .tap { |request| assign_payload(request, payload) }
112
+ end
113
+
114
+ # Assigns basic authorization if provided in the config
115
+ #
116
+ # @param request [Net::HTTP::Post] prepared http post
117
+ # @param config [OpenStruct] Diffend config
118
+ def assign_auth(request, config)
119
+ return unless config
120
+ return unless config.shareable_id
121
+ return unless config.shareable_key
122
+
123
+ request.basic_auth(config.shareable_id, config.shareable_key)
124
+ end
125
+
126
+ # Assigns payload as json
127
+ #
128
+ # @param request [Net::HTTP::Post] prepared http post
129
+ # @param payload [Hash] with versions to check
130
+ def assign_payload(request, payload)
131
+ request.body = JSON.dump(payload: payload)
132
+ end
133
+
134
+ def exponential_backoff(retry_count)
135
+ 2**(retry_count + 1)
136
+ end
137
+ end
138
+ end
139
+ end
@@ -65,18 +65,16 @@ module Diffend
65
65
  def build_install
66
66
  hash = build_main
67
67
 
68
- @definition.requested_specs.each do |spec|
68
+ @definition.specs.each do |spec|
69
69
  next if skip?(spec.source)
70
70
 
71
71
  locked_spec = @locked_specs.find { |s| s.name == spec.name }
72
72
 
73
- spec2 = locked_spec || spec
74
-
75
- hash['dependencies'][spec2.name] = {
76
- 'platform' => build_spec_platform(spec2),
77
- 'source' => build_spec_source(spec2),
78
- 'type' => build_dependency_type(spec2.name),
79
- 'versions' => build_versions(spec2)
73
+ hash['dependencies'][spec.name] = {
74
+ 'platform' => build_spec_platform(spec, locked_spec),
75
+ 'source' => build_spec_source(spec),
76
+ 'type' => build_dependency_type(spec.name),
77
+ 'versions' => build_versions(spec, locked_spec)
80
78
  }
81
79
  end
82
80
 
@@ -89,13 +87,13 @@ module Diffend
89
87
  def build_update
90
88
  hash = build_main
91
89
 
92
- @definition.requested_specs.each do |spec|
90
+ @definition.specs.each do |spec|
93
91
  next if skip?(spec.source)
94
92
 
95
93
  locked_spec = @locked_specs.find { |s| s.name == spec.name }
96
94
 
97
95
  hash['dependencies'][spec.name] = {
98
- 'platform' => build_spec_platform(spec),
96
+ 'platform' => build_spec_platform(spec, locked_spec),
99
97
  'source' => build_spec_source(spec),
100
98
  'type' => build_dependency_type(spec.name),
101
99
  'versions' => build_versions(spec, locked_spec)
@@ -126,7 +124,11 @@ module Diffend
126
124
  #
127
125
  # @return [Array<String>]
128
126
  def build_versions(spec, locked_spec = nil)
129
- locked_spec ? [locked_spec.version.to_s, spec.version.to_s] : [spec.version.to_s]
127
+ if locked_spec && locked_spec.version.to_s != spec.version.to_s
128
+ [locked_spec.version.to_s, spec.version.to_s]
129
+ else
130
+ [spec.version.to_s]
131
+ end
130
132
  end
131
133
 
132
134
  # @param specs [Array] specs that are direct dependencies
@@ -144,10 +146,25 @@ module Diffend
144
146
  # Build gem platform
145
147
  #
146
148
  # @param spec [Bundler::StubSpecification, Bundler::LazySpecification, Gem::Specification]
149
+ # @param locked_spec [Bundler::LazySpecification, Gem::Specification, NilClass]
147
150
  #
148
151
  # @return [String]
149
- def build_spec_platform(spec)
150
- spec.platform || spec.send(:generic_local_platform)
152
+ def build_spec_platform(spec, locked_spec)
153
+ spec.platform || locked_spec&.platform || build_spec_generic_platform(spec)
154
+ end
155
+
156
+ # Build gem generic platform
157
+ #
158
+ # @param spec [Bundler::StubSpecification, Bundler::LazySpecification, Gem::Specification]
159
+ #
160
+ # @return [String]
161
+ def build_spec_generic_platform(spec)
162
+ platform = spec.send(:generic_local_platform)
163
+
164
+ case platform
165
+ when String then platform
166
+ when Gem::Platform then platform.os
167
+ end
151
168
  end
152
169
 
153
170
  # Build gem source type
@@ -229,17 +246,17 @@ module Diffend
229
246
  # @return [Array<Hash>]
230
247
  def build_sources
231
248
  sources = @definition.send(:sources).rubygems_sources
232
- hash = []
249
+ hash = {}
233
250
 
234
251
  sources.each do |source|
235
252
  type = build_source_type(source.remotes)
236
253
 
237
254
  source.remotes.each do |src|
238
- hash << { 'name' => source_name(src), 'type' => type }
255
+ hash[source_name(src)] = type
239
256
  end
240
257
  end
241
258
 
242
- hash
259
+ hash.map { |name, type| { 'name' => name, 'type' => type } }
243
260
  end
244
261
 
245
262
  # Build gem source type
@@ -23,11 +23,23 @@ module Diffend
23
23
  def call(command, definition)
24
24
  config = fetch_config
25
25
 
26
- response = Request.call(
27
- command, payload(command, config&.project_id, definition), config
26
+ payload = payload(command, config.project_id, definition)
27
+
28
+ response = Diffend::Request.call(
29
+ config,
30
+ commands_url(command, config.project_id),
31
+ payload
28
32
  )
29
33
 
30
34
  JSON.parse(response.body)
35
+ rescue StandardError => e
36
+ Diffend::HandleErrors::Report.call(
37
+ exception: e,
38
+ payload: payload,
39
+ config: config,
40
+ message: :unhandled_exception,
41
+ report: true
42
+ )
31
43
  end
32
44
 
33
45
  # Build diffend, host, packages, and platform specific information
@@ -85,6 +97,9 @@ module Diffend
85
97
  }.freeze
86
98
  end
87
99
 
100
+ # Build platform ruby information
101
+ #
102
+ # @return [Hash]
88
103
  def build_platform_ruby
89
104
  if defined?(JRUBY_VERSION)
90
105
  revision = JRUBY_REVISION.to_s
@@ -117,7 +132,7 @@ module Diffend
117
132
  uname = Etc.uname
118
133
 
119
134
  {
120
- 'command' => { 'name' => '', 'options' => '' },
135
+ 'command' => build_host_command,
121
136
  'ips' => build_host_ips,
122
137
  'name' => uname[:nodename],
123
138
  'system' => {
@@ -127,10 +142,24 @@ module Diffend
127
142
  'version' => uname[:version]
128
143
  },
129
144
  'tags' => build_host_tags,
130
- 'user' => Etc.getpwuid(Process.uid).name
145
+ 'user' => Etc.getpwuid(Process.uid).name,
146
+ 'pid' => Process.pid
131
147
  }.freeze
132
148
  end
133
149
 
150
+ # Build host command information
151
+ #
152
+ # @return [Hash]
153
+ def build_host_command
154
+ {
155
+ 'name' => $PROGRAM_NAME.split('/').last.strip,
156
+ 'options' => ARGV.join(' ')
157
+ }
158
+ end
159
+
160
+ # Build host ips, except localhost and loopback
161
+ #
162
+ # @return [Array<String>]
134
163
  def build_host_ips
135
164
  Socket.ip_address_list.map do |ip|
136
165
  next if ip.ipv4_loopback? || ip.ipv6_loopback? || ip.ipv6_linklocal?
@@ -139,6 +168,9 @@ module Diffend
139
168
  end.compact
140
169
  end
141
170
 
171
+ # Build host tags
172
+ #
173
+ # @return [Array]
142
174
  def build_host_tags
143
175
  tags = []
144
176
 
@@ -155,7 +187,7 @@ module Diffend
155
187
  tags
156
188
  end
157
189
 
158
- # Fetch coditsu config file
190
+ # Fetch diffend config file
159
191
  #
160
192
  # @return [OpenStruct, nil] configuration object
161
193
  #
@@ -165,6 +197,18 @@ module Diffend
165
197
  File.expand_path('..', Bundler.bin_path)
166
198
  )
167
199
  end
200
+
201
+ # Provides diffend command endpoint url
202
+ #
203
+ # @param command [String] either install or update
204
+ # @param project_id [String] diffend project_id
205
+ #
206
+ # @return [String] diffend endpoint
207
+ def commands_url(command, project_id)
208
+ return ENV['DIFFEND_COMMAND_URL'] if ENV.key?('DIFFEND_COMMAND_URL')
209
+
210
+ "https://my.diffend.io/api/projects/#{project_id}/bundle/#{command}"
211
+ end
168
212
  end
169
213
  end
170
214
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: diffend
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.19
4
+ version: 0.2.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomasz Pajor
@@ -34,7 +34,7 @@ cert_chain:
34
34
  9MmF6uCQa1EjK2p8tYT0MnbHrFkoehxdX4VO9y99GAkhZyJNKPYPtyAUFV27sT2V
35
35
  LfCJRk4ifKIN/FUCwDSn8Cz0m6oH265q0p6wdzI6qrWOjP8tGOMBTA==
36
36
  -----END CERTIFICATE-----
37
- date: 2020-08-18 00:00:00.000000000 Z
37
+ date: 2020-09-06 00:00:00.000000000 Z
38
38
  dependencies:
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: bundler
@@ -92,13 +92,18 @@ files:
92
92
  - certs/tomaszpajor.pem
93
93
  - diffend.gemspec
94
94
  - lib/diffend.rb
95
+ - lib/diffend/build_bundler_definition.rb
95
96
  - lib/diffend/commands.rb
96
97
  - lib/diffend/config/fetcher.rb
97
98
  - lib/diffend/config/file_finder.rb
98
99
  - lib/diffend/config/validator.rb
99
100
  - lib/diffend/errors.rb
101
+ - lib/diffend/handle_errors/build_exception_payload.rb
102
+ - lib/diffend/handle_errors/display_to_stdout.rb
103
+ - lib/diffend/handle_errors/messages.rb
104
+ - lib/diffend/handle_errors/report.rb
105
+ - lib/diffend/request.rb
100
106
  - lib/diffend/voting.rb
101
- - lib/diffend/voting/request.rb
102
107
  - lib/diffend/voting/versions/local.rb
103
108
  - lib/diffend/voting/versions/remote.rb
104
109
  - plugins.rb
metadata.gz.sig CHANGED
Binary file
@@ -1,191 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'net/http'
4
- require 'openssl'
5
- require 'json'
6
- require 'securerandom'
7
-
8
- module Diffend
9
- module Voting
10
- # Module responsible for doing request to Diffend
11
- module Request
12
- # List of connection exceptions
13
- CONNECTION_EXCEPTIONS = [
14
- Errno::ECONNRESET,
15
- Errno::ENETUNREACH,
16
- Errno::EHOSTUNREACH,
17
- Errno::ECONNREFUSED
18
- ].freeze
19
- # List of timeout exceptions
20
- TIMEOUT_EXCEPTIONS = [
21
- Net::OpenTimeout,
22
- Net::ReadTimeout
23
- ].freeze
24
- # Request headers
25
- HEADERS = { 'Content-Type': 'application/json' }.freeze
26
-
27
- private_constant :HEADERS
28
-
29
- class << self
30
- # Execute request to Diffend
31
- #
32
- # @param command [String] either install or update
33
- # @param payload [Hash] with versions to check
34
- # @param config [OpenStruct] Diffend config
35
- #
36
- # @return [Net::HTTPResponse] response from Diffend
37
- def call(command, payload, config)
38
- retry_count ||= 0
39
-
40
- build_http(commands_url(command, config.project_id)) do |http, uri|
41
- http.request(build_request(uri, config, payload))
42
- end
43
- rescue *CONNECTION_EXCEPTIONS => e
44
- Bundler.ui.error('We experienced a connection issue, retrying...')
45
- sleep(exponential_backoff(retry_count))
46
- retry_count += 1
47
-
48
- retry if retry_count < 3
49
-
50
- output_report(build_report(payload, e))
51
- Bundler.ui.error('^^^ Above is the dump of your request ^^^')
52
- Bundler.ui.error(build_request_error_message)
53
-
54
- exit 1
55
- rescue *TIMEOUT_EXCEPTIONS => e
56
- Bundler.ui.error('We experienced a timeout issue, retrying...')
57
- sleep(exponential_backoff(retry_count))
58
- retry_count += 1
59
-
60
- retry if retry_count < 3
61
-
62
- output_report(build_report(payload, e))
63
- Bundler.ui.error('^^^ Above is the dump of your request ^^^')
64
- Bundler.ui.error(build_request_error_message)
65
-
66
- exit 1
67
- rescue StandardError => e
68
- exception_payload = build_report(payload, e)
69
- output_report(exception_payload)
70
- Bundler.ui.error('^^^ Above is the dump of your request ^^^')
71
- Bundler.ui.error(build_unhandled_exception_message)
72
-
73
- build_http(errors_url(config.project_id)) do |http, uri|
74
- http.request(build_request(uri, config, exception_payload))
75
- end
76
-
77
- exit 1
78
- end
79
-
80
- # Builds http connection object
81
- #
82
- # @param url [String] command endpoint url
83
- def build_http(url)
84
- uri = URI(url)
85
-
86
- Net::HTTP.start(
87
- uri.host,
88
- uri.port,
89
- use_ssl: uri.scheme == 'https',
90
- verify_mode: OpenSSL::SSL::VERIFY_NONE,
91
- open_timeout: 5,
92
- read_timeout: 5
93
- ) { |http| yield(http, uri) }
94
- end
95
-
96
- # Build http post request and assigns headers and payload
97
- #
98
- # @param uri [URI::HTTPS]
99
- # @param config [OpenStruct] Diffend config
100
- # @param payload [Hash] with versions to check
101
- #
102
- # @return [Net::HTTP::Post]
103
- def build_request(uri, config, payload)
104
- Net::HTTP::Post
105
- .new(uri.request_uri, HEADERS)
106
- .tap { |request| assign_auth(request, config) }
107
- .tap { |request| assign_payload(request, payload) }
108
- end
109
-
110
- # Assigns basic authorization if provided in the config
111
- #
112
- # @param request [Net::HTTP::Post] prepared http post
113
- # @param config [OpenStruct] Diffend config
114
- def assign_auth(request, config)
115
- return unless config
116
- return unless config.shareable_id
117
- return unless config.shareable_key
118
-
119
- request.basic_auth(config.shareable_id, config.shareable_key)
120
- end
121
-
122
- # Assigns payload as json
123
- #
124
- # @param request [Net::HTTP::Post] prepared http post
125
- # @param payload [Hash] with versions to check
126
- def assign_payload(request, payload)
127
- request.body = JSON.dump(payload: payload)
128
- end
129
-
130
- # Provides diffend command endpoint url
131
- #
132
- # @param command [String] either install or update
133
- # @param project_id [String] diffend project_id
134
- #
135
- # @return [String] diffend endpoint
136
- def commands_url(command, project_id)
137
- return ENV['DIFFEND_COMMAND_URL'] if ENV.key?('DIFFEND_COMMAND_URL')
138
-
139
- "https://my.diffend.io/api/projects/#{project_id}/bundle/#{command}"
140
- end
141
-
142
- # Provides diffend errors endpoint url
143
- #
144
- # @param project_id [String] diffend project_id
145
- #
146
- # @return [String] diffend endpoint
147
- def errors_url(project_id)
148
- return ENV['DIFFEND_ERROR_URL'] if ENV.key?('DIFFEND_ERROR_URL')
149
-
150
- "https://my.diffend.io/api/projects/#{project_id}/errors"
151
- end
152
-
153
- def exponential_backoff(retry_count)
154
- 2**(retry_count + 1)
155
- end
156
-
157
- def build_request_error_message
158
- <<~MSG
159
- \nWe were unable to process your request at this time. We recorded this incident in our system and will review it.\n
160
- If you think that this is a bug, don't hesitate.\n
161
- Create an issue on https://github.com/diffend-io/diffend-ruby/issues\n
162
- MSG
163
- end
164
-
165
- def build_unhandled_exception_message
166
- <<~MSG
167
- \nSomething went really wrong. We recorded this incident in our system and will review it.\n
168
- This is a bug, don't hesitate.\n
169
- Create an issue on https://github.com/diffend-io/diffend-ruby/issues\n
170
- MSG
171
- end
172
-
173
- def build_report(payload, exception)
174
- {
175
- request_id: SecureRandom.uuid,
176
- payload: payload,
177
- exception: {
178
- class: exception.class,
179
- message: exception.message,
180
- backtrace: exception.backtrace
181
- }
182
- }
183
- end
184
-
185
- def output_report(report)
186
- puts report.to_json
187
- end
188
- end
189
- end
190
- end
191
- end