diffend 0.2.15

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.
@@ -0,0 +1,200 @@
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
+ DEPENDENCIES = {
17
+ direct: 0,
18
+ dep: 1
19
+ }.freeze
20
+ SOURCES = {
21
+ valid: 0,
22
+ multiple_primary: 1
23
+ }.freeze
24
+ GEM_SOURCES = {
25
+ local: 0,
26
+ gemfile: 1
27
+ }.freeze
28
+
29
+ class << self
30
+ # @param command [String] either install or update
31
+ # @param definition [Bundler::Definition] definition for your source
32
+ def call(command, definition)
33
+ Bundler.ui.silence { definition.resolve_remotely! }
34
+
35
+ instance = new(definition)
36
+
37
+ case command
38
+ when Commands::INSTALL then instance.build_install
39
+ when Commands::UPDATE then instance.build_update
40
+ else
41
+ raise ArgumentError, "invalid command: #{command}"
42
+ end
43
+ end
44
+ end
45
+
46
+ # @param definition [Bundler::Definition] definition for your source
47
+ #
48
+ # @return [Hash] local dependencies
49
+ def initialize(definition)
50
+ @definition = definition
51
+ @direct_dependencies = Hash[definition.dependencies.map { |val| [val.name, val] }]
52
+ @main_source = definition.send(:sources).rubygems_sources.last
53
+ # Support case without Gemfile.lock
54
+ @locked_specs = @definition.locked_gems ? @definition.locked_gems.specs : []
55
+ end
56
+
57
+ def build_install
58
+ hash = build_main
59
+
60
+ @definition.requested_specs.each do |spec|
61
+ next if skip?(spec.source)
62
+
63
+ locked_spec = @locked_specs.find { |s| s.name == spec.name }
64
+
65
+ spec2 = locked_spec || spec
66
+
67
+ hash['dependencies'][spec2.name] = {
68
+ 'platform' => build_spec_platform(spec2),
69
+ 'source' => build_spec_source(spec2),
70
+ 'type' => build_dependency_type(spec2.name),
71
+ 'versions' => build_versions(spec2)
72
+ }
73
+ end
74
+
75
+ hash
76
+ end
77
+
78
+ # @param definition [Bundler::Definition] definition for your source
79
+ def build_update
80
+ hash = build_main
81
+
82
+ @definition.requested_specs.each do |spec|
83
+ next if skip?(spec.source)
84
+
85
+ locked_spec = @locked_specs.find { |s| s.name == spec.name }
86
+
87
+ hash['dependencies'][spec.name] = {
88
+ 'platform' => build_spec_platform(spec),
89
+ 'source' => build_spec_source(spec),
90
+ 'type' => build_dependency_type(spec.name),
91
+ 'versions' => build_versions(spec, locked_spec)
92
+ }
93
+ end
94
+
95
+ hash
96
+ end
97
+
98
+ private
99
+
100
+ def build_main
101
+ {
102
+ 'dependencies' => {},
103
+ 'sources' => build_sources,
104
+ 'plugins' => {},
105
+ 'platforms' => @definition.platforms.map(&:to_s)
106
+ }
107
+ end
108
+
109
+ def build_versions(spec, locked_spec = nil)
110
+ locked_spec ? [locked_spec.version.to_s, spec.version.to_s] : [spec.version.to_s]
111
+ end
112
+
113
+ # @param specs [Array] specs that are direct dependencies
114
+ # @param name [String] spec name
115
+ #
116
+ # @return [Boolean] dependency type
117
+ def build_dependency_type(name)
118
+ @direct_dependencies.key?(name) ? DEPENDENCIES[:direct] : DEPENDENCIES[:dep]
119
+ end
120
+
121
+ def build_spec_platform(spec)
122
+ spec.platform || spec.send(:generic_local_platform)
123
+ end
124
+
125
+ def build_spec_source(spec)
126
+ if @direct_dependencies.key?(spec.name)
127
+ dep_spec = @direct_dependencies[spec.name]
128
+
129
+ if dep_spec.source
130
+ { 'type' => GEM_SOURCES[:gemfile], 'url' => source_name_from_source(dep_spec.source) }
131
+ else
132
+ { 'type' => GEM_SOURCES[:gemfile], 'url' => source_name_from_source(@main_source) }
133
+ end
134
+ else
135
+ if spec.source.respond_to?(:remotes)
136
+ { 'type' => GEM_SOURCES[:gemfile], 'url' => source_name_from_source(spec.source) }
137
+ else
138
+ { 'type' => GEM_SOURCES[:local], 'url' => '' }
139
+ end
140
+ end
141
+ end
142
+
143
+ def source_name_from_source(source)
144
+ source_name(source.remotes.first)
145
+ end
146
+
147
+ def source_name(name)
148
+ name.to_s[0...-1]
149
+ end
150
+
151
+ def build_sources
152
+ sources = @definition.send(:sources).rubygems_sources
153
+ hash = []
154
+
155
+ sources.each do |source|
156
+ type = source.remotes.count > 1 ? SOURCES[:multiple_primary] : SOURCES[:valid]
157
+
158
+ source.remotes.each do |src|
159
+ hash << { 'name' => source_name(src), 'type' => type }
160
+ end
161
+ end
162
+
163
+ hash
164
+ end
165
+
166
+ # Checks if we should skip a source
167
+ #
168
+ # @param source [Bundler::Source::Git, Bundler::Source::Rubygems]
169
+ #
170
+ # @return [Boolean] true if we should skip this source, false otherwise
171
+ def skip?(source)
172
+ return true if git?(source)
173
+ return true if me?(source)
174
+
175
+ false
176
+ end
177
+
178
+ # Checks if it's a git source
179
+ #
180
+ # @param source [Bundler::Source::Git, Bundler::Source::Rubygems]
181
+ #
182
+ # @return [Boolean] true if it's a git source, false otherwise
183
+ def git?(source)
184
+ source.instance_of?(Bundler::Source::Git)
185
+ end
186
+
187
+ # Checks if it's a self source, this happens for repositories that are a gem
188
+ #
189
+ # @param source [Bundler::Source::Path,Bundler::Source::Git,Bundler::Source::Rubygems]
190
+ #
191
+ # @return [Boolean] true if it's a self source, false otherwise
192
+ def me?(source)
193
+ return false unless ME_SOURCES.include?(source.class)
194
+
195
+ source.path.to_s == ME_PATH
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,174 @@
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
+ def call(command, definition)
24
+ config = fetch_config
25
+
26
+ response = Request.call(
27
+ command, payload(command, config&.project_id, definition), config
28
+ )
29
+
30
+ JSON.parse(response.body)
31
+ end
32
+
33
+ # Build diffend, host, packages, and platform specific information
34
+ #
35
+ # @param command [String] either install or update
36
+ # @param project_id [String] diffend project_id
37
+ # @param definition [Bundler::Definition] definition for your source
38
+ #
39
+ # @return [Hash] payload for diffend endpoint
40
+ def payload(command, project_id, definition)
41
+ {
42
+ 'diffend' => build_diffend(project_id),
43
+ 'host' => build_host,
44
+ 'packages' => Local.call(command, definition),
45
+ 'platform' => build_platform
46
+ }.freeze
47
+ end
48
+
49
+ # Build diffend information
50
+ #
51
+ # @param project_id [String, nil] diffend project_id
52
+ #
53
+ # @return [Hash]
54
+ def build_diffend(project_id)
55
+ {
56
+ 'api_version' => API_VERSION,
57
+ 'environment' => build_diffend_environment,
58
+ 'project_id' => project_id,
59
+ 'type' => PLATFORM_TYPE,
60
+ 'version' => Diffend::VERSION
61
+ }.freeze
62
+ end
63
+
64
+ # Build diffend environment information
65
+ #
66
+ # @return [String]
67
+ def build_diffend_environment
68
+ ENV['DIFFEND_ENV'] || 'development'
69
+ end
70
+
71
+ # Build platform information
72
+ #
73
+ # @return [Hash]
74
+ def build_platform
75
+ {
76
+ 'bundler' => {
77
+ 'version' => Bundler::VERSION
78
+ },
79
+ 'environment' => build_platform_environment,
80
+ 'ruby' => build_platform_ruby,
81
+ 'rubygems' => {
82
+ 'specification_version' => Gem::Specification::CURRENT_SPECIFICATION_VERSION,
83
+ 'version' => Gem::VERSION
84
+ }
85
+ }.freeze
86
+ end
87
+
88
+ def build_platform_ruby
89
+ if defined?(JRUBY_VERSION)
90
+ revision = JRUBY_REVISION.to_s
91
+ version = JRUBY_VERSION
92
+ else
93
+ revision = RUBY_REVISION.to_s
94
+ version = RUBY_ENGINE_VERSION
95
+ end
96
+
97
+ {
98
+ 'engine' => RUBY_ENGINE,
99
+ 'patchlevel' => RUBY_PATCHLEVEL,
100
+ 'release_date' => RUBY_RELEASE_DATE,
101
+ 'revision' => revision,
102
+ 'version' => version
103
+ }
104
+ end
105
+
106
+ # Build platform environment information
107
+ #
108
+ # @return [String]
109
+ def build_platform_environment
110
+ ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
111
+ end
112
+
113
+ # Build host information
114
+ #
115
+ # @return [Hash]
116
+ def build_host
117
+ uname = Etc.uname
118
+
119
+ {
120
+ 'command' => { 'name' => '', 'options' => '' },
121
+ 'ips' => build_host_ips,
122
+ 'name' => uname[:nodename],
123
+ 'system' => {
124
+ 'machine' => uname[:machine],
125
+ 'name' => uname[:sysname],
126
+ 'release' => uname[:release],
127
+ 'version' => uname[:version]
128
+ },
129
+ 'tags' => build_host_tags,
130
+ 'user' => Etc.getlogin
131
+ }.freeze
132
+ end
133
+
134
+ def build_host_ips
135
+ Socket.ip_address_list.map do |ip|
136
+ next if ip.ipv4_loopback? || ip.ipv6_loopback? || ip.ipv6_linklocal?
137
+
138
+ ip.ip_address
139
+ end.compact
140
+ end
141
+
142
+ def build_host_tags
143
+ tags = []
144
+
145
+ if ENV.key?('GITHUB_ACTIONS')
146
+ tags << 'ci'
147
+ tags << 'ci-github'
148
+ end
149
+
150
+ if ENV.key?('CIRCLECI')
151
+ tags << 'ci'
152
+ tags << 'ci-circle'
153
+ end
154
+
155
+ tags
156
+ end
157
+
158
+ # Fetch coditsu config file
159
+ #
160
+ # @return [OpenStruct, nil] configuration object
161
+ #
162
+ # @raise [Errors::MissingConfigurationFile] when no config file
163
+ def fetch_config
164
+ Config::Fetcher.call(
165
+ File.expand_path('..', Bundler.bin_path)
166
+ )
167
+ rescue Errors::MissingConfigurationFile
168
+ nil
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'diffend'
4
+
5
+ Diffend.register
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'byebug'
4
+ require 'diffend'
5
+
6
+
7
+ command = 'install'
8
+ project_id = nil
9
+
10
+ gemfile = ARGV[0]
11
+ lockfile = ARGV[1]
12
+
13
+ definition = Bundler::Definition.build(gemfile, lockfile, true)
14
+
15
+ pp Diffend::Voting::Versions::Remote.payload(command, project_id, definition)
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: diffend
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.15
5
+ platform: ruby
6
+ authors:
7
+ - Tomasz Pajor
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIERDCCAqygAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBt0b21l
14
+ ay9EQz1wb2xpc2hnZWVrcy9EQz1jb20wHhcNMjAwNzA3MTY0NjU0WhcNMjEwNzA3
15
+ MTY0NjU0WjAmMSQwIgYDVQQDDBt0b21lay9EQz1wb2xpc2hnZWVrcy9EQz1jb20w
16
+ ggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDPRTvPuofdtL/wFEPOwPUr
17
+ vR0XHzM/ADb2GBuzu6fzgmoxaYXBe8A++0BbgFvK47T04i8bsbXnfkxrkz/nupQ5
18
+ SK2DPgS4HWnADuyBuyBY7LT4O1wwlytdlHtJgQV6NIcbprcOs/ZQKnimZpW9uByu
19
+ FoN3i94pAEQhuzK0S+wWPvSm22+6XGtCuOzyFGdnCJjGUOkCRno5Nx34MWz0NpJ3
20
+ 9Ekkyy8g2cLvBcUdfeSrY7WsJ5cPCNrBs5cMuV426s1dDrhuvsW+sacwwY/4/LBw
21
+ JzEX4/zS+lsVIX+iOoIFGJdeGnpEWqKgWoaskxqseFi661td1n9UaMXxgoaYh/oX
22
+ 3fJOy2jsZFboZ/eJ5rfciXLiCqSERGkEA+QcA2/jC/d77YJ1FfJW9uwJs3kptf4D
23
+ p6h8wuA3T6rN4QrxkGBYzOfUJ2zSQy1cFu0rTZiYdKo9X6BunnxhmUExNng7advu
24
+ qo8IDinyRlqA5+sOLXd4W3AS/RfF2nrayZNa3khTmmUCAwEAAaN9MHswCQYDVR0T
25
+ BAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFHRFOZPwpgOd2m8FIOodOii+OiID
26
+ MCAGA1UdEQQZMBeBFXRvbWVrQHBvbGlzaGdlZWtzLmNvbTAgBgNVHRIEGTAXgRV0
27
+ b21la0Bwb2xpc2hnZWVrcy5jb20wDQYJKoZIhvcNAQELBQADggGBAKWFwYTGZVoy
28
+ Bj3L9lvGOXpz8VWNoptFNHdncpaw1MMhS8UHcPQOUEiExX5ZH7MARy1fBjMXzIh9
29
+ 41ZpCjR+S6uCEpzUcg5Z/kEWa/wOW6tqrX+zfyxFATDI20pYaQWOLepjbDxePFMZ
30
+ GAlIX5UNsze04A+wArXAttZB4oPt6loS1ao0GNdMb+syYMLzZUTW/sY2rm8zP4Mz
31
+ Kt+zjoqMxQ1Jf+EwH+0uq8Tj5BJcmG6mWYM+ljvRbxBwfimoUBUCQe6KIDouF0Og
32
+ uwLMY7X3jSERta4SxyY+iY7qNLsmG370GIGYbHuIiCwubFXt8jiPJZEdPE1xuzVF
33
+ CLsYItzC28UQEWrVe6sJ0Fuqv5VHM6t8jNClkXDwzf95efFlGSCFN4t+/dywVIK8
34
+ 9MmF6uCQa1EjK2p8tYT0MnbHrFkoehxdX4VO9y99GAkhZyJNKPYPtyAUFV27sT2V
35
+ LfCJRk4ifKIN/FUCwDSn8Cz0m6oH265q0p6wdzI6qrWOjP8tGOMBTA==
36
+ -----END CERTIFICATE-----
37
+ date: 2020-07-27 00:00:00.000000000 Z
38
+ dependencies:
39
+ - !ruby/object:Gem::Dependency
40
+ name: bundler
41
+ requirement: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ type: :development
47
+ prerelease: false
48
+ version_requirements: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ - !ruby/object:Gem::Dependency
54
+ name: rake
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ description:
68
+ email:
69
+ - contact@diffend.io
70
+ executables: []
71
+ extensions: []
72
+ extra_rdoc_files: []
73
+ files:
74
+ - ".coditsu/ci.yml"
75
+ - ".diffend.yml"
76
+ - ".github/workflows/ci.yml"
77
+ - ".gitignore"
78
+ - ".rspec"
79
+ - ".ruby-version"
80
+ - Gemfile
81
+ - Gemfile.lock
82
+ - LICENSE
83
+ - README.md
84
+ - bin/bundle
85
+ - bin/byebug
86
+ - bin/htmldiff
87
+ - bin/ldiff
88
+ - bin/rake
89
+ - bin/rspec
90
+ - certs/mensfeld.pem
91
+ - certs/tomaszpajor.pem
92
+ - diffend.gemspec
93
+ - lib/diffend.rb
94
+ - lib/diffend/commands.rb
95
+ - lib/diffend/config/fetcher.rb
96
+ - lib/diffend/config/file_finder.rb
97
+ - lib/diffend/errors.rb
98
+ - lib/diffend/voting.rb
99
+ - lib/diffend/voting/request.rb
100
+ - lib/diffend/voting/versions/local.rb
101
+ - lib/diffend/voting/versions/remote.rb
102
+ - plugins.rb
103
+ - scripts/generate_payload_for_file.rb
104
+ homepage: https://diffend.io
105
+ licenses:
106
+ - Prosperity Public License
107
+ metadata: {}
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubygems_version: 3.1.2
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: OSS supply chain security and management platform.
127
+ test_files: []