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 +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
|