diffend 0.2.15

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