diffend 0.2.29 → 0.2.34

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.
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Diffend
4
- module Config
5
- # Class used to figure out the file from which we should load the settings
6
- module FileFinder
7
- # Names of the files or paths where we will look for the settings
8
- #
9
- # @note We do the double dot trick, to look outside of the current dir because when
10
- # executed from a docker container, we copy the local uncommitted settings into the
11
- # dir above the app location not to pollute the reset state of the git repo
12
- #
13
- # @note Order is important, as for local env we should load from
14
- # local file (if present first)
15
- FILE_NAMES = %w[
16
- .diffend.yml
17
- ].map { |name| ["../#{name}", name] }.tap(&:flatten!).freeze
18
-
19
- private_constant :FILE_NAMES
20
-
21
- class << self
22
- # Looks for Diffend settings file for a given env
23
- #
24
- # @param build_path [String] path of the current build
25
- #
26
- # @return [String] path to the file from which we should load all the settings
27
- def call(build_path)
28
- FILE_NAMES
29
- .map { |name| File.join(build_path, name) }
30
- .map { |name| Dir[name] }
31
- .find { |selection| !selection.empty? }
32
- .tap { |path| path || raise(Errors::MissingConfigurationFile) }
33
- .first
34
- end
35
- end
36
- end
37
- end
38
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Diffend
4
- # Module for all the components related to setting up the config
5
- module Config
6
- # Class responsible for validating the config from .diffend.yml
7
- module Validator
8
- class << self
9
- # @param config [OpenStruct] path of the current build
10
- def call(config)
11
- raise Errors::ProjectIdMissingInConfigurationFile if missing?(config, 'project_id')
12
- raise Errors::ShareableIdMissingInConfigurationFile if missing?(config, 'shareable_id')
13
- raise Errors::ShareableKeyMissingInConfigurationFile if missing?(config, 'shareable_key')
14
- raise Errors::BuildPathMissingInConfigurationFile if missing?(config, 'build_path')
15
- end
16
-
17
- private
18
-
19
- def missing?(config, key)
20
- config.public_send(key).nil? || config.public_send(key).empty?
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,304 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Diffend
4
- module Voting
5
- # Module responsible for handling both local and remote gem versions
6
- module Versions
7
- # Module responsible for preparing current or current/new versions of gems
8
- class Local
9
- # Definition of a local path, if it matches it means that we are the source
10
- ME_PATH = '.'
11
- # Sources that we expect to match ourselves too
12
- ME_SOURCES = [
13
- Bundler::Source::Gemspec,
14
- Bundler::Source::Path
15
- ].freeze
16
- # List of dependency types
17
- DEPENDENCIES_TYPES = {
18
- direct: 0,
19
- dependency: 1
20
- }.freeze
21
- # List of sources types
22
- SOURCES_TYPES = {
23
- valid: 0,
24
- multiple_primary: 1
25
- }.freeze
26
- # List of gem sources types
27
- GEM_SOURCES_TYPES = {
28
- local: 0,
29
- gemfile_source: 1,
30
- gemfile_git: 2,
31
- gemfile_path: 3
32
- }.freeze
33
-
34
- class << self
35
- # @param command [String] either install or update
36
- # @param definition [Bundler::Definition] definition for your source
37
- def call(command, definition)
38
- Bundler.ui.silence { definition.resolve_remotely! }
39
-
40
- instance = new(definition)
41
-
42
- case command
43
- when Commands::INSTALL, Commands::EXEC then instance.build_install
44
- when Commands::UPDATE then instance.build_update
45
- else
46
- raise ArgumentError, "invalid command: #{command}"
47
- end
48
- end
49
- end
50
-
51
- # @param definition [Bundler::Definition] definition for your source
52
- #
53
- # @return [Hash] local dependencies
54
- def initialize(definition)
55
- @definition = definition
56
- @direct_dependencies = Hash[definition.dependencies.map { |val| [val.name, val] }]
57
- # Support case without Gemfile.lock
58
- @locked_specs = @definition.locked_gems ? @definition.locked_gems.specs : []
59
- end
60
-
61
- # Build install specification
62
- #
63
- # @return [Hash]
64
- def build_install
65
- hash = build_main
66
-
67
- @definition.specs.each do |spec|
68
- next if skip?(spec.source)
69
-
70
- locked_spec = @locked_specs.find { |s| s.name == spec.name }
71
-
72
- hash['dependencies'][spec.name] = {
73
- 'platform' => build_spec_platform(spec, locked_spec),
74
- 'source' => build_spec_source(spec),
75
- 'type' => build_dependency_type(spec.name),
76
- 'versions' => build_versions(spec, locked_spec)
77
- }
78
- end
79
-
80
- hash
81
- end
82
-
83
- # Build update specification
84
- #
85
- # @return [Hash]
86
- def build_update
87
- hash = build_main
88
-
89
- @definition.specs.each do |spec|
90
- next if skip?(spec.source)
91
-
92
- locked_spec = @locked_specs.find { |s| s.name == spec.name }
93
-
94
- hash['dependencies'][spec.name] = {
95
- 'platform' => build_spec_platform(spec, locked_spec),
96
- 'source' => build_spec_source(spec),
97
- 'type' => build_dependency_type(spec.name),
98
- 'versions' => build_versions(spec, locked_spec)
99
- }
100
- end
101
-
102
- hash
103
- end
104
-
105
- private
106
-
107
- # Build default specification
108
- #
109
- # @return [Hash]
110
- def build_main
111
- {
112
- 'dependencies' => {},
113
- 'sources' => build_sources,
114
- 'plugins' => {},
115
- 'platforms' => @definition.platforms.map(&:to_s)
116
- }
117
- end
118
-
119
- # Build gem versions
120
- #
121
- # @param spec [Bundler::StubSpecification, Bundler::LazySpecification, Gem::Specification]
122
- # @param locked_spec [Bundler::LazySpecification, Gem::Specification, NilClass]
123
- #
124
- # @return [Array<String>]
125
- def build_versions(spec, locked_spec = nil)
126
- if locked_spec && locked_spec.version.to_s != spec.version.to_s
127
- [locked_spec.version.to_s, spec.version.to_s]
128
- else
129
- [spec.version.to_s]
130
- end
131
- end
132
-
133
- # @param specs [Array] specs that are direct dependencies
134
- # @param name [String] spec name
135
- #
136
- # @return [Boolean] dependency type
137
- def build_dependency_type(name)
138
- if @direct_dependencies.key?(name)
139
- DEPENDENCIES_TYPES[:direct]
140
- else
141
- DEPENDENCIES_TYPES[:dependency]
142
- end
143
- end
144
-
145
- # Build gem platform
146
- #
147
- # @param spec [Bundler::StubSpecification, Bundler::LazySpecification, Gem::Specification]
148
- # @param locked_spec [Bundler::LazySpecification, Gem::Specification, NilClass]
149
- #
150
- # @return [String]
151
- def build_spec_platform(spec, locked_spec)
152
- parse_platform(
153
- spec.platform || locked_spec&.platform || spec.send(:generic_local_platform)
154
- )
155
- end
156
-
157
- # Parse gem platform
158
- #
159
- # @param platform [String, Gem::Platform]
160
- #
161
- # @return [String]
162
- def parse_platform(platform)
163
- case platform
164
- when String then platform
165
- when Gem::Platform then platform.os
166
- end
167
- end
168
-
169
- # Build gem source type
170
- #
171
- # @param source [Bundler::Source] gem source type
172
- #
173
- # @return [Integer] internal gem source type
174
- def build_spec_gem_source_type(source)
175
- case source
176
- when Bundler::Source::Metadata
177
- GEM_SOURCES_TYPES[:local]
178
- when Bundler::Source::Rubygems, Bundler::Source::Rubygems::Remote
179
- GEM_SOURCES_TYPES[:gemfile_source]
180
- when Bundler::Source::Git
181
- GEM_SOURCES_TYPES[:gemfile_git]
182
- when Bundler::Source::Path
183
- GEM_SOURCES_TYPES[:gemfile_path]
184
- else
185
- raise ArgumentError, "unknown source #{source.class}"
186
- end
187
- end
188
-
189
- # Build gem source
190
- #
191
- # @param spec [Bundler::StubSpecification, Bundler::LazySpecification, Gem::Specification]
192
- #
193
- # @return [Hash]
194
- def build_spec_source(spec)
195
- source = source_for_spec(spec)
196
-
197
- {
198
- 'type' => build_spec_gem_source_type(source),
199
- 'value' => source_name_from_source(source)
200
- }
201
- end
202
-
203
- # Figure out source for gem
204
- #
205
- # @param spec [Bundler::StubSpecification, Bundler::LazySpecification, Gem::Specification]
206
- #
207
- # @return [Bundler::Source] gem source type
208
- def source_for_spec(spec)
209
- return spec.remote if spec.remote
210
-
211
- case spec.source
212
- when Bundler::Source::Rubygems
213
- spec
214
- .source
215
- .send(:remote_specs)
216
- .search(Bundler::Dependency.new(spec.name, spec.version))
217
- .last
218
- .remote
219
- when Bundler::Source::Metadata, Bundler::Source::Git, Bundler::Source::Path
220
- spec.source
221
- else
222
- raise ArgumentError, "unknown source #{spec.source.class}"
223
- end
224
- end
225
-
226
- # Build gem source name
227
- #
228
- # @param source [Bundler::Source] gem source type
229
- #
230
- # @return [String]
231
- def source_name_from_source(source)
232
- case source
233
- when Bundler::Source::Metadata
234
- ''
235
- when Bundler::Source::Rubygems::Remote
236
- source_name(source.anonymized_uri)
237
- when Bundler::Source::Git
238
- source.instance_variable_get(:@safe_uri)
239
- when Bundler::Source::Path
240
- source.path
241
- else
242
- raise ArgumentError, "unknown source #{source.class}"
243
- end
244
- end
245
-
246
- # @param uri [Bundler::URI]
247
- #
248
- # @return [String]
249
- def source_name(uri)
250
- uri.to_s[0...-1]
251
- end
252
-
253
- # Build sources used in the Gemfile
254
- #
255
- # @return [Array<Hash>]
256
- def build_sources
257
- sources = @definition.send(:sources).rubygems_sources
258
- hash = {}
259
-
260
- sources.each do |source|
261
- type = build_source_type(source.remotes)
262
-
263
- source.remotes.each do |src|
264
- hash[source_name(src)] = type
265
- end
266
- end
267
-
268
- hash.map { |name, type| { 'name' => name, 'type' => type } }
269
- end
270
-
271
- # Build gem source type
272
- #
273
- # @param remotes [Array<Bundler::URI>]
274
- #
275
- # @return [Integer] internal source type
276
- def build_source_type(remotes)
277
- remotes.count > 1 ? SOURCES_TYPES[:multiple_primary] : SOURCES_TYPES[:valid]
278
- end
279
-
280
- # Checks if we should skip a source
281
- #
282
- # @param source [Bundler::Source] gem source type
283
- #
284
- # @return [Boolean] true if we should skip this source, false otherwise
285
- def skip?(source)
286
- return true if me?(source)
287
-
288
- false
289
- end
290
-
291
- # Checks if it's a self source, this happens for repositories that are a gem
292
- #
293
- # @param source [Bundler::Source] gem source type
294
- #
295
- # @return [Boolean] true if it's a self source, false otherwise
296
- def me?(source)
297
- return false unless ME_SOURCES.include?(source.class)
298
-
299
- source.path.to_s == ME_PATH
300
- end
301
- end
302
- end
303
- end
304
- end
@@ -1,227 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
- require 'etc'
5
-
6
- module Diffend
7
- module Voting
8
- # Module responsible for handling both local and remote gem versions
9
- module Versions
10
- # Module responsible for fetching safe/malicious votes
11
- # for current or current/new versions of gems
12
- module Remote
13
- # API version
14
- API_VERSION = '0.1'
15
- # Platform type ruby
16
- PLATFORM_TYPE = 0
17
-
18
- private_constant :API_VERSION, :PLATFORM_TYPE
19
-
20
- class << self
21
- # @param command [String] either install or update
22
- # @param definition [Bundler::Definition] definition for your source
23
- # @param config [OpenStruct] diffend config
24
- def call(command, config, definition)
25
- payload = payload(command, config.project_id, definition)
26
-
27
- response = Diffend::Request.call(
28
- build_request_object(command, config, payload)
29
- )
30
-
31
- JSON.parse(response.body)
32
- rescue StandardError => e
33
- Diffend::HandleErrors::Report.call(
34
- exception: e,
35
- payload: payload || {},
36
- config: config,
37
- message: :unhandled_exception,
38
- report: true
39
- )
40
- end
41
-
42
- # @param command [String] either install or update
43
- # @param config [OpenStruct] diffend config
44
- # @param payload [Hash]
45
- #
46
- # @return [Diffend::RequestObject]
47
- def build_request_object(command, config, payload)
48
- Diffend::RequestObject.new(
49
- config: config,
50
- url: commands_url(command, config.project_id),
51
- payload: payload,
52
- request_method: :post
53
- )
54
- end
55
-
56
- # Build diffend, host, packages, and platform specific information
57
- #
58
- # @param command [String] either install or update
59
- # @param project_id [String] diffend project_id
60
- # @param definition [Bundler::Definition] definition for your source
61
- #
62
- # @return [Hash] payload for diffend endpoint
63
- def payload(command, project_id, definition)
64
- {
65
- 'diffend' => build_diffend(project_id),
66
- 'host' => build_host,
67
- 'packages' => Local.call(command, definition),
68
- 'platform' => build_platform
69
- }.freeze
70
- end
71
-
72
- # Build diffend information
73
- #
74
- # @param project_id [String, nil] diffend project_id
75
- #
76
- # @return [Hash]
77
- def build_diffend(project_id)
78
- {
79
- 'api_version' => API_VERSION,
80
- 'environment' => build_diffend_environment,
81
- 'project_id' => project_id,
82
- 'type' => PLATFORM_TYPE,
83
- 'version' => Diffend::VERSION
84
- }.freeze
85
- end
86
-
87
- # Build diffend environment information
88
- #
89
- # @return [String]
90
- def build_diffend_environment
91
- ENV['DIFFEND_ENV'] || 'development'
92
- end
93
-
94
- # Build platform information
95
- #
96
- # @return [Hash]
97
- def build_platform
98
- {
99
- 'bundler' => {
100
- 'version' => Bundler::VERSION
101
- },
102
- 'environment' => build_platform_environment,
103
- 'ruby' => build_platform_ruby,
104
- 'rubygems' => {
105
- 'specification_version' => Gem::Specification::CURRENT_SPECIFICATION_VERSION,
106
- 'version' => Gem::VERSION
107
- }
108
- }.freeze
109
- end
110
-
111
- # Build platform ruby information
112
- #
113
- # @return [Hash]
114
- def build_platform_ruby
115
- if defined?(JRUBY_VERSION)
116
- revision = JRUBY_REVISION.to_s
117
- version = JRUBY_VERSION
118
- else
119
- revision = RUBY_REVISION.to_s
120
- version = RUBY_ENGINE_VERSION
121
- end
122
-
123
- {
124
- 'engine' => RUBY_ENGINE,
125
- 'patchlevel' => RUBY_PATCHLEVEL,
126
- 'release_date' => RUBY_RELEASE_DATE,
127
- 'revision' => revision,
128
- 'version' => version
129
- }
130
- end
131
-
132
- # Build platform environment information
133
- #
134
- # @return [String]
135
- def build_platform_environment
136
- ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
137
- end
138
-
139
- # Build host information
140
- #
141
- # @return [Hash]
142
- def build_host
143
- uname = Etc.uname
144
-
145
- {
146
- 'command' => build_host_command,
147
- 'ips' => build_host_ips,
148
- 'name' => uname[:nodename],
149
- 'system' => {
150
- 'machine' => uname[:machine],
151
- 'name' => uname[:sysname],
152
- 'release' => uname[:release],
153
- 'version' => uname[:version]
154
- },
155
- 'tags' => build_host_tags,
156
- 'user' => Etc.getpwuid(Process.uid).name,
157
- 'pid' => Process.pid
158
- }.freeze
159
- end
160
-
161
- # Build host command information
162
- #
163
- # @return [Hash]
164
- def build_host_command
165
- if File.exist?($PROGRAM_NAME)
166
- if defined?(JRUBY_VERSION)
167
- name = $PROGRAM_NAME.split('/').last.strip
168
- command = "#{name} #{ARGV.join(' ')}"
169
- else
170
- array = `ps -p #{Process.pid} -o command=`.strip.split(' ')
171
- array.shift if array.first.end_with?('bin/ruby')
172
- name = array.shift.split('/').last.strip
173
- command = "#{name} #{array.join(' ')}"
174
- end
175
-
176
- { 'name' => command, 'title' => '' }
177
- else
178
- { 'name' => ARGV.join(' '), 'title' => $PROGRAM_NAME }
179
- end
180
- end
181
-
182
- # Build host ips, except localhost and loopback
183
- #
184
- # @return [Array<String>]
185
- def build_host_ips
186
- Socket.ip_address_list.map do |ip|
187
- next if ip.ipv4_loopback? || ip.ipv6_loopback? || ip.ipv6_linklocal?
188
-
189
- ip.ip_address
190
- end.compact
191
- end
192
-
193
- # Build host tags
194
- #
195
- # @return [Array]
196
- def build_host_tags
197
- tags = []
198
-
199
- if ENV.key?('GITHUB_ACTIONS')
200
- tags << 'ci'
201
- tags << 'ci-github'
202
- end
203
-
204
- if ENV.key?('CIRCLECI')
205
- tags << 'ci'
206
- tags << 'ci-circle'
207
- end
208
-
209
- tags
210
- end
211
-
212
- # Provides diffend command endpoint url
213
- #
214
- # @param command [String] either install or update
215
- # @param project_id [String] diffend project_id
216
- #
217
- # @return [String] diffend endpoint
218
- def commands_url(command, project_id)
219
- return ENV['DIFFEND_COMMAND_URL'] if ENV.key?('DIFFEND_COMMAND_URL')
220
-
221
- "https://my.diffend.io/api/projects/#{project_id}/bundle/#{command}"
222
- end
223
- end
224
- end
225
- end
226
- end
227
- end