diffend 0.2.29 → 0.2.34

Sign up to get free protection for your applications and to get access to all the features.
@@ -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