bundler-audited_update 0.2.0 → 0.3.0
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
- data/bin/audited_bundle_update +2 -1
- data/lib/bundler/audited_update.rb +164 -90
- metadata +7 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 55ee9261d8740b888e04057710f5a0b25b6155ca49fcae312702afba4ff9762b
|
|
4
|
+
data.tar.gz: dc14cf4a44acb080253bf2ae3f369f8b4ae62f948c532a98a1bb36d665795f34
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f256a3a79e6f20e4a5d054fc4e519e364ce902f006be752098ff3d9e17b93887079d16e0a1b7fd869f1de49d1f4e7f8f194abce6a4996c37a45afa492521783
|
|
7
|
+
data.tar.gz: a97bdd6cf867e5f4661741c8f643adb83c5d618fed11ea9aa0d373fdd4f56b19576123c74a0ad432470112546c2be38a9af9b023c61a5b835b07bdfb09e66b4f
|
data/bin/audited_bundle_update
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'bundler'
|
|
2
4
|
require 'bundler/lockfile_parser'
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
5
|
+
require 'bundler/cli'
|
|
6
|
+
require 'bundler/cli/update'
|
|
7
|
+
require 'open-uri'
|
|
6
8
|
require 'net/http'
|
|
7
9
|
require 'json'
|
|
8
10
|
require 'versionomy'
|
|
@@ -10,25 +12,31 @@ require 'launchy'
|
|
|
10
12
|
|
|
11
13
|
module Bundler
|
|
12
14
|
class AuditedUpdate
|
|
15
|
+
CHANGELOG_URLS = {
|
|
16
|
+
"graphql-pro" => "https://github.com/rmosolgo/graphql-ruby/blob/master/CHANGELOG-pro.md",
|
|
17
|
+
"sidekiq" => "https://github.com/mperham/sidekiq/blob/main/Changes.md",
|
|
18
|
+
"faraday" => "https://github.com/lostisland/faraday/releases"
|
|
19
|
+
}
|
|
20
|
+
|
|
13
21
|
def run!
|
|
14
22
|
@before_specs = gem_specs
|
|
15
23
|
bundle_update
|
|
16
24
|
@after_specs = gem_specs
|
|
17
25
|
|
|
18
|
-
@output =
|
|
26
|
+
@output = ''
|
|
19
27
|
@output += "# Gem Changes\n"
|
|
20
28
|
@output += "\n"
|
|
21
29
|
|
|
22
|
-
output_gems(
|
|
23
|
-
output_gems(
|
|
30
|
+
output_gems('Added Gems', added_gems)
|
|
31
|
+
output_gems('Removed Gems', removed_gems)
|
|
24
32
|
output_changed_gems(changed_gems)
|
|
25
33
|
|
|
26
34
|
puts "\n\n\n\n\n"
|
|
27
35
|
|
|
28
|
-
puts
|
|
29
|
-
puts
|
|
30
|
-
puts
|
|
31
|
-
puts
|
|
36
|
+
puts '--------------------------------'
|
|
37
|
+
puts 'Upgraded Gems'
|
|
38
|
+
puts '(Generated with bundler-audited_updated https://github.com/bmulholland/audited_bundle_update)'
|
|
39
|
+
puts '--------------------------------'
|
|
32
40
|
|
|
33
41
|
puts @output
|
|
34
42
|
end
|
|
@@ -46,16 +54,20 @@ module Bundler
|
|
|
46
54
|
def output_changed_gems(gems)
|
|
47
55
|
return if gems.empty?
|
|
48
56
|
|
|
49
|
-
major_upgrades = gems.
|
|
50
|
-
minor_upgrades = gems.select
|
|
51
|
-
|
|
57
|
+
major_upgrades = gems.reject { |_, versions| versions[:before].major == versions[:after].major }
|
|
58
|
+
minor_upgrades = gems.select do |name, versions|
|
|
59
|
+
!major_upgrades.keys.include?(name) && versions[:before].minor != versions[:after].minor
|
|
60
|
+
end
|
|
61
|
+
point_upgrades = gems.reject do |name, _|
|
|
62
|
+
major_upgrades.keys.include?(name) || minor_upgrades.keys.include?(name)
|
|
63
|
+
end
|
|
52
64
|
|
|
53
65
|
@output += "## Upgraded Gems\n"
|
|
54
66
|
@output += "\n"
|
|
55
67
|
|
|
56
|
-
output_changed_gems_section(
|
|
57
|
-
output_changed_gems_section(
|
|
58
|
-
output_changed_gems_section(
|
|
68
|
+
output_changed_gems_section('Major', major_upgrades)
|
|
69
|
+
output_changed_gems_section('Minor', minor_upgrades)
|
|
70
|
+
output_changed_gems_section('Point', point_upgrades)
|
|
59
71
|
|
|
60
72
|
@output += "\n"
|
|
61
73
|
end
|
|
@@ -69,82 +81,137 @@ module Bundler
|
|
|
69
81
|
end
|
|
70
82
|
|
|
71
83
|
def gem_output(name, version)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
84
|
+
# gems that are continuously released and therefore have no helpful
|
|
85
|
+
# changelog
|
|
86
|
+
continuously_released_gems = %w[aws-partitions aws-sdk-core sorbet sorbet-runtime
|
|
87
|
+
sorbet-static-and-runtime]
|
|
88
|
+
|
|
89
|
+
if continuously_released_gems.include?(name)
|
|
90
|
+
puts "\n\n\n"
|
|
91
|
+
puts '--------------------------------'
|
|
92
|
+
puts "#{name} updated"
|
|
93
|
+
puts '--------------------------------'
|
|
94
|
+
|
|
95
|
+
if version.is_a? Hash
|
|
96
|
+
info = gem_info(name, version[:after])
|
|
97
|
+
version_string = "#{version[:before]} -> #{version[:after]}"
|
|
98
|
+
else
|
|
99
|
+
info = gem_info(name, version)
|
|
100
|
+
version_string = version
|
|
101
|
+
end
|
|
75
102
|
|
|
76
103
|
guessed_source = gem_source_url(info)
|
|
104
|
+
change_detail = guessed_source
|
|
77
105
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
elsif answer == "n"
|
|
100
|
-
impact = "No impact"
|
|
101
|
-
elsif answer == "o"
|
|
102
|
-
Launchy.open(changelog_url)
|
|
103
|
-
else
|
|
104
|
-
puts "Invalid answer"
|
|
105
|
-
end
|
|
106
|
-
end
|
|
106
|
+
puts 'This gem is continuously updated, with no meaningful changelog.'
|
|
107
|
+
|
|
108
|
+
impact = nil
|
|
109
|
+
while impact.nil?
|
|
110
|
+
puts "Does #{name} #{version_string} impact your application? (y/n/[o]pen in browser)"
|
|
111
|
+
answer = gets
|
|
112
|
+
answer = answer.downcase.strip
|
|
113
|
+
case answer
|
|
114
|
+
when 'y'
|
|
115
|
+
puts "What's a short description of the impact?"
|
|
116
|
+
impact = gets
|
|
117
|
+
when 'n'
|
|
118
|
+
impact = 'No impact'
|
|
119
|
+
when 'o'
|
|
120
|
+
Launchy.open(guessed_source)
|
|
121
|
+
else
|
|
122
|
+
puts 'Invalid answer'
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
change_detail = impact
|
|
107
127
|
|
|
108
|
-
|
|
128
|
+
elsif version.is_a? Hash
|
|
129
|
+
version_string = "#{version[:before]} -> #{version[:after]}"
|
|
130
|
+
info = gem_info(name, version[:after])
|
|
131
|
+
|
|
132
|
+
changelog_text, changelog_url = guess_changelog(
|
|
133
|
+
name, gem_source_url(info)
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
if changelog_text && !changelog_text.empty?
|
|
137
|
+
puts "\n\n\n"
|
|
138
|
+
puts '--------------------------------'
|
|
139
|
+
puts "#{name} changes from #{version_string}"
|
|
140
|
+
puts '--------------------------------'
|
|
141
|
+
|
|
142
|
+
# Output the changelog text from top until the line that contains the previous version
|
|
143
|
+
changelog_output = changelog_text.split(/^.*#{Regexp.escape(version[:before].to_s)}/, 2).first
|
|
144
|
+
|
|
145
|
+
# Max 200 lines
|
|
146
|
+
changelog_output = changelog_output.lines.to_a[0...200].join
|
|
147
|
+
|
|
148
|
+
puts changelog_output
|
|
149
|
+
impact = nil
|
|
150
|
+
while impact.nil?
|
|
151
|
+
puts "Does #{name} #{version_string} impact your application? (y/n/[o]pen in browser)"
|
|
152
|
+
answer = gets
|
|
153
|
+
answer = answer.downcase.strip
|
|
154
|
+
case answer
|
|
155
|
+
when 'y'
|
|
156
|
+
puts "What's a short description of the impact?"
|
|
157
|
+
impact = gets
|
|
158
|
+
when 'n'
|
|
159
|
+
impact = 'No impact'
|
|
160
|
+
when 'o'
|
|
161
|
+
Launchy.open(changelog_url)
|
|
162
|
+
else
|
|
163
|
+
puts 'Invalid answer'
|
|
164
|
+
end
|
|
109
165
|
end
|
|
166
|
+
|
|
167
|
+
change_detail = impact
|
|
110
168
|
end
|
|
111
169
|
|
|
112
170
|
else
|
|
113
171
|
version_string = version
|
|
114
172
|
info = gem_info(name, version)
|
|
115
|
-
|
|
116
|
-
change_detail = guessed_source
|
|
173
|
+
change_detail = gem_source_url(info)
|
|
117
174
|
end
|
|
118
175
|
|
|
119
|
-
change_detail ||=
|
|
120
|
-
|
|
176
|
+
change_detail ||= 'Unsupported source URL, cannot search for changelog'
|
|
121
177
|
|
|
122
178
|
@output += "* #{name} (#{version_string}): #{change_detail}\n"
|
|
123
179
|
end
|
|
124
180
|
|
|
125
|
-
def guess_changelog(root_url)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
181
|
+
def guess_changelog(name, root_url)
|
|
182
|
+
# There are always going to be exceptions, so just hardcode those.
|
|
183
|
+
root_url = CHANGELOG_URLS[name] if CHANGELOG_URLS.key?(name)
|
|
184
|
+
|
|
185
|
+
return nil unless root_url
|
|
186
|
+
|
|
187
|
+
filenames = %w[
|
|
188
|
+
CHANGELOG
|
|
189
|
+
CHANGELOG.md
|
|
190
|
+
Changelog
|
|
191
|
+
Changelog.md
|
|
192
|
+
History
|
|
193
|
+
History.md
|
|
194
|
+
HISTORY.md
|
|
195
|
+
History.rdoc
|
|
196
|
+
Changes
|
|
197
|
+
CHANGES
|
|
198
|
+
CHANGES.md
|
|
199
|
+
NEWS
|
|
200
|
+
]
|
|
140
201
|
changelog_text = nil
|
|
141
202
|
changelog_url = nil
|
|
142
203
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
204
|
+
root_url_is_releases_page = root_url.end_with?("/releases")
|
|
205
|
+
|
|
206
|
+
changelog_url = root_url if root_url_is_releases_page
|
|
207
|
+
|
|
208
|
+
unless changelog_url
|
|
209
|
+
filenames.each do |filename|
|
|
210
|
+
changelog_text = try_changelog_url(root_url, filename)
|
|
211
|
+
if changelog_text
|
|
212
|
+
changelog_url = changelog_url_for(root_url, filename)
|
|
213
|
+
break
|
|
214
|
+
end
|
|
148
215
|
end
|
|
149
216
|
end
|
|
150
217
|
|
|
@@ -154,7 +221,7 @@ module Bundler
|
|
|
154
221
|
end
|
|
155
222
|
|
|
156
223
|
unless changelog_text
|
|
157
|
-
changelog_text =
|
|
224
|
+
changelog_text = 'Could not find changelog URL, try manually'
|
|
158
225
|
changelog_url = root_url
|
|
159
226
|
end
|
|
160
227
|
|
|
@@ -162,8 +229,10 @@ module Bundler
|
|
|
162
229
|
end
|
|
163
230
|
|
|
164
231
|
def gem_source_url(info)
|
|
165
|
-
|
|
166
|
-
|
|
232
|
+
return nil unless info
|
|
233
|
+
|
|
234
|
+
source_url_guess = info['source_code_uri'] || info['homepage_uri']
|
|
235
|
+
if source_url_guess&.include?('github.com')
|
|
167
236
|
source_url_guess
|
|
168
237
|
else
|
|
169
238
|
# Unsupported source URL
|
|
@@ -172,22 +241,22 @@ module Bundler
|
|
|
172
241
|
end
|
|
173
242
|
|
|
174
243
|
def added_gems
|
|
175
|
-
@after_specs.reject {|spec| @before_specs.map(&:name).include?(spec.name) }
|
|
244
|
+
@after_specs.reject { |spec| @before_specs.map(&:name).include?(spec.name) }
|
|
176
245
|
end
|
|
177
246
|
|
|
178
247
|
def removed_gems
|
|
179
|
-
@before_specs.reject {|spec| @after_specs.map(&:name).include?(spec.name) }
|
|
248
|
+
@before_specs.reject { |spec| @after_specs.map(&:name).include?(spec.name) }
|
|
180
249
|
end
|
|
181
250
|
|
|
182
251
|
def changed_gems
|
|
183
252
|
gems = @after_specs.reject do |after_spec|
|
|
184
|
-
before_spec = @before_specs.find {|before_spec| before_spec && before_spec.name == after_spec.name }
|
|
253
|
+
before_spec = @before_specs.find { |before_spec| before_spec && before_spec.name == after_spec.name }
|
|
185
254
|
!before_spec || before_spec.version == after_spec.version
|
|
186
255
|
end
|
|
187
256
|
|
|
188
257
|
gems.map! do |the_gem|
|
|
189
|
-
before_gem = @before_specs.find {|before_spec| before_spec.name == the_gem.name }
|
|
190
|
-
after_gem = @after_specs.find {|after_spec| after_spec.name == the_gem.name }
|
|
258
|
+
before_gem = @before_specs.find { |before_spec| before_spec.name == the_gem.name }
|
|
259
|
+
after_gem = @after_specs.find { |after_spec| after_spec.name == the_gem.name }
|
|
191
260
|
versions = {
|
|
192
261
|
before: Versionomy.parse(before_gem.version.to_s),
|
|
193
262
|
after: Versionomy.parse(after_gem.version.to_s)
|
|
@@ -199,42 +268,47 @@ module Bundler
|
|
|
199
268
|
end
|
|
200
269
|
|
|
201
270
|
def github_releases_url(source_root)
|
|
202
|
-
api_source_root = source_root.gsub(
|
|
203
|
-
"#{api_source_root}/releases"
|
|
271
|
+
api_source_root = source_root.gsub('github.com/', 'api.github.com/repos/')
|
|
272
|
+
api_source_root.end_with?("/releases") ? api_source_root : "#{api_source_root}/releases"
|
|
204
273
|
end
|
|
205
274
|
|
|
206
275
|
def github_releases_bodies(source_root)
|
|
207
276
|
response = ::URI.parse(github_releases_url(source_root)).read
|
|
208
277
|
releases = JSON.parse(response)
|
|
209
|
-
release_notes =
|
|
278
|
+
release_notes = ''
|
|
210
279
|
releases.each do |release|
|
|
211
|
-
next unless release[
|
|
212
|
-
|
|
280
|
+
next unless release['body']
|
|
281
|
+
|
|
282
|
+
release_notes += release['name']
|
|
213
283
|
release_notes += "\n"
|
|
214
|
-
release_notes += release[
|
|
284
|
+
release_notes += release['body']
|
|
215
285
|
release_notes += "\n"
|
|
216
286
|
release_notes += "\n"
|
|
217
287
|
end
|
|
218
288
|
release_notes
|
|
219
289
|
rescue OpenURI::HTTPError
|
|
220
|
-
|
|
290
|
+
nil
|
|
221
291
|
end
|
|
222
292
|
|
|
223
293
|
def changelog_url_for(source_root, filename)
|
|
224
|
-
raw_source_root = source_root.gsub(
|
|
294
|
+
raw_source_root = source_root.gsub('github.com', 'raw.githubusercontent.com')
|
|
225
295
|
url = "#{raw_source_root}/master/#{filename}"
|
|
226
296
|
end
|
|
227
297
|
|
|
228
298
|
def try_changelog_url(source_root, filename)
|
|
229
299
|
::URI.parse(changelog_url_for(source_root, filename)).read
|
|
230
300
|
rescue OpenURI::HTTPError
|
|
231
|
-
|
|
301
|
+
nil
|
|
232
302
|
end
|
|
233
303
|
|
|
234
304
|
def gem_info(name, version)
|
|
235
305
|
gem_url = "https://rubygems.org/api/v2/rubygems/#{name}/versions/#{version}"
|
|
236
306
|
response = ::URI.parse(gem_url).read
|
|
237
307
|
JSON.parse(response)
|
|
308
|
+
rescue OpenURI::HTTPError => e
|
|
309
|
+
# return nil for 404 - which means the gem doens't exist on rubygems,
|
|
310
|
+
# probably private
|
|
311
|
+
raise unless e.message.include?('404')
|
|
238
312
|
end
|
|
239
313
|
|
|
240
314
|
def gem_specs
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bundler-audited_update
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brendan Mulholland
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-08-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -39,7 +39,7 @@ dependencies:
|
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: launchy
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - ">="
|
|
@@ -53,7 +53,7 @@ dependencies:
|
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
56
|
+
name: versionomy
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
59
|
- - ">="
|
|
@@ -79,7 +79,8 @@ files:
|
|
|
79
79
|
homepage: http://rubygems.org/gems/bundler-audited_update
|
|
80
80
|
licenses:
|
|
81
81
|
- MIT
|
|
82
|
-
metadata:
|
|
82
|
+
metadata:
|
|
83
|
+
rubygems_mfa_required: 'true'
|
|
83
84
|
post_install_message:
|
|
84
85
|
rdoc_options: []
|
|
85
86
|
require_paths:
|
|
@@ -95,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
95
96
|
- !ruby/object:Gem::Version
|
|
96
97
|
version: '0'
|
|
97
98
|
requirements: []
|
|
98
|
-
rubygems_version: 3.
|
|
99
|
+
rubygems_version: 3.3.7
|
|
99
100
|
signing_key:
|
|
100
101
|
specification_version: 4
|
|
101
102
|
summary: Streamlined bundler audit with Changelog detection and summary ouput
|