diffend 0.2.19 → 0.2.23
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.github/workflows/ci.yml +3 -0
- data/CHANGELOG.md +20 -1
- data/Gemfile +2 -1
- data/Gemfile.lock +12 -1
- data/lib/diffend.rb +37 -20
- data/lib/diffend/build_bundler_definition.rb +26 -0
- data/lib/diffend/handle_errors/build_exception_payload.rb +30 -0
- data/lib/diffend/handle_errors/display_to_stdout.rb +17 -0
- data/lib/diffend/handle_errors/messages.rb +19 -0
- data/lib/diffend/handle_errors/report.rb +59 -0
- data/lib/diffend/request.rb +139 -0
- data/lib/diffend/voting/versions/local.rb +33 -16
- data/lib/diffend/voting/versions/remote.rb +49 -5
- metadata +8 -3
- metadata.gz.sig +0 -0
- data/lib/diffend/voting/request.rb +0 -191
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ce266f8f72de49360adc1e6e1f79c8bf5fa08727ffc990292877c015e1040ee
|
4
|
+
data.tar.gz: 1a71a4a519b1f2afb9bc993726c045b4db5b87833459ba8f7192c2a2f4232aa6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08dd6da1d3984200d9ac07fd9fd1f9a0adf6b7746f86a77ab560b77b356dc6fad819513adea6fe2d714b1f06ed8cf5441d796681fd507b64247a2db3560d3138'
|
7
|
+
data.tar.gz: 2155bbba6da089606b38d36fcec4259054f6cac053bf56eefb303d6d3aa223ba4253ca771249a2543696c636e8c509aa75ceb3ab50f055dd18a2ba9715e5cb9f
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/.github/workflows/ci.yml
CHANGED
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.
|
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
data/Gemfile.lock
CHANGED
@@ -1,13 +1,20 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
diffend (0.2.
|
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.
|
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
|
-
|
34
|
-
command,
|
35
|
-
build_definition(command)
|
36
|
-
)
|
38
|
+
execute
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
40
|
-
#
|
41
|
-
|
42
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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 ||
|
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.
|
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
|
-
|
74
|
-
|
75
|
-
|
76
|
-
'
|
77
|
-
'
|
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.
|
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
|
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
|
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
|
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
|
-
|
27
|
-
|
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' =>
|
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
|
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.
|
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-
|
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
|